Skip to content

Commit baf1494

Browse files
bors[bot]iDawer
andauthored
Merge #9807
9807: Implicit `Sized` bounds r=iDawer a=iDawer This should close #8984 `hir_ty`: - Type parameters, associated types and `impl Trait` are `Sized` by deafault except `Self` in a trait. - Implicit `Sized` bound is added to end of predicate list. It does not check if such bound is present already. Also it does not track the bound is implicit. - Allowed ambiguous unsize coercion if Chalk returns definite guidance. - Allowed ambiguous autoderef if Chalk returns definite guidance. `hir_def`: - `ItemTree` pretty printing shows `?Sized` bounds. `HirDisplay`: - `impl Trait` with weird bounds rendered correctly. - `Sized`/`?Sized` bounds are not shown if they are default. ### Perf `./target/rust-analyzer-baseline_8a843113 -q analysis-stats --memory-usage .` ``` Database loaded: 1.63s, 287minstr, 91mb crates: 38, mods: 741, decls: 15914, fns: 11835 Item Collection: 26.80s, 73ginstr, 338mb exprs: 318994, ??ty: 398 (0%), ?ty: 435 (0%), !ty: 174 Inference: 50.28s, 116ginstr, 516mb Total: 77.08s, 189ginstr, 855mb ``` `./target/rust-analyzer-sized-fixed_ambig_coercion-de074fe6 -q analysis-stats --memory-usage .` ``` Database loaded: 1.63s, 287minstr, 91mb crates: 38, mods: 741, decls: 15914, fns: 11835 Item Collection: 26.95s, 73ginstr, 338mb exprs: 318994, ??ty: 398 (0%), ?ty: 435 (0%), !ty: 166 Inference: 96.39s, 234ginstr, 543mb Total: 123.33s, 307ginstr, 881mb ``` Co-authored-by: Dawer <7803845+iDawer@users.noreply.github.com>
2 parents c619cb1 + 6c366ad commit baf1494

File tree

20 files changed

+620
-104
lines changed

20 files changed

+620
-104
lines changed

crates/hir/src/display.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use hir_def::{
77
};
88
use hir_ty::display::{
99
write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError,
10-
HirFormatter,
10+
HirFormatter, SizedByDefault,
1111
};
1212
use hir_ty::Interner;
1313
use syntax::ast::{self, NameOwner};
@@ -93,7 +93,7 @@ impl HirDisplay for Function {
9393
} else {
9494
match &*data.ret_type {
9595
TypeRef::ImplTrait(bounds) => match bounds[0].as_ref() {
96-
TypeBound::Path(path) => {
96+
TypeBound::Path(path, _) => {
9797
path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings
9898
[0]
9999
.type_ref
@@ -239,7 +239,8 @@ impl HirDisplay for TypeParam {
239239
let predicates =
240240
bounds.iter().cloned().map(|b| b.substitute(&Interner, &substs)).collect::<Vec<_>>();
241241
if !(predicates.is_empty() || f.omit_verbose_types()) {
242-
write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?;
242+
let default_sized = SizedByDefault::Sized { anchor: self.module(f.db).krate().id };
243+
write_bounds_like_dyn_trait_with_prefix(":", &predicates, default_sized, f)?;
243244
}
244245
Ok(())
245246
}

crates/hir_def/src/generics.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,10 +338,6 @@ impl GenericParams {
338338
hrtb_lifetimes: Option<&Box<[Name]>>,
339339
target: Either<TypeRef, LifetimeRef>,
340340
) {
341-
if bound.question_mark_token().is_some() {
342-
// FIXME: remove this bound
343-
return;
344-
}
345341
let bound = TypeBound::from_ast(lower_ctx, bound);
346342
let predicate = match (target, bound) {
347343
(Either::Left(type_ref), bound) => match hrtb_lifetimes {

crates/hir_def/src/item_tree/lower.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use syntax::{
1010

1111
use crate::{
1212
generics::{GenericParams, TypeParamData, TypeParamProvenance},
13-
type_ref::{LifetimeRef, TraitRef},
13+
type_ref::{LifetimeRef, TraitBoundModifier, TraitRef},
1414
};
1515

1616
use super::*;
@@ -369,7 +369,7 @@ impl<'a> Ctx<'a> {
369369
let (ret_type, async_ret_type) = if func.async_token().is_some() {
370370
let async_ret_type = ret_type.clone();
371371
let future_impl = desugar_future_path(ret_type);
372-
let ty_bound = Interned::new(TypeBound::Path(future_impl));
372+
let ty_bound = Interned::new(TypeBound::Path(future_impl, TraitBoundModifier::None));
373373
(TypeRef::ImplTrait(vec![ty_bound]), Some(async_ret_type))
374374
} else {
375375
(ret_type, None)

crates/hir_def/src/item_tree/pretty.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::{
88
attr::RawAttrs,
99
generics::{WherePredicate, WherePredicateTypeTarget},
1010
path::GenericArg,
11+
type_ref::TraitBoundModifier,
1112
visibility::RawVisibility,
1213
};
1314

@@ -543,7 +544,13 @@ impl<'a> Printer<'a> {
543544
}
544545

545546
match bound.as_ref() {
546-
TypeBound::Path(path) => self.print_path(path),
547+
TypeBound::Path(path, modifier) => {
548+
match modifier {
549+
TraitBoundModifier::None => (),
550+
TraitBoundModifier::Maybe => w!(self, "?"),
551+
}
552+
self.print_path(path)
553+
}
547554
TypeBound::ForLifetime(lifetimes, path) => {
548555
w!(self, "for<{}> ", lifetimes.iter().format(", "));
549556
self.print_path(path);

crates/hir_def/src/item_tree/tests.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ struct S<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> {
304304
field: &'a &'b T,
305305
}
306306
307-
struct Tuple<T: Copy>(T);
307+
struct Tuple<T: Copy, U: ?Sized>(T, U);
308308
309309
impl<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> S<'a, 'b, T, K> {
310310
fn f<G: 'a>(arg: impl Copy) -> impl Copy {}
@@ -325,11 +325,13 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
325325
pub(self) field: &'a &'b T,
326326
}
327327
328-
pub(self) struct Tuple<T>(
328+
pub(self) struct Tuple<T, U>(
329329
pub(self) 0: T,
330+
pub(self) 1: U,
330331
)
331332
where
332-
T: Copy;
333+
T: Copy,
334+
U: ?Sized;
333335
334336
impl<'a, 'b, T, const K: u8> S<'a, 'b, T, K>
335337
where

crates/hir_def/src/type_ref.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,20 @@ impl LifetimeRef {
118118

119119
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
120120
pub enum TypeBound {
121-
Path(Path),
121+
Path(Path, TraitBoundModifier),
122122
ForLifetime(Box<[Name]>, Path),
123123
Lifetime(LifetimeRef),
124124
Error,
125125
}
126126

127+
/// A modifier on a bound, currently this is only used for `?Sized`, where the
128+
/// modifier is `Maybe`.
129+
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
130+
pub enum TraitBoundModifier {
131+
None,
132+
Maybe,
133+
}
134+
127135
impl TypeRef {
128136
/// Converts an `ast::TypeRef` to a `hir::TypeRef`.
129137
pub fn from_ast(ctx: &LowerCtx, node: ast::Type) -> Self {
@@ -233,7 +241,7 @@ impl TypeRef {
233241
TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
234242
for bound in bounds {
235243
match bound.as_ref() {
236-
TypeBound::Path(path) | TypeBound::ForLifetime(_, path) => {
244+
TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
237245
go_path(path, f)
238246
}
239247
TypeBound::Lifetime(_) | TypeBound::Error => (),
@@ -265,7 +273,7 @@ impl TypeRef {
265273
}
266274
for bound in &binding.bounds {
267275
match bound.as_ref() {
268-
TypeBound::Path(path) | TypeBound::ForLifetime(_, path) => {
276+
TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
269277
go_path(path, f)
270278
}
271279
TypeBound::Lifetime(_) | TypeBound::Error => (),
@@ -295,7 +303,13 @@ impl TypeBound {
295303

296304
match node.kind() {
297305
ast::TypeBoundKind::PathType(path_type) => {
298-
lower_path_type(path_type).map(TypeBound::Path).unwrap_or(TypeBound::Error)
306+
let m = match node.question_mark_token() {
307+
Some(_) => TraitBoundModifier::Maybe,
308+
None => TraitBoundModifier::None,
309+
};
310+
lower_path_type(path_type)
311+
.map(|p| TypeBound::Path(p, m))
312+
.unwrap_or(TypeBound::Error)
299313
}
300314
ast::TypeBoundKind::ForType(for_type) => {
301315
let lt_refs = match for_type.generic_param_list() {
@@ -320,9 +334,10 @@ impl TypeBound {
320334
}
321335
}
322336

323-
pub fn as_path(&self) -> Option<&Path> {
337+
pub fn as_path(&self) -> Option<(&Path, &TraitBoundModifier)> {
324338
match self {
325-
TypeBound::Path(p) | TypeBound::ForLifetime(_, p) => Some(p),
339+
TypeBound::Path(p, m) => Some((p, m)),
340+
TypeBound::ForLifetime(_, p) => Some((p, &TraitBoundModifier::None)),
326341
TypeBound::Lifetime(_) | TypeBound::Error => None,
327342
}
328343
}

crates/hir_ty/src/autoderef.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ use log::{info, warn};
1414

1515
use crate::{
1616
db::HirDatabase, static_lifetime, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds,
17-
DebruijnIndex, Environment, InEnvironment, Interner, ProjectionTyExt, Solution, Substitution,
18-
Ty, TyBuilder, TyKind,
17+
ConstrainedSubst, DebruijnIndex, Environment, Guidance, InEnvironment, Interner,
18+
ProjectionTyExt, Solution, Substitution, Ty, TyBuilder, TyKind,
1919
};
2020

2121
const AUTODEREF_RECURSION_LIMIT: Limit = Limit::new(10);
@@ -187,7 +187,8 @@ fn deref_by_trait(
187187
let solution = db.trait_solve(krate, canonical)?;
188188

189189
match &solution {
190-
Solution::Unique(vars) => {
190+
Solution::Unique(Canonical { value: ConstrainedSubst { subst, .. }, binders })
191+
| Solution::Ambig(Guidance::Definite(Canonical { value: subst, binders })) => {
191192
// FIXME: vars may contain solutions for any inference variables
192193
// that happened to be inside ty. To correctly handle these, we
193194
// would have to pass the solution up to the inference context, but
@@ -203,8 +204,8 @@ fn deref_by_trait(
203204
// assumptions will be broken. We would need to properly introduce
204205
// new variables in that case
205206

206-
for i in 1..vars.binders.len(&Interner) {
207-
if vars.value.subst.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner)
207+
for i in 1..binders.len(&Interner) {
208+
if subst.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner)
208209
!= &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
209210
{
210211
warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution);
@@ -214,13 +215,11 @@ fn deref_by_trait(
214215
// FIXME: we remove lifetime variables here since they can confuse
215216
// the method resolution code later
216217
Some(fixup_lifetime_variables(Canonical {
217-
value: vars
218-
.value
219-
.subst
220-
.at(&Interner, vars.value.subst.len(&Interner) - 1)
218+
value: subst
219+
.at(&Interner, subst.len(&Interner) - 1)
221220
.assert_ty_ref(&Interner)
222221
.clone(),
223-
binders: vars.binders.clone(),
222+
binders: binders.clone(),
224223
}))
225224
}
226225
Solution::Ambig(_) => {

crates/hir_ty/src/chalk_db.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,13 +412,28 @@ pub(crate) fn associated_ty_data_query(
412412
.with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable);
413413
let self_ty =
414414
TyKind::BoundVar(BoundVar::new(crate::DebruijnIndex::INNERMOST, 0)).intern(&Interner);
415-
let bounds = type_alias_data
415+
let mut bounds: Vec<_> = type_alias_data
416416
.bounds
417417
.iter()
418418
.flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false))
419419
.filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty))
420420
.collect();
421421

422+
if !ctx.unsized_types.borrow().contains(&self_ty) {
423+
let sized_trait = resolver
424+
.krate()
425+
.and_then(|krate| db.lang_item(krate, "sized".into()))
426+
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
427+
let sized_bound = sized_trait.into_iter().map(|sized_trait| {
428+
let trait_bound =
429+
rust_ir::TraitBound { trait_id: sized_trait, args_no_self: Default::default() };
430+
let inline_bound = rust_ir::InlineBound::TraitBound(trait_bound);
431+
chalk_ir::Binders::empty(&Interner, inline_bound)
432+
});
433+
bounds.extend(sized_bound);
434+
bounds.shrink_to_fit();
435+
}
436+
422437
// FIXME: Re-enable where clauses on associated types when an upstream chalk bug is fixed.
423438
// (rust-analyzer#9052)
424439
// let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);

0 commit comments

Comments
 (0)