Do not use PostAnalysis TypingMode for IDE method resolution

As explained in the comments, PostAnalysis is good for most IDE things but not method resolution.

This fixes a bug which should not be impacted by this at all - return position impl trait in trait. It is currently lowered to an opaque, while it should be lowered to an anonymous associated type. But today when it is lowered as an opaque, this opaque of course has no definition and will normalize to an error, preventing method resolution on it from succeeding in some cases.
This commit is contained in:
Chayim Refael Friedman
2026-03-04 22:06:36 +02:00
parent 3c4ae110c7
commit 398419b1e7
2 changed files with 45 additions and 1 deletions

View File

@@ -5952,7 +5952,16 @@ impl<'db> Type<'db> {
) -> R {
let module = resolver.module();
let interner = DbInterner::new_with(db, module.krate(db));
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
// Most IDE operations want to operate in PostAnalysis mode, revealing opaques. This makes
// for a nicer IDE experience. However, method resolution is always done on real code (either
// existing code or code to be inserted), and there using PostAnalysis is dangerous - we may
// suggest invalid methods. So we're using the TypingMode of the body we're in.
let typing_mode = if let Some(body_owner) = resolver.body_owner() {
TypingMode::analysis_in_body(interner, body_owner.into())
} else {
TypingMode::non_body_analysis()
};
let infcx = interner.infer_ctxt().build(typing_mode);
let unstable_features =
MethodResolutionUnstableFeatures::from_def_map(resolver.top_level_def_map());
let environment = param_env_from_resolver(db, resolver);

View File

@@ -3659,3 +3659,38 @@ fn main() {
"#]],
);
}
#[test]
fn rpitit_with_reference() {
check(
r#"
trait Foo {
fn foo(&self);
}
trait Bar {
fn bar(&self) -> &impl Foo;
}
fn baz(v: impl Bar) {
v.bar().$0
}
"#,
expect![[r#"
me foo() (as Foo) fn(&self)
sn box Box::new(expr)
sn call function(expr)
sn const const {}
sn dbg dbg!(expr)
sn dbgr dbg!(&expr)
sn deref *expr
sn let let
sn letm let mut
sn match match expr {}
sn ref &expr
sn refm &mut expr
sn return return expr
sn unsafe unsafe {}
"#]],
);
}