about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFrancis McKenzie <info@macca.tech>2024-06-29 13:06:28 +0800
committerFrancis McKenzie <info@macca.tech>2024-07-28 00:32:37 +0800
commit1261827eb9332b9595994d9be67ba9da80f1a644 (patch)
tree8fba1154fc33b9256d24ccbe60e341c290d8b8bf
parent34dc7ac79f6a2fe20e2fb67f106566ded456c7dd (diff)
downloadrust-1261827eb9332b9595994d9be67ba9da80f1a644.tar.gz
rust-1261827eb9332b9595994d9be67ba9da80f1a644.zip
Fix for #17497 - Invalid RA diagnostic error: expected 2 arguments, found 1
The issue occurs because in some configurations of traits where one of them has Deref as a supertrait, RA's type inference algorithm fails to resolve the Deref::Target type, and instead uses a TyKind::BoundVar (i.e. an unknown type). This "autoderefed" type then incorrectly acts as if it implements all traits in scope.

The fix is to re-apply the same sanity-check that is done in iterate_method_candidates_with_autoref(), that is: don't try to resolve methods on unknown types. This same sanity-check is now done on each autoderefed type for which trait methods are about to be checked. If the autoderefed type is unknown, then the iterating of the trait methods for that type is skipped.

Includes a unit test that only passes after applying the fixes in this commit.

Includes a change to the assertion count in test syntax_highlighting::tests::benchmark_syntax_highlighting_parser as suggested by Lukas Wirth during review.

Includes a change to the sanity-check code as suggested by Florian Diebold during review.
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs39
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs2
3 files changed, 47 insertions, 3 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
index c07bd08be40..8ba8071d36e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
@@ -30,8 +30,8 @@ use crate::{
     utils::all_super_traits,
     AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, GenericArgData,
     Goal, Guidance, InEnvironment, Interner, Mutability, Scalar, Solution, Substitution,
-    TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, VariableKind,
-    WhereClause,
+    TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, TyVariableKind,
+    VariableKind, WhereClause,
 };
 
 /// This is used as a key for indexing impls.
@@ -1083,6 +1083,11 @@ fn iterate_method_candidates_by_receiver(
     table.run_in_snapshot(|table| {
         let mut autoderef = autoderef::Autoderef::new(table, receiver_ty.clone(), true);
         while let Some((self_ty, _)) = autoderef.next() {
+            if matches!(self_ty.kind(Interner), TyKind::InferenceVar(_, TyVariableKind::General)) {
+                // don't try to resolve methods on unknown types
+                return ControlFlow::Continue(());
+            }
+
             iterate_trait_method_candidates(
                 &self_ty,
                 autoderef.table,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
index 360a1292834..14e2e746531 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
@@ -2099,3 +2099,42 @@ fn test() {
 "#,
     );
 }
+
+#[test]
+fn mismatched_args_due_to_supertraits_with_deref() {
+    check_no_mismatches(
+        r#"
+//- minicore: deref
+use core::ops::Deref;
+
+trait Trait1 {
+    type Assoc: Deref<Target = String>;
+}
+
+trait Trait2: Trait1 {
+}
+
+trait Trait3 {
+    type T1: Trait1;
+    type T2: Trait2;
+    fn bar(&self, x: bool, y: bool);
+}
+
+struct Foo;
+
+impl Foo {
+    fn bar(&mut self, _: &'static str) {}
+}
+
+impl Deref for Foo {
+    type Target = u32;
+    fn deref(&self) -> &Self::Target { &0 }
+}
+
+fn problem_method<T: Trait3>() {
+    let mut foo = Foo;
+    foo.bar("hello"); // Rustc ok, RA errors (mismatched args)
+}
+"#,
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
index 5f711600a29..2070022d418 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
@@ -1238,7 +1238,7 @@ fn benchmark_syntax_highlighting_parser() {
             })
             .count()
     };
-    assert_eq!(hash, 1169);
+    assert_eq!(hash, 1167);
 }
 
 #[test]