aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
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
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')
-rw-r--r--crates/ra_hir_def/src/adt.rs1
-rw-r--r--crates/ra_hir_def/src/body/lower.rs38
-rw-r--r--crates/ra_hir_def/src/expr.rs2
3 files changed, 37 insertions, 4 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 985f409e8..2bdfc2b8d 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -174,6 +174,7 @@ impl HasChildSource for VariantId {
174 } 174 }
175} 175}
176 176
177#[derive(Debug, Copy, Clone, PartialEq, Eq)]
177pub enum StructKind { 178pub enum StructKind {
178 Tuple, 179 Tuple,
179 Record, 180 Record,
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));
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
index 9707c5527..66d004717 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -48,7 +48,7 @@ pub enum Literal {
48 48
49#[derive(Debug, Clone, Eq, PartialEq)] 49#[derive(Debug, Clone, Eq, PartialEq)]
50pub enum Expr { 50pub enum Expr {
51 /// This is produced if syntax tree does not have a required expression piece. 51 /// This is produced if the syntax tree does not have a required expression piece.
52 Missing, 52 Missing,
53 Path(Path), 53 Path(Path),
54 If { 54 If {