aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/body/lower.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-02-21 15:56:34 +0000
committerFlorian Diebold <[email protected]>2020-02-21 16:01:19 +0000
commitf1f45f9191d60c52dbedec717aee0de4a0580bcc (patch)
treebaebf708dcdc154fbe4fe903906e11e344a09802 /crates/ra_hir_def/src/body/lower.rs
parente3037c2631ecb55996b676ce2c18b9df1858abaa (diff)
Fix handling of const patterns
E.g. in `match x { None => ... }`, `None` is a path pattern (resolving to the option variant), not a binding. To determine this, we need to try to resolve the name during lowering. This isn't too hard since we already need to resolve names for macro expansion anyway (though maybe a bit hacky). Fixes #1618.
Diffstat (limited to 'crates/ra_hir_def/src/body/lower.rs')
-rw-r--r--crates/ra_hir_def/src/body/lower.rs38
1 files changed, 35 insertions, 3 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index b1626fa11..b3fb6d452 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -15,6 +15,7 @@ use ra_syntax::{
15use test_utils::tested_by; 15use test_utils::tested_by;
16 16
17use crate::{ 17use crate::{
18 adt::StructKind,
18 body::{Body, BodySourceMap, Expander, PatPtr}, 19 body::{Body, BodySourceMap, Expander, PatPtr},
19 builtin_type::{BuiltinFloat, BuiltinInt}, 20 builtin_type::{BuiltinFloat, BuiltinInt},
20 db::DefDatabase, 21 db::DefDatabase,
@@ -22,11 +23,12 @@ use crate::{
22 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp, 23 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp,
23 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, 24 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
24 }, 25 },
26 item_scope::BuiltinShadowMode,
25 path::GenericArgs, 27 path::GenericArgs,
26 path::Path, 28 path::Path,
27 type_ref::{Mutability, TypeRef}, 29 type_ref::{Mutability, TypeRef},
28 ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, StaticLoc, 30 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId,
29 StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, 31 StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
30}; 32};
31 33
32pub(super) fn lower( 34pub(super) fn lower(
@@ -571,7 +573,37 @@ where
571 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 573 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
572 let annotation = BindingAnnotation::new(bp.is_mutable(), bp.is_ref()); 574 let annotation = BindingAnnotation::new(bp.is_mutable(), bp.is_ref());
573 let subpat = bp.pat().map(|subpat| self.collect_pat(subpat)); 575 let subpat = bp.pat().map(|subpat| self.collect_pat(subpat));
574 Pat::Bind { name, mode: annotation, subpat } 576 if annotation == BindingAnnotation::Unannotated && subpat.is_none() {
577 // This could also be a single-segment path pattern. To
578 // decide that, we need to try resolving the name.
579 let (resolved, _) = self.expander.crate_def_map.resolve_path(
580 self.db,
581 self.expander.module.local_id,
582 &name.clone().into(),
583 BuiltinShadowMode::Other,
584 );
585 match resolved.take_values() {
586 Some(ModuleDefId::ConstId(_)) => Pat::Path(name.into()),
587 Some(ModuleDefId::EnumVariantId(_)) => {
588 // this is only really valid for unit variants, but
589 // shadowing other enum variants with a pattern is
590 // an error anyway
591 Pat::Path(name.into())
592 }
593 Some(ModuleDefId::AdtId(AdtId::StructId(s)))
594 if self.db.struct_data(s).variant_data.kind() != StructKind::Record =>
595 {
596 // Funnily enough, record structs *can* be shadowed
597 // by pattern bindings (but unit or tuple structs
598 // can't).
599 Pat::Path(name.into())
600 }
601 // shadowing statics is an error as well, so we just ignore that case here
602 _ => Pat::Bind { name, mode: annotation, subpat },
603 }
604 } else {
605 Pat::Bind { name, mode: annotation, subpat }
606 }
575 } 607 }
576 ast::Pat::TupleStructPat(p) => { 608 ast::Pat::TupleStructPat(p) => {
577 let path = p.path().and_then(|path| self.expander.parse_path(path)); 609 let path = p.path().and_then(|path| self.expander.parse_path(path));