Skip to content

Commit 43e7434

Browse files
Merge pull request #22363 from A4-Tacks/adt-unsized-ty-missing
fix: no lint unsized adt self_ty missing bounded assoc
2 parents 961b5b0 + b062ef8 commit 43e7434

2 files changed

Lines changed: 55 additions & 6 deletions

File tree

crates/hir/src/lib.rs

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -944,14 +944,17 @@ impl Module {
944944
.collect();
945945

946946
if !missing.is_empty() {
947+
let env = ParamEnvAndCrate {
948+
param_env: db.trait_environment(GenericDefId::from(impl_id).into()),
949+
krate: self.id.krate(db),
950+
};
947951
let self_ty = db.impl_self_ty(impl_id).instantiate_identity().skip_norm_wip();
948-
let self_ty = structurally_normalize_ty(
949-
&infcx,
950-
self_ty,
951-
db.trait_environment(GenericDefId::from(impl_id).into()),
952-
);
952+
let self_ty = structurally_normalize_ty(&infcx, self_ty, env.param_env);
953+
let tail_ty = struct_tail_raw(db, interner, self_ty, |ty| {
954+
structurally_normalize_ty(&infcx, ty, env.param_env)
955+
});
953956
let self_ty_is_guaranteed_unsized = matches!(
954-
self_ty.kind(),
957+
tail_ty.kind(),
955958
TyKind::Dynamic(..) | TyKind::Slice(..) | TyKind::Str
956959
);
957960
if self_ty_is_guaranteed_unsized {
@@ -7472,5 +7475,43 @@ impl MacroCallIdExt for span::MacroCallId {
74727475
}
74737476
}
74747477

7478+
// Like https://github.com/rust-lang/rust/blob/7c3c88f42ad444f4688b865591d84660be4ece2f/compiler/rustc_middle/src/ty/util.rs#L254-L310
7479+
pub fn struct_tail_raw<'db>(
7480+
db: &'db dyn HirDatabase,
7481+
interner: DbInterner<'db>,
7482+
mut ty: Ty<'db>,
7483+
mut normalize: impl FnMut(Ty<'db>) -> Ty<'db>,
7484+
) -> Ty<'db> {
7485+
let recursion_limit = 16;
7486+
for iteration in 0.. {
7487+
if iteration >= recursion_limit {
7488+
return Ty::new_error(interner, ErrorGuaranteed);
7489+
}
7490+
match ty.kind() {
7491+
TyKind::Adt(def, args) => {
7492+
let AdtId::StructId(def_id) = def.def_id() else { break };
7493+
let last_field = db.field_types(def_id.into()).iter().next_back();
7494+
match last_field {
7495+
Some((_, field)) => {
7496+
ty = normalize(field.get().instantiate(interner, args).skip_norm_wip())
7497+
}
7498+
None => break,
7499+
}
7500+
}
7501+
TyKind::Tuple(tys) if let Some((&last_ty, _)) = tys.split_last() => {
7502+
ty = last_ty;
7503+
}
7504+
TyKind::Tuple(_) => break,
7505+
TyKind::Pat(inner, _) => {
7506+
ty = inner;
7507+
}
7508+
_ => {
7509+
break;
7510+
}
7511+
}
7512+
}
7513+
ty
7514+
}
7515+
74757516
pub use hir_ty::next_solver;
74767517
pub use hir_ty::setup_tracing;

crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,18 @@ impl Trait for () {
149149
type Item = ();
150150
fn item() {}
151151
}
152+
impl Trait for Adt<i32> {}
153+
//^^^^^ error: not all trait items implemented, missing: `type Item`, `fn item`
152154
153155
// Items with Self: Sized bound not required to be implemented for unsized types.
154156
impl Trait for str {}
155157
impl Trait for dyn OtherTrait {}
158+
impl Trait for Adt<[i32]> {}
159+
impl Trait for Slice<i32> {}
160+
impl Trait for (str,) {}
161+
162+
struct Adt<T>(i32, T);
163+
struct Slice<T>([T]);
156164
"#,
157165
)
158166
}

0 commit comments

Comments
 (0)