From b217e9cc50a5fb3a85f4db162b3217e4e7f007c5 Mon Sep 17 00:00:00 2001 From: Dawer <7803845+iDawer@users.noreply.github.com> Date: Sat, 12 Jun 2021 21:47:07 +0500 Subject: [PATCH] add implicit Sized bound to associated types --- crates/hir_ty/src/chalk_db.rs | 17 ++++++++++- crates/hir_ty/src/lower.rs | 7 ++--- crates/hir_ty/src/tests/method_resolution.rs | 28 +++++++++++++++++ crates/hir_ty/src/tests/traits.rs | 32 ++++++++++++++++++++ 4 files changed, 79 insertions(+), 5 deletions(-) diff --git a/crates/hir_ty/src/chalk_db.rs b/crates/hir_ty/src/chalk_db.rs index a55b99de042..333d934ed37 100644 --- a/crates/hir_ty/src/chalk_db.rs +++ b/crates/hir_ty/src/chalk_db.rs @@ -412,13 +412,28 @@ pub(crate) fn associated_ty_data_query( .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable); let self_ty = TyKind::BoundVar(BoundVar::new(crate::DebruijnIndex::INNERMOST, 0)).intern(&Interner); - let bounds = type_alias_data + let mut bounds: Vec<_> = type_alias_data .bounds .iter() .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false)) .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) .collect(); + if !ctx.unsized_types.borrow().contains(&self_ty) { + let sized_trait = resolver + .krate() + .and_then(|krate| db.lang_item(krate, "sized".into())) + .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id)); + let sized_bound = sized_trait.into_iter().map(|sized_trait| { + let trait_bound = + rust_ir::TraitBound { trait_id: sized_trait, args_no_self: Default::default() }; + let inline_bound = rust_ir::InlineBound::TraitBound(trait_bound); + chalk_ir::Binders::empty(&Interner, inline_bound) + }); + bounds.extend(sized_bound); + bounds.shrink_to_fit(); + } + // FIXME: Re-enable where clauses on associated types when an upstream chalk bug is fixed. // (rust-analyzer#9052) // let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 3a9e3012319..4544c613893 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -66,8 +66,8 @@ pub struct TyLoweringContext<'a> { /// Splitting this up would be a possible fix. opaque_type_data: RefCell>, expander: RefCell>, - /// Keeps tracking types with explicit `?Sized` bounds. - unsized_types: RefCell>, + /// Tracks types with explicit `?Sized` bounds. + pub(crate) unsized_types: RefCell>, } impl<'a> TyLoweringContext<'a> { @@ -796,7 +796,7 @@ pub(crate) fn lower_type_bound( .and_then(|krate| self.db.lang_item(krate, "sized".into())) .and_then(|lang_item| lang_item.as_trait()); // Don't lower associated type bindings as the only possible relaxed trait bound - // `?Sized` has none of them. + // `?Sized` has no of them. // If we got another trait here ignore the bound completely. let trait_id = self .lower_trait_ref_from_path(path, Some(self_ty.clone())) @@ -996,7 +996,6 @@ pub(crate) fn generic_predicates_for_param_query( let ctx = TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); let generics = generics(db.upcast(), param_id.parent); - // TODO(iDawer): add implicitly sized clauses? resolver .where_predicates_in_scope() // we have to filter out all other predicates *first*, before attempting to lower them diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs index 90eee77422e..aa4234969b9 100644 --- a/crates/hir_ty/src/tests/method_resolution.rs +++ b/crates/hir_ty/src/tests/method_resolution.rs @@ -1312,3 +1312,31 @@ fn into_iter(self) -> Self::Out { loop {} } "#, ); } + +#[test] +fn sized_blanket_impl() { + check_infer( + r#" +#[lang = "sized"] +pub trait Sized {} + +trait Foo { fn foo() -> u8; } +impl Foo for T {} +fn f() { + u32::foo; + S::foo; + T::foo; + U::foo; + <[u32]>::foo; +} +"#, + expect![[r#" + 127..198 '{ ...foo; }': () + 133..141 'u32::foo': fn foo() -> u8 + 147..153 'S::foo': fn foo() -> u8 + 159..165 'T::foo': fn foo() -> u8 + 171..177 'U::foo': {unknown} + 183..195 '<[u32]>::foo': {unknown} + "#]], + ); +} diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index d5d0173ec11..dfcc4608c16 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs @@ -3515,3 +3515,35 @@ fn foo(&self) -> S1 { S1 } "#, ); } + +#[test] +fn associated_type_sized_bounds() { + check_infer( + r#" +#[lang = "sized"] +pub trait Sized {} + +struct Yes; +trait IsSized { const IS_SIZED: Yes; } +impl IsSized for T { const IS_SIZED: Yes = Yes; } + +trait Foo { + type Explicit: Sized; + type Implicit; + type Relaxed: ?Sized; +} +fn f() { + F::Explicit::IS_SIZED; + F::Implicit::IS_SIZED; + F::Relaxed::IS_SIZED; +} +"#, + expect![[r#" + 142..145 'Yes': Yes + 250..333 '{ ...ZED; }': () + 256..277 'F::Exp..._SIZED': Yes + 283..304 'F::Imp..._SIZED': Yes + 310..330 'F::Rel..._SIZED': {unknown} + "#]], + ); +}