Skip to content

Commit 44ff3c4

Browse files
committed
Auto merge of rust-lang#14232 - HKalbasi:mir, r=Veykril
MIR episode 2 This PR adds: 1. `need-mut` and `unused-mut` diagnostics 2. `View mir` command which shows MIR for the body under cursor, useful for debugging 3. MIR lowering for or-patterns and for-loops
2 parents 31c12ec + bcd7ecb commit 44ff3c4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+3164
-760
lines changed

crates/hir-def/src/body.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use syntax::{ast, AstPtr, SyntaxNode, SyntaxNodePtr};
2424
use crate::{
2525
attr::Attrs,
2626
db::DefDatabase,
27-
expr::{dummy_expr_id, Expr, ExprId, Label, LabelId, Pat, PatId},
27+
expr::{dummy_expr_id, Binding, BindingId, Expr, ExprId, Label, LabelId, Pat, PatId},
2828
item_scope::BuiltinShadowMode,
2929
macro_id_to_def_id,
3030
nameres::DefMap,
@@ -270,6 +270,7 @@ pub struct Mark {
270270
pub struct Body {
271271
pub exprs: Arena<Expr>,
272272
pub pats: Arena<Pat>,
273+
pub bindings: Arena<Binding>,
273274
pub or_pats: FxHashMap<PatId, Arc<[PatId]>>,
274275
pub labels: Arena<Label>,
275276
/// The patterns for the function's parameters. While the parameter types are
@@ -435,13 +436,24 @@ impl Body {
435436
}
436437

437438
fn shrink_to_fit(&mut self) {
438-
let Self { _c: _, body_expr: _, block_scopes, or_pats, exprs, labels, params, pats } = self;
439+
let Self {
440+
_c: _,
441+
body_expr: _,
442+
block_scopes,
443+
or_pats,
444+
exprs,
445+
labels,
446+
params,
447+
pats,
448+
bindings,
449+
} = self;
439450
block_scopes.shrink_to_fit();
440451
or_pats.shrink_to_fit();
441452
exprs.shrink_to_fit();
442453
labels.shrink_to_fit();
443454
params.shrink_to_fit();
444455
pats.shrink_to_fit();
456+
bindings.shrink_to_fit();
445457
}
446458
}
447459

@@ -451,6 +463,7 @@ impl Default for Body {
451463
body_expr: dummy_expr_id(),
452464
exprs: Default::default(),
453465
pats: Default::default(),
466+
bindings: Default::default(),
454467
or_pats: Default::default(),
455468
labels: Default::default(),
456469
params: Default::default(),
@@ -484,6 +497,14 @@ impl Index<LabelId> for Body {
484497
}
485498
}
486499

500+
impl Index<BindingId> for Body {
501+
type Output = Binding;
502+
503+
fn index(&self, b: BindingId) -> &Binding {
504+
&self.bindings[b]
505+
}
506+
}
507+
487508
// FIXME: Change `node_` prefix to something more reasonable.
488509
// Perhaps `expr_syntax` and `expr_id`?
489510
impl BodySourceMap {

crates/hir-def/src/body/lower.rs

Lines changed: 80 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use la_arena::Arena;
1515
use once_cell::unsync::OnceCell;
1616
use profile::Count;
1717
use rustc_hash::FxHashMap;
18+
use smallvec::SmallVec;
1819
use syntax::{
1920
ast::{
2021
self, ArrayExprKind, AstChildren, HasArgList, HasLoopBody, HasName, LiteralKind,
@@ -30,9 +31,9 @@ use crate::{
3031
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
3132
db::DefDatabase,
3233
expr::{
33-
dummy_expr_id, Array, BindingAnnotation, ClosureKind, Expr, ExprId, FloatTypeWrapper,
34-
Label, LabelId, Literal, MatchArm, Movability, Pat, PatId, RecordFieldPat, RecordLitField,
35-
Statement,
34+
dummy_expr_id, Array, Binding, BindingAnnotation, BindingId, ClosureKind, Expr, ExprId,
35+
FloatTypeWrapper, Label, LabelId, Literal, MatchArm, Movability, Pat, PatId,
36+
RecordFieldPat, RecordLitField, Statement,
3637
},
3738
item_scope::BuiltinShadowMode,
3839
path::{GenericArgs, Path},
@@ -87,6 +88,7 @@ pub(super) fn lower(
8788
body: Body {
8889
exprs: Arena::default(),
8990
pats: Arena::default(),
91+
bindings: Arena::default(),
9092
labels: Arena::default(),
9193
params: Vec::new(),
9294
body_expr: dummy_expr_id(),
@@ -116,6 +118,22 @@ struct ExprCollector<'a> {
116118
is_lowering_generator: bool,
117119
}
118120

121+
#[derive(Debug, Default)]
122+
struct BindingList {
123+
map: FxHashMap<Name, BindingId>,
124+
}
125+
126+
impl BindingList {
127+
fn find(
128+
&mut self,
129+
ec: &mut ExprCollector<'_>,
130+
name: Name,
131+
mode: BindingAnnotation,
132+
) -> BindingId {
133+
*self.map.entry(name).or_insert_with_key(|n| ec.alloc_binding(n.clone(), mode))
134+
}
135+
}
136+
119137
impl ExprCollector<'_> {
120138
fn collect(
121139
mut self,
@@ -127,17 +145,16 @@ impl ExprCollector<'_> {
127145
param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false))
128146
{
129147
let ptr = AstPtr::new(&self_param);
130-
let param_pat = self.alloc_pat(
131-
Pat::Bind {
132-
name: name![self],
133-
mode: BindingAnnotation::new(
134-
self_param.mut_token().is_some() && self_param.amp_token().is_none(),
135-
false,
136-
),
137-
subpat: None,
138-
},
139-
Either::Right(ptr),
148+
let binding_id = self.alloc_binding(
149+
name![self],
150+
BindingAnnotation::new(
151+
self_param.mut_token().is_some() && self_param.amp_token().is_none(),
152+
false,
153+
),
140154
);
155+
let param_pat =
156+
self.alloc_pat(Pat::Bind { id: binding_id, subpat: None }, Either::Right(ptr));
157+
self.add_definition_to_binding(binding_id, param_pat);
141158
self.body.params.push(param_pat);
142159
}
143160

@@ -179,6 +196,9 @@ impl ExprCollector<'_> {
179196
id
180197
}
181198

199+
fn alloc_binding(&mut self, name: Name, mode: BindingAnnotation) -> BindingId {
200+
self.body.bindings.alloc(Binding { name, mode, definitions: SmallVec::new() })
201+
}
182202
fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
183203
let src = self.expander.to_source(ptr);
184204
let id = self.make_pat(pat, src.clone());
@@ -804,7 +824,7 @@ impl ExprCollector<'_> {
804824
}
805825

806826
fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
807-
let pat_id = self.collect_pat_(pat);
827+
let pat_id = self.collect_pat_(pat, &mut BindingList::default());
808828
for (_, pats) in self.name_to_pat_grouping.drain() {
809829
let pats = Arc::<[_]>::from(pats);
810830
self.body.or_pats.extend(pats.iter().map(|&pat| (pat, pats.clone())));
@@ -820,16 +840,18 @@ impl ExprCollector<'_> {
820840
}
821841
}
822842

823-
fn collect_pat_(&mut self, pat: ast::Pat) -> PatId {
843+
fn collect_pat_(&mut self, pat: ast::Pat, binding_list: &mut BindingList) -> PatId {
824844
let pattern = match &pat {
825845
ast::Pat::IdentPat(bp) => {
826846
let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
827847

828848
let key = self.is_lowering_inside_or_pat.then(|| name.clone());
829849
let annotation =
830850
BindingAnnotation::new(bp.mut_token().is_some(), bp.ref_token().is_some());
831-
let subpat = bp.pat().map(|subpat| self.collect_pat_(subpat));
832-
let pattern = if annotation == BindingAnnotation::Unannotated && subpat.is_none() {
851+
let subpat = bp.pat().map(|subpat| self.collect_pat_(subpat, binding_list));
852+
let (binding, pattern) = if annotation == BindingAnnotation::Unannotated
853+
&& subpat.is_none()
854+
{
833855
// This could also be a single-segment path pattern. To
834856
// decide that, we need to try resolving the name.
835857
let (resolved, _) = self.expander.def_map.resolve_path(
@@ -839,30 +861,37 @@ impl ExprCollector<'_> {
839861
BuiltinShadowMode::Other,
840862
);
841863
match resolved.take_values() {
842-
Some(ModuleDefId::ConstId(_)) => Pat::Path(name.into()),
864+
Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())),
843865
Some(ModuleDefId::EnumVariantId(_)) => {
844866
// this is only really valid for unit variants, but
845867
// shadowing other enum variants with a pattern is
846868
// an error anyway
847-
Pat::Path(name.into())
869+
(None, Pat::Path(name.into()))
848870
}
849871
Some(ModuleDefId::AdtId(AdtId::StructId(s)))
850872
if self.db.struct_data(s).variant_data.kind() != StructKind::Record =>
851873
{
852874
// Funnily enough, record structs *can* be shadowed
853875
// by pattern bindings (but unit or tuple structs
854876
// can't).
855-
Pat::Path(name.into())
877+
(None, Pat::Path(name.into()))
856878
}
857879
// shadowing statics is an error as well, so we just ignore that case here
858-
_ => Pat::Bind { name, mode: annotation, subpat },
880+
_ => {
881+
let id = binding_list.find(self, name, annotation);
882+
(Some(id), Pat::Bind { id, subpat })
883+
}
859884
}
860885
} else {
861-
Pat::Bind { name, mode: annotation, subpat }
886+
let id = binding_list.find(self, name, annotation);
887+
(Some(id), Pat::Bind { id, subpat })
862888
};
863889

864890
let ptr = AstPtr::new(&pat);
865891
let pat = self.alloc_pat(pattern, Either::Left(ptr));
892+
if let Some(binding_id) = binding {
893+
self.add_definition_to_binding(binding_id, pat);
894+
}
866895
if let Some(key) = key {
867896
self.name_to_pat_grouping.entry(key).or_default().push(pat);
868897
}
@@ -871,11 +900,11 @@ impl ExprCollector<'_> {
871900
ast::Pat::TupleStructPat(p) => {
872901
let path =
873902
p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
874-
let (args, ellipsis) = self.collect_tuple_pat(p.fields());
903+
let (args, ellipsis) = self.collect_tuple_pat(p.fields(), binding_list);
875904
Pat::TupleStruct { path, args, ellipsis }
876905
}
877906
ast::Pat::RefPat(p) => {
878-
let pat = self.collect_pat_opt(p.pat());
907+
let pat = self.collect_pat_opt_(p.pat(), binding_list);
879908
let mutability = Mutability::from_mutable(p.mut_token().is_some());
880909
Pat::Ref { pat, mutability }
881910
}
@@ -886,12 +915,12 @@ impl ExprCollector<'_> {
886915
}
887916
ast::Pat::OrPat(p) => {
888917
self.is_lowering_inside_or_pat = true;
889-
let pats = p.pats().map(|p| self.collect_pat_(p)).collect();
918+
let pats = p.pats().map(|p| self.collect_pat_(p, binding_list)).collect();
890919
Pat::Or(pats)
891920
}
892-
ast::Pat::ParenPat(p) => return self.collect_pat_opt_(p.pat()),
921+
ast::Pat::ParenPat(p) => return self.collect_pat_opt_(p.pat(), binding_list),
893922
ast::Pat::TuplePat(p) => {
894-
let (args, ellipsis) = self.collect_tuple_pat(p.fields());
923+
let (args, ellipsis) = self.collect_tuple_pat(p.fields(), binding_list);
895924
Pat::Tuple { args, ellipsis }
896925
}
897926
ast::Pat::WildcardPat(_) => Pat::Wild,
@@ -904,7 +933,7 @@ impl ExprCollector<'_> {
904933
.fields()
905934
.filter_map(|f| {
906935
let ast_pat = f.pat()?;
907-
let pat = self.collect_pat_(ast_pat);
936+
let pat = self.collect_pat_(ast_pat, binding_list);
908937
let name = f.field_name()?.as_name();
909938
Some(RecordFieldPat { name, pat })
910939
})
@@ -923,9 +952,15 @@ impl ExprCollector<'_> {
923952

924953
// FIXME properly handle `RestPat`
925954
Pat::Slice {
926-
prefix: prefix.into_iter().map(|p| self.collect_pat_(p)).collect(),
927-
slice: slice.map(|p| self.collect_pat_(p)),
928-
suffix: suffix.into_iter().map(|p| self.collect_pat_(p)).collect(),
955+
prefix: prefix
956+
.into_iter()
957+
.map(|p| self.collect_pat_(p, binding_list))
958+
.collect(),
959+
slice: slice.map(|p| self.collect_pat_(p, binding_list)),
960+
suffix: suffix
961+
.into_iter()
962+
.map(|p| self.collect_pat_(p, binding_list))
963+
.collect(),
929964
}
930965
}
931966
ast::Pat::LiteralPat(lit) => {
@@ -948,7 +983,7 @@ impl ExprCollector<'_> {
948983
Pat::Missing
949984
}
950985
ast::Pat::BoxPat(boxpat) => {
951-
let inner = self.collect_pat_opt_(boxpat.pat());
986+
let inner = self.collect_pat_opt_(boxpat.pat(), binding_list);
952987
Pat::Box { inner }
953988
}
954989
ast::Pat::ConstBlockPat(const_block_pat) => {
@@ -965,7 +1000,7 @@ impl ExprCollector<'_> {
9651000
let src = self.expander.to_source(Either::Left(AstPtr::new(&pat)));
9661001
let pat =
9671002
self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| {
968-
this.collect_pat_opt_(expanded_pat)
1003+
this.collect_pat_opt_(expanded_pat, binding_list)
9691004
});
9701005
self.source_map.pat_map.insert(src, pat);
9711006
return pat;
@@ -979,21 +1014,25 @@ impl ExprCollector<'_> {
9791014
self.alloc_pat(pattern, Either::Left(ptr))
9801015
}
9811016

982-
fn collect_pat_opt_(&mut self, pat: Option<ast::Pat>) -> PatId {
1017+
fn collect_pat_opt_(&mut self, pat: Option<ast::Pat>, binding_list: &mut BindingList) -> PatId {
9831018
match pat {
984-
Some(pat) => self.collect_pat_(pat),
1019+
Some(pat) => self.collect_pat_(pat, binding_list),
9851020
None => self.missing_pat(),
9861021
}
9871022
}
9881023

989-
fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Box<[PatId]>, Option<usize>) {
1024+
fn collect_tuple_pat(
1025+
&mut self,
1026+
args: AstChildren<ast::Pat>,
1027+
binding_list: &mut BindingList,
1028+
) -> (Box<[PatId]>, Option<usize>) {
9901029
// Find the location of the `..`, if there is one. Note that we do not
9911030
// consider the possibility of there being multiple `..` here.
9921031
let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::RestPat(_)));
9931032
// We want to skip the `..` pattern here, since we account for it above.
9941033
let args = args
9951034
.filter(|p| !matches!(p, ast::Pat::RestPat(_)))
996-
.map(|p| self.collect_pat_(p))
1035+
.map(|p| self.collect_pat_(p, binding_list))
9971036
.collect();
9981037

9991038
(args, ellipsis)
@@ -1022,6 +1061,10 @@ impl ExprCollector<'_> {
10221061
None => Some(()),
10231062
}
10241063
}
1064+
1065+
fn add_definition_to_binding(&mut self, binding_id: BindingId, pat_id: PatId) {
1066+
self.body.bindings[binding_id].definitions.push(pat_id);
1067+
}
10251068
}
10261069

10271070
impl From<ast::LiteralKind> for Literal {

crates/hir-def/src/body/pretty.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::fmt::{self, Write};
55
use syntax::ast::HasName;
66

77
use crate::{
8-
expr::{Array, BindingAnnotation, ClosureKind, Literal, Movability, Statement},
8+
expr::{Array, BindingAnnotation, BindingId, ClosureKind, Literal, Movability, Statement},
99
pretty::{print_generic_args, print_path, print_type_ref},
1010
type_ref::TypeRef,
1111
};
@@ -524,14 +524,8 @@ impl<'a> Printer<'a> {
524524
}
525525
Pat::Path(path) => self.print_path(path),
526526
Pat::Lit(expr) => self.print_expr(*expr),
527-
Pat::Bind { mode, name, subpat } => {
528-
let mode = match mode {
529-
BindingAnnotation::Unannotated => "",
530-
BindingAnnotation::Mutable => "mut ",
531-
BindingAnnotation::Ref => "ref ",
532-
BindingAnnotation::RefMut => "ref mut ",
533-
};
534-
w!(self, "{}{}", mode, name);
527+
Pat::Bind { id, subpat } => {
528+
self.print_binding(*id);
535529
if let Some(pat) = subpat {
536530
self.whitespace();
537531
self.print_pat(*pat);
@@ -635,4 +629,15 @@ impl<'a> Printer<'a> {
635629
fn print_path(&mut self, path: &Path) {
636630
print_path(path, self).unwrap();
637631
}
632+
633+
fn print_binding(&mut self, id: BindingId) {
634+
let Binding { name, mode, .. } = &self.body.bindings[id];
635+
let mode = match mode {
636+
BindingAnnotation::Unannotated => "",
637+
BindingAnnotation::Mutable => "mut ",
638+
BindingAnnotation::Ref => "ref ",
639+
BindingAnnotation::RefMut => "ref mut ",
640+
};
641+
w!(self, "{}{}", mode, name);
642+
}
638643
}

0 commit comments

Comments
 (0)