Do not error at impls for unsized types that do not include where Self: Sized items

This commit is contained in:
Chayim Refael Friedman 2025-06-10 14:04:21 +03:00
parent 6acff6c1f8
commit 6f4a6d4349
4 changed files with 64 additions and 3 deletions

View File

@ -122,7 +122,7 @@ pub fn dyn_compatibility_of_trait_query(
res
}
fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool {
pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool {
let krate = def.module(db).krate();
let Some(sized) = LangItem::Sized.resolve_trait(db, krate) else {
return false;

View File

@ -229,7 +229,7 @@ impl Generics {
}
/// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`).
pub(crate) fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution {
pub fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution {
Substitution::from_iter(
Interner,
self.iter_id().map(|id| match id {

View File

@ -846,7 +846,7 @@ impl Module {
)
}
let missing: Vec<_> = required_items
let mut missing: Vec<_> = required_items
.filter(|(name, id)| {
!impl_assoc_items_scratch.iter().any(|(impl_name, impl_item)| {
discriminant(impl_item) == discriminant(id) && impl_name == name
@ -854,6 +854,38 @@ impl Module {
})
.map(|(name, item)| (name.clone(), AssocItem::from(*item)))
.collect();
if !missing.is_empty() {
let self_ty = db.impl_self_ty(impl_def.id).substitute(
Interner,
&hir_ty::generics::generics(db, impl_def.id.into()).placeholder_subst(db),
);
let self_ty = if let TyKind::Alias(AliasTy::Projection(projection)) =
self_ty.kind(Interner)
{
db.normalize_projection(
projection.clone(),
db.trait_environment(impl_def.id.into()),
)
} else {
self_ty
};
let self_ty_is_guaranteed_unsized = matches!(
self_ty.kind(Interner),
TyKind::Dyn(..) | TyKind::Slice(..) | TyKind::Str
);
if self_ty_is_guaranteed_unsized {
missing.retain(|(_, assoc_item)| {
let assoc_item = match *assoc_item {
AssocItem::Function(it) => it.id.into(),
AssocItem::Const(it) => it.id.into(),
AssocItem::TypeAlias(it) => it.id.into(),
};
!hir_ty::dyn_compatibility::generics_require_sized_self(db, assoc_item)
});
}
}
if !missing.is_empty() {
acc.push(
TraitImplMissingAssocItems {

View File

@ -127,4 +127,33 @@ impl !Trait for () {}
"#,
)
}
#[test]
fn impl_sized_for_unsized() {
check_diagnostics(
r#"
//- minicore: sized
trait Trait {
type Item
where
Self: Sized;
fn item()
where
Self: Sized;
}
trait OtherTrait {}
impl Trait for () {
type Item = ();
fn item() {}
}
// Items with Self: Sized bound not required to be implemented for unsized types.
impl Trait for str {}
impl Trait for dyn OtherTrait {}
"#,
)
}
}