about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <me@lukaswirth.dev>2025-06-10 11:37:30 +0000
committerGitHub <noreply@github.com>2025-06-10 11:37:30 +0000
commitb64e7482783c4d267dbf2cbc445a272855f8ec48 (patch)
tree9744dacde821d336158061ef9e33ada283a23948
parente3ec14385f62ea80f40e7b131ca2ccb58a1cafcf (diff)
parent95fdb2d81188cc04d3b26689da6e2d8cf3b0bb33 (diff)
downloadrust-b64e7482783c4d267dbf2cbc445a272855f8ec48.tar.gz
rust-b64e7482783c4d267dbf2cbc445a272855f8ec48.zip
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
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/generics.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs34
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs29
4 files changed, 64 insertions, 3 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
index ed8d8dc2624..48094945c11 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
@@ -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;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
index bb4aaf78895..a3ed39934cd 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
@@ -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 {
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index e8218cf8611..969fd3eb480 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -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 {
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
index fa7ba90a756..0e18ce96740 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
@@ -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 {}
+ "#,
+        )
+    }
 }