Skip to content

Commit d777f43

Browse files
committed
Auto merge of rust-lang#17511 - mckenfra:github_issue_17497_fix_v5, r=flodiebold
rust-lang#17497 - Invalid RA diagnostic error: expected 2 arguments, found 1 Fix for rust-lang#17497 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()`](https://github.com/rust-lang/rust-analyzer/blob/9463d9eea4b87e651e7d8ed8425a9c92f23b1cdf/crates/hir-ty/src/method_resolution.rs#L1008), 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.
2 parents 75fabf6 + 976fcd3 commit d777f43

File tree

3 files changed

+47
-3
lines changed

3 files changed

+47
-3
lines changed

src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ use crate::{
3030
utils::all_super_traits,
3131
AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, GenericArgData,
3232
Goal, Guidance, InEnvironment, Interner, Mutability, Scalar, Solution, Substitution,
33-
TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, VariableKind,
34-
WhereClause,
33+
TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, TyVariableKind,
34+
VariableKind, WhereClause,
3535
};
3636

3737
/// This is used as a key for indexing impls.
@@ -1083,6 +1083,11 @@ fn iterate_method_candidates_by_receiver(
10831083
table.run_in_snapshot(|table| {
10841084
let mut autoderef = autoderef::Autoderef::new(table, receiver_ty.clone(), true);
10851085
while let Some((self_ty, _)) = autoderef.next() {
1086+
if matches!(self_ty.kind(Interner), TyKind::InferenceVar(_, TyVariableKind::General)) {
1087+
// don't try to resolve methods on unknown types
1088+
return ControlFlow::Continue(());
1089+
}
1090+
10861091
iterate_trait_method_candidates(
10871092
&self_ty,
10881093
autoderef.table,

src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2099,3 +2099,42 @@ fn test() {
20992099
"#,
21002100
);
21012101
}
2102+
2103+
#[test]
2104+
fn mismatched_args_due_to_supertraits_with_deref() {
2105+
check_no_mismatches(
2106+
r#"
2107+
//- minicore: deref
2108+
use core::ops::Deref;
2109+
2110+
trait Trait1 {
2111+
type Assoc: Deref<Target = String>;
2112+
}
2113+
2114+
trait Trait2: Trait1 {
2115+
}
2116+
2117+
trait Trait3 {
2118+
type T1: Trait1;
2119+
type T2: Trait2;
2120+
fn bar(&self, x: bool, y: bool);
2121+
}
2122+
2123+
struct Foo;
2124+
2125+
impl Foo {
2126+
fn bar(&mut self, _: &'static str) {}
2127+
}
2128+
2129+
impl Deref for Foo {
2130+
type Target = u32;
2131+
fn deref(&self) -> &Self::Target { &0 }
2132+
}
2133+
2134+
fn problem_method<T: Trait3>() {
2135+
let mut foo = Foo;
2136+
foo.bar("hello"); // Rustc ok, RA errors (mismatched args)
2137+
}
2138+
"#,
2139+
);
2140+
}

src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1238,7 +1238,7 @@ fn benchmark_syntax_highlighting_parser() {
12381238
})
12391239
.count()
12401240
};
1241-
assert_eq!(hash, 1169);
1241+
assert_eq!(hash, 1167);
12421242
}
12431243

12441244
#[test]

0 commit comments

Comments
 (0)