Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-ty/src/infer/expr.rs12
-rw-r--r--crates/hir-ty/src/tests/regression.rs55
-rw-r--r--crates/hir-ty/src/tests/traits.rs66
3 files changed, 88 insertions, 45 deletions
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 226e9f5cd6..62339779a5 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -1704,7 +1704,7 @@ impl<'db> InferenceContext<'_, 'db> {
});
match resolved {
Ok((func, _is_visible)) => {
- self.check_method_call(tgt_expr, &[], func.sig, receiver_ty, expected)
+ self.check_method_call(tgt_expr, &[], func.sig, expected)
}
Err(_) => self.err_ty(),
}
@@ -1844,7 +1844,7 @@ impl<'db> InferenceContext<'_, 'db> {
item: func.def_id.into(),
})
}
- self.check_method_call(tgt_expr, args, func.sig, receiver_ty, expected)
+ self.check_method_call(tgt_expr, args, func.sig, expected)
}
// Failed to resolve, report diagnostic and try to resolve as call to field access or
// assoc function
@@ -1934,16 +1934,14 @@ impl<'db> InferenceContext<'_, 'db> {
tgt_expr: ExprId,
args: &[ExprId],
sig: FnSig<'db>,
- receiver_ty: Ty<'db>,
expected: &Expectation<'db>,
) -> Ty<'db> {
- let (formal_receiver_ty, param_tys) = if !sig.inputs_and_output.inputs().is_empty() {
- (sig.inputs_and_output.as_slice()[0], &sig.inputs_and_output.inputs()[1..])
+ let param_tys = if !sig.inputs_and_output.inputs().is_empty() {
+ &sig.inputs_and_output.inputs()[1..]
} else {
- (self.types.types.error, &[] as _)
+ &[]
};
let ret_ty = sig.output();
- self.table.unify(formal_receiver_ty, receiver_ty);
self.check_call_arguments(tgt_expr, param_tys, ret_ty, expected, args, &[], sig.c_variadic);
ret_ty
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index c805f03044..df49d7999f 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -891,13 +891,14 @@ use core::ops::Deref;
struct BufWriter {}
-struct Mutex<T> {}
-struct MutexGuard<'a, T> {}
+struct Mutex<T>(T);
+struct MutexGuard<'a, T>(&'a T);
impl<T> Mutex<T> {
fn lock(&self) -> MutexGuard<'_, T> {}
}
impl<'a, T: 'a> Deref for MutexGuard<'a, T> {
type Target = T;
+ fn deref(&self) -> &Self::Target { loop {} }
}
fn flush(&self) {
let w: &Mutex<BufWriter>;
@@ -905,14 +906,18 @@ fn flush(&self) {
}
"#,
expect![[r#"
- 123..127 'self': &'? Mutex<T>
- 150..152 '{}': MutexGuard<'?, T>
- 234..238 'self': &'? {unknown}
- 240..290 '{ ...()); }': ()
- 250..251 'w': &'? Mutex<BufWriter>
- 276..287 '*(w.lock())': BufWriter
- 278..279 'w': &'? Mutex<BufWriter>
- 278..286 'w.lock()': MutexGuard<'?, BufWriter>
+ 129..133 'self': &'? Mutex<T>
+ 156..158 '{}': MutexGuard<'?, T>
+ 242..246 'self': &'? MutexGuard<'a, T>
+ 265..276 '{ loop {} }': &'? T
+ 267..274 'loop {}': !
+ 272..274 '{}': ()
+ 289..293 'self': &'? {unknown}
+ 295..345 '{ ...()); }': ()
+ 305..306 'w': &'? Mutex<BufWriter>
+ 331..342 '*(w.lock())': BufWriter
+ 333..334 'w': &'? Mutex<BufWriter>
+ 333..341 'w.lock()': MutexGuard<'?, BufWriter>
"#]],
);
}
@@ -2563,3 +2568,33 @@ fn main() {
"#,
);
}
+
+#[test]
+fn regression_21429() {
+ check_no_mismatches(
+ r#"
+trait DatabaseLike {
+ type ForeignKey: ForeignKeyLike<DB = Self>;
+}
+
+trait ForeignKeyLike {
+ type DB: DatabaseLike;
+
+ fn host_columns(&self, database: &Self::DB);
+}
+
+trait ColumnLike {
+ type DB: DatabaseLike;
+
+ fn foo() -> &&<<Self as ColumnLike>::DB as DatabaseLike>::ForeignKey {
+ loop {}
+ }
+
+ fn foreign_keys(&self, database: &Self::DB) {
+ let fk = Self::foo();
+ fk.host_columns(database);
+ }
+}
+ "#,
+ );
+}
diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs
index 38591f486e..b825a0a8f0 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/crates/hir-ty/src/tests/traits.rs
@@ -429,7 +429,7 @@ fn associated_type_shorthand_from_method_bound() {
trait Iterable {
type Item;
}
-struct S<T>;
+struct S<T>(T);
impl<T> S<T> {
fn foo(self) -> T::Item where T: Iterable { loop {} }
}
@@ -1103,40 +1103,50 @@ fn test() {
fn argument_impl_trait_type_args_2() {
check_infer_with_mismatches(
r#"
-//- minicore: sized
+//- minicore: sized, phantom_data
+use core::marker::PhantomData;
+
trait Trait {}
struct S;
impl Trait for S {}
-struct F<T>;
+struct F<T>(PhantomData<T>);
impl<T> F<T> {
fn foo<U>(self, x: impl Trait) -> (T, U) { loop {} }
}
fn test() {
- F.foo(S);
- F::<u32>.foo(S);
- F::<u32>.foo::<i32>(S);
- F::<u32>.foo::<i32, u32>(S); // extraneous argument should be ignored
+ F(PhantomData).foo(S);
+ F::<u32>(PhantomData).foo(S);
+ F::<u32>(PhantomData).foo::<i32>(S);
+ F::<u32>(PhantomData).foo::<i32, u32>(S); // extraneous argument should be ignored
}"#,
expect![[r#"
- 87..91 'self': F<T>
- 93..94 'x': impl Trait
- 118..129 '{ loop {} }': (T, U)
- 120..127 'loop {}': !
- 125..127 '{}': ()
- 143..283 '{ ...ored }': ()
- 149..150 'F': F<{unknown}>
- 149..157 'F.foo(S)': ({unknown}, {unknown})
- 155..156 'S': S
- 163..171 'F::<u32>': F<u32>
- 163..178 'F::<u32>.foo(S)': (u32, {unknown})
- 176..177 'S': S
- 184..192 'F::<u32>': F<u32>
- 184..206 'F::<u3...32>(S)': (u32, i32)
- 204..205 'S': S
- 212..220 'F::<u32>': F<u32>
- 212..239 'F::<u3...32>(S)': (u32, i32)
- 237..238 'S': S
+ 135..139 'self': F<T>
+ 141..142 'x': impl Trait
+ 166..177 '{ loop {} }': (T, U)
+ 168..175 'loop {}': !
+ 173..175 '{}': ()
+ 191..383 '{ ...ored }': ()
+ 197..198 'F': fn F<{unknown}>(PhantomData<{unknown}>) -> F<{unknown}>
+ 197..211 'F(PhantomData)': F<{unknown}>
+ 197..218 'F(Phan...foo(S)': ({unknown}, {unknown})
+ 199..210 'PhantomData': PhantomData<{unknown}>
+ 216..217 'S': S
+ 224..232 'F::<u32>': fn F<u32>(PhantomData<u32>) -> F<u32>
+ 224..245 'F::<u3...mData)': F<u32>
+ 224..252 'F::<u3...foo(S)': (u32, {unknown})
+ 233..244 'PhantomData': PhantomData<u32>
+ 250..251 'S': S
+ 258..266 'F::<u32>': fn F<u32>(PhantomData<u32>) -> F<u32>
+ 258..279 'F::<u3...mData)': F<u32>
+ 258..293 'F::<u3...32>(S)': (u32, i32)
+ 267..278 'PhantomData': PhantomData<u32>
+ 291..292 'S': S
+ 299..307 'F::<u32>': fn F<u32>(PhantomData<u32>) -> F<u32>
+ 299..320 'F::<u3...mData)': F<u32>
+ 299..339 'F::<u3...32>(S)': (u32, i32)
+ 308..319 'PhantomData': PhantomData<u32>
+ 337..338 'S': S
"#]],
);
}
@@ -4012,7 +4022,7 @@ fn f<F: Foo>() {
fn dyn_map() {
check_types(
r#"
-pub struct Key<K, V, P = (K, V)> {}
+pub struct Key<K, V, P = (K, V)>(K, V, P);
pub trait Policy {
type K;
@@ -4024,7 +4034,7 @@ impl<K, V> Policy for (K, V) {
type V = V;
}
-pub struct KeyMap<KEY> {}
+pub struct KeyMap<KEY>(KEY);
impl<P: Policy> KeyMap<Key<P::K, P::V, P>> {
pub fn get(&self, key: &P::K) -> P::V {
@@ -5023,7 +5033,7 @@ fn main() {
278..280 '{}': ()
290..291 '_': Box<dyn Iterator<Item = &'? [u8]> + '?>
294..298 'iter': Box<dyn Iterator<Item = &'? [u8]> + 'static>
- 294..310 'iter.i...iter()': Box<dyn Iterator<Item = &'? [u8]> + 'static>
+ 294..310 'iter.i...iter()': Box<dyn Iterator<Item = &'? [u8]> + '?>
152..156 'self': &'? mut Box<I>
177..208 '{ ... }': Option<<I as Iterator>::Item>
191..198 'loop {}': !