mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-14 14:13:58 +00:00
Auto merge of #16759 - roife:fix-goto-def-for-constants-in-range-pattern, r=Veykril
fix: goto-definition for constants inside range pattern Fix #15653. This PR addresses the issue where it was not possible to navigate to constants in range patterns, specifically including two major changes: 1. Previously, both the `start` and `end` fields in `Pat::Range` were of type `LiteralOrConst`. When performing `goto-definition` on constants inside range patterns, r-a would use `resolve_bind_pat_to_const` to find their definitions. However, because the content of a `Const` is not `Pat` but `Path`, it was not stored in the `source_map`, so `resolve_bind_pat_to_const` would returns `None`. This PR changes them to `Const(PatId)`, so that during the lowering process, they are considered as a `pat`, allowing their definitions to be found later through `resolve_bind_pat_to_const`. 2. The process related to range patterns in MIR-lowering has been modified to correctly handle the above changes.
This commit is contained in:
commit
223238d9e7
5 changed files with 31 additions and 13 deletions
|
@ -1413,16 +1413,10 @@ impl ExprCollector<'_> {
|
|||
ast::Pat::LiteralPat(it) => {
|
||||
Some(Box::new(LiteralOrConst::Literal(pat_literal_to_hir(it)?.0)))
|
||||
}
|
||||
ast::Pat::IdentPat(p) => {
|
||||
let name =
|
||||
p.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
|
||||
Some(Box::new(LiteralOrConst::Const(name.into())))
|
||||
pat @ (ast::Pat::IdentPat(_) | ast::Pat::PathPat(_)) => {
|
||||
let subpat = self.collect_pat(pat.clone(), binding_list);
|
||||
Some(Box::new(LiteralOrConst::Const(subpat)))
|
||||
}
|
||||
ast::Pat::PathPat(p) => p
|
||||
.path()
|
||||
.and_then(|path| self.expander.parse_path(self.db, path))
|
||||
.map(LiteralOrConst::Const)
|
||||
.map(Box::new),
|
||||
_ => None,
|
||||
})
|
||||
};
|
||||
|
|
|
@ -635,7 +635,7 @@ impl Printer<'_> {
|
|||
fn print_literal_or_const(&mut self, literal_or_const: &LiteralOrConst) {
|
||||
match literal_or_const {
|
||||
LiteralOrConst::Literal(l) => self.print_literal(l),
|
||||
LiteralOrConst::Const(c) => self.print_path(c),
|
||||
LiteralOrConst::Const(c) => self.print_pat(*c),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ pub enum Literal {
|
|||
/// Used in range patterns.
|
||||
pub enum LiteralOrConst {
|
||||
Literal(Literal),
|
||||
Const(Path),
|
||||
Const(PatId),
|
||||
}
|
||||
|
||||
impl Literal {
|
||||
|
|
|
@ -1364,10 +1364,16 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
match loc {
|
||||
LiteralOrConst::Literal(l) => self.lower_literal_to_operand(ty, l),
|
||||
LiteralOrConst::Const(c) => {
|
||||
let unresolved_name = || MirLowerError::unresolved_path(self.db, c);
|
||||
let c = match &self.body.pats[*c] {
|
||||
Pat::Path(p) => p,
|
||||
_ => not_supported!(
|
||||
"only `char` and numeric types are allowed in range patterns"
|
||||
),
|
||||
};
|
||||
let unresolved_name = || MirLowerError::unresolved_path(self.db, c.as_ref());
|
||||
let resolver = self.owner.resolver(self.db.upcast());
|
||||
let pr = resolver
|
||||
.resolve_path_in_value_ns(self.db.upcast(), c)
|
||||
.resolve_path_in_value_ns(self.db.upcast(), c.as_ref())
|
||||
.ok_or_else(unresolved_name)?;
|
||||
match pr {
|
||||
ResolveValueResult::ValueNs(v, _) => {
|
||||
|
|
|
@ -536,6 +536,24 @@ fn bar() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_definition_works_for_consts_inside_range_pattern() {
|
||||
check(
|
||||
r#"
|
||||
//- /lib.rs
|
||||
const A: u32 = 0;
|
||||
//^
|
||||
|
||||
fn bar(v: u32) {
|
||||
match v {
|
||||
0..=$0A => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_def_for_use_alias() {
|
||||
check(
|
||||
|
|
Loading…
Reference in a new issue