about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-ty/src/lower.rs61
-rw-r--r--crates/hir-ty/src/tests/traits.rs28
2 files changed, 54 insertions, 35 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 239f66bcb7e..ae115c8c0da 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -238,18 +238,7 @@ impl<'a> TyLoweringContext<'a> {
                 })
                 .intern(Interner)
             }
-            TypeRef::DynTrait(bounds) => {
-                let self_ty =
-                    TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
-                let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
-                    QuantifiedWhereClauses::from_iter(
-                        Interner,
-                        bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)),
-                    )
-                });
-                let bounds = crate::make_single_type_binders(bounds);
-                TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner)
-            }
+            TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds),
             TypeRef::ImplTrait(bounds) => {
                 match self.impl_trait_mode {
                     ImplTraitLoweringMode::Opaque => {
@@ -468,29 +457,10 @@ impl<'a> TyLoweringContext<'a> {
                         }
                     }
                     0 => {
-                        let self_ty = Some(
-                            TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
-                                .intern(Interner),
-                        );
-                        let trait_ref = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
-                            ctx.lower_trait_ref_from_resolved_path(
-                                trait_,
-                                resolved_segment,
-                                self_ty,
-                            )
-                        });
-                        let dyn_ty = DynTy {
-                            bounds: crate::make_single_type_binders(
-                                QuantifiedWhereClauses::from_iter(
-                                    Interner,
-                                    Some(crate::wrap_empty_binders(WhereClause::Implemented(
-                                        trait_ref,
-                                    ))),
-                                ),
-                            ),
-                            lifetime: static_lifetime(),
-                        };
-                        TyKind::Dyn(dyn_ty).intern(Interner)
+                        // Trait object type without dyn; this should be handled in upstream. See
+                        // `lower_path()`.
+                        stdx::never!("unexpected fully resolved trait path");
+                        TyKind::Error.intern(Interner)
                     }
                     _ => {
                         // FIXME report error (ambiguous associated type)
@@ -555,11 +525,20 @@ impl<'a> TyLoweringContext<'a> {
             let (ty, res) = self.lower_ty_ext(type_ref);
             return self.lower_ty_relative_path(ty, res, path.segments());
         }
+
         let (resolution, remaining_index) =
             match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) {
                 Some(it) => it,
                 None => return (TyKind::Error.intern(Interner), None),
             };
+
+        if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() {
+            // trait object type without dyn
+            let bound = TypeBound::Path(path.clone(), TraitBoundModifier::None);
+            let ty = self.lower_dyn_trait(&[Interned::new(bound)]);
+            return (ty, None);
+        }
+
         let (resolved_segment, remaining_segments) = match remaining_index {
             None => (
                 path.segments().last().expect("resolved path has at least one element"),
@@ -987,6 +966,18 @@ impl<'a> TyLoweringContext<'a> {
             })
     }
 
+    fn lower_dyn_trait(&self, bounds: &[Interned<TypeBound>]) -> Ty {
+        let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
+        let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
+            QuantifiedWhereClauses::from_iter(
+                Interner,
+                bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)),
+            )
+        });
+        let bounds = crate::make_single_type_binders(bounds);
+        TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner)
+    }
+
     fn lower_impl_trait(
         &self,
         bounds: &[Interned<TypeBound>],
diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs
index 75802a5eb4d..c128a051f72 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/crates/hir-ty/src/tests/traits.rs
@@ -1476,6 +1476,34 @@ fn test(x: Trait, y: &Trait) -> u64 {
             165..172 'z.foo()': u64
         "#]],
     );
+
+    check_infer_with_mismatches(
+        r#"
+//- minicore: fn, coerce_unsized
+struct S;
+impl S {
+    fn foo(&self) {}
+}
+fn f(_: &Fn(S)) {}
+fn main() {
+    f(&|number| number.foo());
+}
+        "#,
+        expect![[r#"
+            31..35 'self': &S
+            37..39 '{}': ()
+            47..48 '_': &dyn Fn(S)
+            58..60 '{}': ()
+            71..105 '{     ...()); }': ()
+            77..78 'f': fn f(&dyn Fn(S))
+            77..102 'f(&|nu...foo())': ()
+            79..101 '&|numb....foo()': &|S| -> ()
+            80..101 '|numbe....foo()': |S| -> ()
+            81..87 'number': S
+            89..95 'number': S
+            89..101 'number.foo()': ()
+        "#]],
+    )
 }
 
 #[test]