Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #21750 from ChayimFriedman2/method-res-typingmode
fix: Do not use PostAnalysis TypingMode for IDE method resolution
Shoyu Vanilla (Flint) 7 weeks ago
parent 789ad51 · parent 398419b · commit 87f5363
-rw-r--r--crates/hir/src/lib.rs11
-rw-r--r--crates/ide-completion/src/tests/expression.rs35
2 files changed, 45 insertions, 1 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 9dbee16dae..43cdf80e0d 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -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);
diff --git a/crates/ide-completion/src/tests/expression.rs b/crates/ide-completion/src/tests/expression.rs
index 5fef8c44de..8e50ef10ec 100644
--- a/crates/ide-completion/src/tests/expression.rs
+++ b/crates/ide-completion/src/tests/expression.rs
@@ -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 {}
+ "#]],
+ );
+}