mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-25 11:17:13 +00:00
Do not error at impls for unsized types that do not include where Self: Sized
items
This commit is contained in:
parent
6acff6c1f8
commit
6f4a6d4349
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user