Skip to content

Commit f15267a

Browse files
authored
Merge pull request #19963 from ChayimFriedman2/unsized-impl-items
fix: Do not error at impls for unsized types that do not include `where Self: Sized` items
2 parents bf6d445 + 6f4a6d4 commit f15267a

File tree

4 files changed

+64
-3
lines changed

4 files changed

+64
-3
lines changed

crates/hir-ty/src/dyn_compatibility.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ pub fn dyn_compatibility_of_trait_query(
122122
res
123123
}
124124

125-
fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool {
125+
pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool {
126126
let krate = def.module(db).krate();
127127
let Some(sized) = LangItem::Sized.resolve_trait(db, krate) else {
128128
return false;

crates/hir-ty/src/generics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ impl Generics {
229229
}
230230

231231
/// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`).
232-
pub(crate) fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution {
232+
pub fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution {
233233
Substitution::from_iter(
234234
Interner,
235235
self.iter_id().map(|id| match id {

crates/hir/src/lib.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -846,14 +846,46 @@ impl Module {
846846
)
847847
}
848848

849-
let missing: Vec<_> = required_items
849+
let mut missing: Vec<_> = required_items
850850
.filter(|(name, id)| {
851851
!impl_assoc_items_scratch.iter().any(|(impl_name, impl_item)| {
852852
discriminant(impl_item) == discriminant(id) && impl_name == name
853853
})
854854
})
855855
.map(|(name, item)| (name.clone(), AssocItem::from(*item)))
856856
.collect();
857+
858+
if !missing.is_empty() {
859+
let self_ty = db.impl_self_ty(impl_def.id).substitute(
860+
Interner,
861+
&hir_ty::generics::generics(db, impl_def.id.into()).placeholder_subst(db),
862+
);
863+
let self_ty = if let TyKind::Alias(AliasTy::Projection(projection)) =
864+
self_ty.kind(Interner)
865+
{
866+
db.normalize_projection(
867+
projection.clone(),
868+
db.trait_environment(impl_def.id.into()),
869+
)
870+
} else {
871+
self_ty
872+
};
873+
let self_ty_is_guaranteed_unsized = matches!(
874+
self_ty.kind(Interner),
875+
TyKind::Dyn(..) | TyKind::Slice(..) | TyKind::Str
876+
);
877+
if self_ty_is_guaranteed_unsized {
878+
missing.retain(|(_, assoc_item)| {
879+
let assoc_item = match *assoc_item {
880+
AssocItem::Function(it) => it.id.into(),
881+
AssocItem::Const(it) => it.id.into(),
882+
AssocItem::TypeAlias(it) => it.id.into(),
883+
};
884+
!hir_ty::dyn_compatibility::generics_require_sized_self(db, assoc_item)
885+
});
886+
}
887+
}
888+
857889
if !missing.is_empty() {
858890
acc.push(
859891
TraitImplMissingAssocItems {

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,33 @@ impl !Trait for () {}
127127
"#,
128128
)
129129
}
130+
131+
#[test]
132+
fn impl_sized_for_unsized() {
133+
check_diagnostics(
134+
r#"
135+
//- minicore: sized
136+
trait Trait {
137+
type Item
138+
where
139+
Self: Sized;
140+
141+
fn item()
142+
where
143+
Self: Sized;
144+
}
145+
146+
trait OtherTrait {}
147+
148+
impl Trait for () {
149+
type Item = ();
150+
fn item() {}
151+
}
152+
153+
// Items with Self: Sized bound not required to be implemented for unsized types.
154+
impl Trait for str {}
155+
impl Trait for dyn OtherTrait {}
156+
"#,
157+
)
158+
}
130159
}

0 commit comments

Comments
 (0)