Skip to content

Commit b217e9c

Browse files
committed
add implicit Sized bound to associated types
1 parent 8f2a040 commit b217e9c

File tree

4 files changed

+79
-5
lines changed

4 files changed

+79
-5
lines changed

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);

crates/hir_ty/src/lower.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ pub struct TyLoweringContext<'a> {
6666
/// Splitting this up would be a possible fix.
6767
opaque_type_data: RefCell<Vec<ReturnTypeImplTrait>>,
6868
expander: RefCell<Option<Expander>>,
69-
/// Keeps tracking types with explicit `?Sized` bounds.
70-
unsized_types: RefCell<FxHashSet<Ty>>,
69+
/// Tracks types with explicit `?Sized` bounds.
70+
pub(crate) unsized_types: RefCell<FxHashSet<Ty>>,
7171
}
7272

7373
impl<'a> TyLoweringContext<'a> {
@@ -796,7 +796,7 @@ impl<'a> TyLoweringContext<'a> {
796796
.and_then(|krate| self.db.lang_item(krate, "sized".into()))
797797
.and_then(|lang_item| lang_item.as_trait());
798798
// Don't lower associated type bindings as the only possible relaxed trait bound
799-
// `?Sized` has none of them.
799+
// `?Sized` has no of them.
800800
// If we got another trait here ignore the bound completely.
801801
let trait_id = self
802802
.lower_trait_ref_from_path(path, Some(self_ty.clone()))
@@ -996,7 +996,6 @@ pub(crate) fn generic_predicates_for_param_query(
996996
let ctx =
997997
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
998998
let generics = generics(db.upcast(), param_id.parent);
999-
// TODO(iDawer): add implicitly sized clauses?
1000999
resolver
10011000
.where_predicates_in_scope()
10021001
// we have to filter out all other predicates *first*, before attempting to lower them

crates/hir_ty/src/tests/method_resolution.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,3 +1312,31 @@ impl<'a, T> IntoIterator for &'a [T] {
13121312
"#,
13131313
);
13141314
}
1315+
1316+
#[test]
1317+
fn sized_blanket_impl() {
1318+
check_infer(
1319+
r#"
1320+
#[lang = "sized"]
1321+
pub trait Sized {}
1322+
1323+
trait Foo { fn foo() -> u8; }
1324+
impl<T: Sized> Foo for T {}
1325+
fn f<S: Sized, T, U: ?Sized>() {
1326+
u32::foo;
1327+
S::foo;
1328+
T::foo;
1329+
U::foo;
1330+
<[u32]>::foo;
1331+
}
1332+
"#,
1333+
expect![[r#"
1334+
127..198 '{ ...foo; }': ()
1335+
133..141 'u32::foo': fn foo<u32>() -> u8
1336+
147..153 'S::foo': fn foo<S>() -> u8
1337+
159..165 'T::foo': fn foo<T>() -> u8
1338+
171..177 'U::foo': {unknown}
1339+
183..195 '<[u32]>::foo': {unknown}
1340+
"#]],
1341+
);
1342+
}

crates/hir_ty/src/tests/traits.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3515,3 +3515,35 @@ fn test() {
35153515
"#,
35163516
);
35173517
}
3518+
3519+
#[test]
3520+
fn associated_type_sized_bounds() {
3521+
check_infer(
3522+
r#"
3523+
#[lang = "sized"]
3524+
pub trait Sized {}
3525+
3526+
struct Yes;
3527+
trait IsSized { const IS_SIZED: Yes; }
3528+
impl<T: Sized> IsSized for T { const IS_SIZED: Yes = Yes; }
3529+
3530+
trait Foo {
3531+
type Explicit: Sized;
3532+
type Implicit;
3533+
type Relaxed: ?Sized;
3534+
}
3535+
fn f<F: Foo>() {
3536+
F::Explicit::IS_SIZED;
3537+
F::Implicit::IS_SIZED;
3538+
F::Relaxed::IS_SIZED;
3539+
}
3540+
"#,
3541+
expect![[r#"
3542+
142..145 'Yes': Yes
3543+
250..333 '{ ...ZED; }': ()
3544+
256..277 'F::Exp..._SIZED': Yes
3545+
283..304 'F::Imp..._SIZED': Yes
3546+
310..330 'F::Rel..._SIZED': {unknown}
3547+
"#]],
3548+
);
3549+
}

0 commit comments

Comments
 (0)