Skip to content

Commit d434688

Browse files
committed
mir: build MIR for constants and static initializers.
1 parent cde2f5f commit d434688

File tree

5 files changed

+177
-25
lines changed

5 files changed

+177
-25
lines changed

src/librustc/hir/map/def_collector.rs

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,31 @@ impl<'ast> DefCollector<'ast> {
9797
f(self);
9898
self.parent_def = parent;
9999
}
100+
101+
fn visit_ast_const_integer(&mut self, expr: &'ast Expr) {
102+
// Find the node which will be used after lowering.
103+
if let ExprKind::Paren(ref inner) = expr.node {
104+
return self.visit_ast_const_integer(inner);
105+
}
106+
107+
// FIXME(eddyb) Closures should have separate
108+
// function definition IDs and expression IDs.
109+
if let ExprKind::Closure(..) = expr.node {
110+
return;
111+
}
112+
113+
self.create_def(expr.id, DefPathData::Initializer);
114+
}
115+
116+
fn visit_hir_const_integer(&mut self, expr: &'ast hir::Expr) {
117+
// FIXME(eddyb) Closures should have separate
118+
// function definition IDs and expression IDs.
119+
if let hir::ExprClosure(..) = expr.node {
120+
return;
121+
}
122+
123+
self.create_def(expr.id, DefPathData::Initializer);
124+
}
100125
}
101126

102127
impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
@@ -126,14 +151,17 @@ impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
126151
let variant_def_index =
127152
this.create_def(v.node.data.id(),
128153
DefPathData::EnumVariant(v.node.name.name));
129-
130-
for (index, field) in v.node.data.fields().iter().enumerate() {
131-
let name = field.ident.map(|ident| ident.name)
132-
.unwrap_or(token::intern(&index.to_string()));
133-
this.create_def_with_parent(Some(variant_def_index),
134-
field.id,
135-
DefPathData::Field(name));
136-
}
154+
this.with_parent(variant_def_index, |this| {
155+
for (index, field) in v.node.data.fields().iter().enumerate() {
156+
let name = field.ident.map(|ident| ident.name)
157+
.unwrap_or_else(|| token::intern(&index.to_string()));
158+
this.create_def(field.id, DefPathData::Field(name));
159+
}
160+
161+
if let Some(ref expr) = v.node.disr_expr {
162+
this.visit_ast_const_integer(expr);
163+
}
164+
});
137165
}
138166
}
139167
ItemKind::Struct(ref struct_def, _) => {
@@ -221,6 +249,10 @@ impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
221249
fn visit_expr(&mut self, expr: &'ast Expr) {
222250
let parent_def = self.parent_def;
223251

252+
if let ExprKind::Repeat(_, ref count) = expr.node {
253+
self.visit_ast_const_integer(count);
254+
}
255+
224256
if let ExprKind::Closure(..) = expr.node {
225257
let def = self.create_def(expr.id, DefPathData::ClosureExpr);
226258
self.parent_def = Some(def);
@@ -230,6 +262,13 @@ impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
230262
self.parent_def = parent_def;
231263
}
232264

265+
fn visit_ty(&mut self, ty: &'ast Ty) {
266+
if let TyKind::FixedLengthVec(_, ref length) = ty.node {
267+
self.visit_ast_const_integer(length);
268+
}
269+
visit::walk_ty(self, ty);
270+
}
271+
233272
fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
234273
self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
235274
}
@@ -276,11 +315,15 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
276315
this.create_def(v.node.data.id(),
277316
DefPathData::EnumVariant(v.node.name));
278317

279-
for field in v.node.data.fields() {
280-
this.create_def_with_parent(Some(variant_def_index),
281-
field.id,
282-
DefPathData::Field(field.name));
283-
}
318+
this.with_parent(variant_def_index, |this| {
319+
for field in v.node.data.fields() {
320+
this.create_def(field.id,
321+
DefPathData::Field(field.name));
322+
}
323+
if let Some(ref expr) = v.node.disr_expr {
324+
this.visit_hir_const_integer(expr);
325+
}
326+
});
284327
}
285328
}
286329
hir::ItemStruct(ref struct_def, _) => {
@@ -365,6 +408,10 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
365408
fn visit_expr(&mut self, expr: &'ast hir::Expr) {
366409
let parent_def = self.parent_def;
367410

411+
if let hir::ExprRepeat(_, ref count) = expr.node {
412+
self.visit_hir_const_integer(count);
413+
}
414+
368415
if let hir::ExprClosure(..) = expr.node {
369416
let def = self.create_def(expr.id, DefPathData::ClosureExpr);
370417
self.parent_def = Some(def);
@@ -374,11 +421,18 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
374421
self.parent_def = parent_def;
375422
}
376423

424+
fn visit_ty(&mut self, ty: &'ast hir::Ty) {
425+
if let hir::TyFixedLengthVec(_, ref length) = ty.node {
426+
self.visit_hir_const_integer(length);
427+
}
428+
intravisit::walk_ty(self, ty);
429+
}
430+
377431
fn visit_lifetime_def(&mut self, def: &'ast hir::LifetimeDef) {
378432
self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
379433
}
380434

381435
fn visit_macro_def(&mut self, macro_def: &'ast hir::MacroDef) {
382436
self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
383437
}
384-
}
438+
}

src/librustc/ty/mod.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use middle::cstore::{self, LOCAL_CRATE};
2525
use hir::def::{self, Def, ExportMap};
2626
use hir::def_id::DefId;
2727
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
28-
use middle::region::{CodeExtent};
28+
use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
2929
use traits;
3030
use ty;
3131
use ty::subst::{Subst, Substs, VecPerParamSpace};
@@ -1376,6 +1376,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
13761376
}
13771377
hir::ItemEnum(..) |
13781378
hir::ItemStruct(..) |
1379+
hir::ItemTy(..) |
13791380
hir::ItemImpl(..) |
13801381
hir::ItemConst(..) |
13811382
hir::ItemStatic(..) => {
@@ -1408,6 +1409,15 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
14081409
// This is a convenience to allow closures to work.
14091410
ParameterEnvironment::for_item(cx, cx.map.get_parent(id))
14101411
}
1412+
Some(ast_map::NodeForeignItem(item)) => {
1413+
let def_id = cx.map.local_def_id(id);
1414+
let scheme = cx.lookup_item_type(def_id);
1415+
let predicates = cx.lookup_predicates(def_id);
1416+
cx.construct_parameter_environment(item.span,
1417+
&scheme.generics,
1418+
&predicates,
1419+
ROOT_CODE_EXTENT)
1420+
}
14111421
_ => {
14121422
bug!("ParameterEnvironment::from_item(): \
14131423
`{}` is not an item",

src/librustc_mir/build/expr/as_temp.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,12 @@ impl<'a,'tcx> Builder<'a,'tcx> {
3535

3636
let expr_ty = expr.ty.clone();
3737
let temp = this.temp(expr_ty.clone());
38-
let temp_lifetime = match expr.temp_lifetime {
39-
Some(t) => t,
40-
None => {
41-
span_bug!(expr.span, "no temp_lifetime for expr");
42-
}
43-
};
44-
this.schedule_drop(expr.span, temp_lifetime, &temp, expr_ty);
38+
// In constants, temp_lifetime is None. We should not need to drop
39+
// anything because no values with a destructor can be created in
40+
// a constant at this time, even if the type may need dropping.
41+
if let Some(temp_lifetime) = expr.temp_lifetime {
42+
this.schedule_drop(expr.span, temp_lifetime, &temp, expr_ty);
43+
}
4544

4645
// Careful here not to cause an infinite cycle. If we always
4746
// called `into`, then for lvalues like `x.f`, it would

src/librustc_mir/build/mod.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use hair::cx::Cx;
12-
use rustc::middle::region::{CodeExtent, CodeExtentData};
12+
use rustc::middle::region::{CodeExtent, CodeExtentData, ROOT_CODE_EXTENT};
1313
use rustc::ty::{self, Ty};
1414
use rustc::mir::repr::*;
1515
use rustc_data_structures::fnv::FnvHashMap;
@@ -232,6 +232,33 @@ pub fn construct_fn<'a, 'tcx, A>(hir: Cx<'a,'tcx>,
232232
builder.finish(upvar_decls, arg_decls, return_ty)
233233
}
234234

235+
pub fn construct_const<'a, 'tcx>(hir: Cx<'a,'tcx>,
236+
item_id: ast::NodeId,
237+
ast_expr: &'tcx hir::Expr)
238+
-> (Mir<'tcx>, ScopeAuxiliaryVec) {
239+
let tcx = hir.tcx();
240+
let span = tcx.map.span(item_id);
241+
let mut builder = Builder::new(hir, span);
242+
243+
let extent = ROOT_CODE_EXTENT;
244+
let mut block = START_BLOCK;
245+
let _ = builder.in_scope(extent, block, |builder, call_site_scope_id| {
246+
let expr = builder.hir.mirror(ast_expr);
247+
unpack!(block = builder.into(&Lvalue::ReturnPointer, block, expr));
248+
249+
let return_block = builder.return_block();
250+
builder.cfg.terminate(block, call_site_scope_id, span,
251+
TerminatorKind::Goto { target: return_block });
252+
builder.cfg.terminate(return_block, call_site_scope_id, span,
253+
TerminatorKind::Return);
254+
255+
return_block.unit()
256+
});
257+
258+
let ty = tcx.expr_ty_adjusted(ast_expr);
259+
builder.finish(vec![], vec![], ty::FnConverging(ty))
260+
}
261+
235262
impl<'a,'tcx> Builder<'a,'tcx> {
236263
fn new(hir: Cx<'a, 'tcx>, span: Span) -> Builder<'a, 'tcx> {
237264
let mut builder = Builder {

src/librustc_mir/mir_map.rs

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
//! - `#[rustc_mir(graphviz="file.gv")]`
1717
//! - `#[rustc_mir(pretty="file.mir")]`
1818
19-
extern crate syntax;
20-
2119
use build;
2220
use rustc::dep_graph::DepNode;
2321
use rustc::mir::repr::Mir;
@@ -72,9 +70,73 @@ impl<'a, 'tcx> BuildMir<'a, 'tcx> {
7270

7371
assert!(self.map.map.insert(id, mir).is_none())
7472
}
73+
74+
fn build_const_integer(&mut self, expr: &'tcx hir::Expr) {
75+
// FIXME(eddyb) Closures should have separate
76+
// function definition IDs and expression IDs.
77+
// Type-checking should not let closures get
78+
// this far in an integer constant position.
79+
if let hir::ExprClosure(..) = expr.node {
80+
return;
81+
}
82+
self.build(expr.id, |cx| build::construct_const(cx, expr.id, expr));
83+
}
7584
}
7685

7786
impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
87+
// Const and static items.
88+
fn visit_item(&mut self, item: &'tcx hir::Item) {
89+
match item.node {
90+
hir::ItemConst(_, ref expr) |
91+
hir::ItemStatic(_, _, ref expr) => {
92+
self.build(item.id, |cx| build::construct_const(cx, item.id, expr));
93+
}
94+
_ => {}
95+
}
96+
intravisit::walk_item(self, item);
97+
}
98+
99+
// Trait associated const defaults.
100+
fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
101+
if let hir::ConstTraitItem(_, Some(ref expr)) = item.node {
102+
self.build(item.id, |cx| build::construct_const(cx, item.id, expr));
103+
}
104+
intravisit::walk_trait_item(self, item);
105+
}
106+
107+
// Impl associated const.
108+
fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
109+
if let hir::ImplItemKind::Const(_, ref expr) = item.node {
110+
self.build(item.id, |cx| build::construct_const(cx, item.id, expr));
111+
}
112+
intravisit::walk_impl_item(self, item);
113+
}
114+
115+
// Repeat counts, i.e. [expr; constant].
116+
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
117+
if let hir::ExprRepeat(_, ref count) = expr.node {
118+
self.build_const_integer(count);
119+
}
120+
intravisit::walk_expr(self, expr);
121+
}
122+
123+
// Array lengths, i.e. [T; constant].
124+
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
125+
if let hir::TyFixedLengthVec(_, ref length) = ty.node {
126+
self.build_const_integer(length);
127+
}
128+
intravisit::walk_ty(self, ty);
129+
}
130+
131+
// Enum variant discriminant values.
132+
fn visit_variant(&mut self, v: &'tcx hir::Variant,
133+
g: &'tcx hir::Generics, item_id: ast::NodeId) {
134+
if let Some(ref expr) = v.node.disr_expr {
135+
self.build_const_integer(expr);
136+
}
137+
intravisit::walk_variant(self, v, g, item_id);
138+
}
139+
78140
fn visit_fn(&mut self,
79141
fk: intravisit::FnKind<'tcx>,
80142
decl: &'tcx hir::FnDecl,

0 commit comments

Comments
 (0)