Skip to content

Commit 2a0d16f

Browse files
authored
Merge pull request rust-lang#19167 from ChayimFriedman2/fix-ref-pat
fix: Fix detection of ref patterns for path patterns
2 parents c7a2986 + b7a9a32 commit 2a0d16f

File tree

4 files changed

+64
-17
lines changed

4 files changed

+64
-17
lines changed

src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs

+21
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::ops::{Deref, DerefMut};
77

88
use either::Either;
99
use hir_def::{hir::ExprOrPatId, path::Path, resolver::Resolver, type_ref::TypesMap, TypeOwnerId};
10+
use la_arena::{Idx, RawIdx};
1011

1112
use crate::{
1213
db::HirDatabase,
@@ -81,6 +82,26 @@ impl<'a> InferenceTyLoweringContext<'a> {
8182
};
8283
PathLoweringContext::new(&mut self.ctx, on_diagnostic, path)
8384
}
85+
86+
#[inline]
87+
pub(super) fn at_path_forget_diagnostics<'b>(
88+
&'b mut self,
89+
path: &'b Path,
90+
) -> PathLoweringContext<'b, 'a> {
91+
let on_diagnostic = PathDiagnosticCallback {
92+
data: Either::Right(PathDiagnosticCallbackData {
93+
diagnostics: self.diagnostics,
94+
node: ExprOrPatId::ExprId(Idx::from_raw(RawIdx::from_u32(0))),
95+
}),
96+
callback: |_data, _, _diag| {},
97+
};
98+
PathLoweringContext::new(&mut self.ctx, on_diagnostic, path)
99+
}
100+
101+
#[inline]
102+
pub(super) fn forget_diagnostics(&mut self) {
103+
self.ctx.diagnostics.clear();
104+
}
84105
}
85106

86107
impl<'a> Deref for InferenceTyLoweringContext<'a> {

src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs

+3-10
Original file line numberDiff line numberDiff line change
@@ -565,16 +565,9 @@ impl InferenceContext<'_> {
565565
| Pat::Slice { .. } => true,
566566
Pat::Or(pats) => pats.iter().all(|p| self.is_non_ref_pat(body, *p)),
567567
Pat::Path(path) => {
568-
// A const is a reference pattern, but other value ns things aren't (see #16131). We don't need more than
569-
// the hir-def resolver for this, because if there are segments left, this can only be an (associated) const.
570-
//
571-
// Do not use `TyLoweringContext`'s resolution, we want to ignore errors here (they'll be reported elsewhere).
572-
let resolution = self.resolver.resolve_path_in_value_ns_fully(
573-
self.db.upcast(),
574-
path,
575-
body.pat_path_hygiene(pat),
576-
);
577-
resolution.is_some_and(|it| !matches!(it, hir_def::resolver::ValueNs::ConstId(_)))
568+
// A const is a reference pattern, but other value ns things aren't (see #16131).
569+
let resolved = self.resolve_value_path_inner(path, pat.into(), true);
570+
resolved.is_some_and(|it| !matches!(it.0, hir_def::resolver::ValueNs::ConstId(_)))
578571
}
579572
Pat::ConstBlock(..) => false,
580573
Pat::Lit(expr) => !matches!(

src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs

+19-7
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ impl InferenceContext<'_> {
4040
}
4141

4242
fn resolve_value_path(&mut self, path: &Path, id: ExprOrPatId) -> Option<ValuePathResolution> {
43-
let (value, self_subst) = self.resolve_value_path_inner(path, id)?;
43+
let (value, self_subst) = self.resolve_value_path_inner(path, id, false)?;
4444

4545
let value_def: ValueTyDefId = match value {
4646
ValueNs::FunctionId(it) => it.into(),
@@ -152,6 +152,7 @@ impl InferenceContext<'_> {
152152
&mut self,
153153
path: &Path,
154154
id: ExprOrPatId,
155+
no_diagnostics: bool,
155156
) -> Option<(ValueNs, Option<chalk_ir::Substitution<Interner>>)> {
156157
// Don't use `self.make_ty()` here as we need `orig_ns`.
157158
let mut ctx = TyLoweringContext::new(
@@ -162,7 +163,11 @@ impl InferenceContext<'_> {
162163
&self.diagnostics,
163164
InferenceTyDiagnosticSource::Body,
164165
);
165-
let mut path_ctx = ctx.at_path(path, id);
166+
let mut path_ctx = if no_diagnostics {
167+
ctx.at_path_forget_diagnostics(path)
168+
} else {
169+
ctx.at_path(path, id)
170+
};
166171
let (value, self_subst) = if let Some(type_ref) = path.type_anchor() {
167172
let last = path.segments().last()?;
168173

@@ -172,7 +177,7 @@ impl InferenceContext<'_> {
172177

173178
path_ctx.ignore_last_segment();
174179
let (ty, _) = path_ctx.lower_ty_relative_path(ty, orig_ns);
175-
drop(ctx);
180+
drop_ctx(ctx, no_diagnostics);
176181
let ty = self.table.insert_type_vars(ty);
177182
let ty = self.table.normalize_associated_types_in(ty);
178183
self.resolve_ty_assoc_item(ty, last.name, id).map(|(it, substs)| (it, Some(substs)))?
@@ -183,7 +188,7 @@ impl InferenceContext<'_> {
183188

184189
match value_or_partial {
185190
ResolveValueResult::ValueNs(it, _) => {
186-
drop(ctx);
191+
drop_ctx(ctx, no_diagnostics);
187192
(it, None)
188193
}
189194
ResolveValueResult::Partial(def, remaining_index, _) => {
@@ -202,7 +207,7 @@ impl InferenceContext<'_> {
202207
let self_ty = self.table.new_type_var();
203208
let trait_ref =
204209
path_ctx.lower_trait_ref_from_resolved_path(trait_, self_ty);
205-
drop(ctx);
210+
drop_ctx(ctx, no_diagnostics);
206211
self.resolve_trait_assoc_item(trait_ref, last_segment, id)
207212
}
208213
(def, _) => {
@@ -212,7 +217,7 @@ impl InferenceContext<'_> {
212217
// as Iterator>::Item::default`)
213218
path_ctx.ignore_last_segment();
214219
let (ty, _) = path_ctx.lower_partly_resolved_path(def, true);
215-
drop(ctx);
220+
drop_ctx(ctx, no_diagnostics);
216221
if ty.is_unknown() {
217222
return None;
218223
}
@@ -227,7 +232,14 @@ impl InferenceContext<'_> {
227232
}
228233
}
229234
};
230-
Some((value, self_subst))
235+
return Some((value, self_subst));
236+
237+
#[inline]
238+
fn drop_ctx(mut ctx: TyLoweringContext<'_>, no_diagnostics: bool) {
239+
if no_diagnostics {
240+
ctx.forget_diagnostics();
241+
}
242+
}
231243
}
232244

233245
fn add_required_obligations_for_value_path(&mut self, def: GenericDefId, subst: &Substitution) {

src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs

+21
Original file line numberDiff line numberDiff line change
@@ -1235,4 +1235,25 @@ fn f() {
12351235
"#,
12361236
);
12371237
}
1238+
1239+
#[test]
1240+
fn complex_enum_variant_non_ref_pat() {
1241+
check_diagnostics(
1242+
r#"
1243+
enum Enum { Variant }
1244+
1245+
trait Trait {
1246+
type Assoc;
1247+
}
1248+
impl Trait for () {
1249+
type Assoc = Enum;
1250+
}
1251+
1252+
fn foo(v: &Enum) {
1253+
let <Enum>::Variant = v;
1254+
let <() as Trait>::Assoc::Variant = v;
1255+
}
1256+
"#,
1257+
);
1258+
}
12381259
}

0 commit comments

Comments
 (0)