Skip to content

Commit 6c751e0

Browse files
committed
Auto merge of #31474 - arielb1:mir-typeck, r=nikomatsakis
This should stop broken MIR from annoying us when we try to implement things
2 parents cfabd17 + d84658e commit 6c751e0

Some content is hidden

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

43 files changed

+1509
-190
lines changed

src/librustc/middle/expr_use_visitor.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -721,10 +721,11 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
721721
if let Some(adjustment) = adj {
722722
match adjustment {
723723
adjustment::AdjustReifyFnPointer |
724-
adjustment::AdjustUnsafeFnPointer => {
724+
adjustment::AdjustUnsafeFnPointer |
725+
adjustment::AdjustMutToConstPointer => {
725726
// Creating a closure/fn-pointer or unsizing consumes
726727
// the input and stores it into the resulting rvalue.
727-
debug!("walk_adjustment(AdjustReifyFnPointer|AdjustUnsafeFnPointer)");
728+
debug!("walk_adjustment: trivial adjustment");
728729
let cmt_unadjusted =
729730
return_if_err!(self.mc.cat_expr_unadjusted(expr));
730731
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);

src/librustc/middle/mem_categorization.rs

+1
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
430430

431431
adjustment::AdjustReifyFnPointer |
432432
adjustment::AdjustUnsafeFnPointer |
433+
adjustment::AdjustMutToConstPointer |
433434
adjustment::AdjustDerefRef(_) => {
434435
debug!("cat_expr({:?}): {:?}",
435436
adjustment,

src/librustc/middle/ty/adjustment.rs

+24-7
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ use rustc_front::hir;
2121

2222
#[derive(Copy, Clone)]
2323
pub enum AutoAdjustment<'tcx> {
24-
AdjustReifyFnPointer, // go from a fn-item type to a fn-pointer type
25-
AdjustUnsafeFnPointer, // go from a safe fn pointer to an unsafe fn pointer
24+
AdjustReifyFnPointer, // go from a fn-item type to a fn-pointer type
25+
AdjustUnsafeFnPointer, // go from a safe fn pointer to an unsafe fn pointer
26+
AdjustMutToConstPointer, // go from a mut raw pointer to a const raw pointer
2627
AdjustDerefRef(AutoDerefRef<'tcx>),
2728
}
2829

@@ -106,7 +107,8 @@ impl<'tcx> AutoAdjustment<'tcx> {
106107
pub fn is_identity(&self) -> bool {
107108
match *self {
108109
AdjustReifyFnPointer |
109-
AdjustUnsafeFnPointer => false,
110+
AdjustUnsafeFnPointer |
111+
AdjustMutToConstPointer => false,
110112
AdjustDerefRef(ref r) => r.is_identity(),
111113
}
112114
}
@@ -151,7 +153,7 @@ impl<'tcx> ty::TyS<'tcx> {
151153
return match adjustment {
152154
Some(adjustment) => {
153155
match *adjustment {
154-
AdjustReifyFnPointer => {
156+
AdjustReifyFnPointer => {
155157
match self.sty {
156158
ty::TyBareFn(Some(_), b) => {
157159
cx.mk_fn(None, b)
@@ -164,17 +166,32 @@ impl<'tcx> ty::TyS<'tcx> {
164166
}
165167
}
166168

167-
AdjustUnsafeFnPointer => {
169+
AdjustUnsafeFnPointer => {
168170
match self.sty {
169171
ty::TyBareFn(None, b) => cx.safe_to_unsafe_fn_ty(b),
170172
ref b => {
171173
cx.sess.bug(
172-
&format!("AdjustReifyFnPointer adjustment on non-fn-item: \
174+
&format!("AdjustUnsafeFnPointer adjustment on non-fn-ptr: \
173175
{:?}",
174176
b));
175177
}
176178
}
177-
}
179+
}
180+
181+
AdjustMutToConstPointer => {
182+
match self.sty {
183+
ty::TyRawPtr(mt) => cx.mk_ptr(ty::TypeAndMut {
184+
ty: mt.ty,
185+
mutbl: hir::MutImmutable
186+
}),
187+
ref b => {
188+
cx.sess.bug(
189+
&format!("AdjustMutToConstPointer on non-raw-ptr: \
190+
{:?}",
191+
b));
192+
}
193+
}
194+
}
178195

179196
AdjustDerefRef(ref adj) => {
180197
let mut adjusted_ty = self;

src/librustc/middle/ty/context.rs

+7
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ pub struct Tables<'tcx> {
131131
/// equivalents. This table is not used in trans (since regions
132132
/// are erased there) and hence is not serialized to metadata.
133133
pub liberated_fn_sigs: NodeMap<ty::FnSig<'tcx>>,
134+
135+
/// For each FRU expression, record the normalized types of the fields
136+
/// of the struct - this is needed because it is non-trivial to
137+
/// normalize while preserving regions. This table is used only in
138+
/// MIR construction and hence is not serialized to metadata.
139+
pub fru_field_types: NodeMap<Vec<Ty<'tcx>>>
134140
}
135141

136142
impl<'tcx> Tables<'tcx> {
@@ -144,6 +150,7 @@ impl<'tcx> Tables<'tcx> {
144150
closure_tys: DefIdMap(),
145151
closure_kinds: DefIdMap(),
146152
liberated_fn_sigs: NodeMap(),
153+
fru_field_types: NodeMap()
147154
}
148155
}
149156

src/librustc/mir/mir_map.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,30 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use dep_graph::DepNode;
1112
use util::nodemap::NodeMap;
1213
use mir::repr::Mir;
1314
use mir::transform::MirPass;
1415
use middle::ty;
16+
use middle::infer;
1517

1618
pub struct MirMap<'tcx> {
1719
pub map: NodeMap<Mir<'tcx>>,
1820
}
1921

2022
impl<'tcx> MirMap<'tcx> {
2123
pub fn run_passes(&mut self, passes: &mut [Box<MirPass>], tcx: &ty::ctxt<'tcx>) {
22-
for (_, ref mut mir) in &mut self.map {
24+
if passes.is_empty() { return; }
25+
26+
for (&id, mir) in &mut self.map {
27+
let did = tcx.map.local_def_id(id);
28+
let _task = tcx.dep_graph.in_task(DepNode::MirMapConstruction(did));
29+
30+
let param_env = ty::ParameterEnvironment::for_item(tcx, id);
31+
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env));
32+
2333
for pass in &mut *passes {
24-
pass.run_on_mir(mir, tcx)
34+
pass.run_on_mir(mir, &infcx)
2535
}
2636
}
2737
}

src/librustc/mir/repr.rs

+11-8
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ pub struct Mir<'tcx> {
4545
/// values in that it is possible to borrow them and mutate them
4646
/// through the resulting reference.
4747
pub temp_decls: Vec<TempDecl<'tcx>>,
48+
49+
/// A span representing this MIR, for error reporting
50+
pub span: Span,
4851
}
4952

5053
/// where execution begins
@@ -145,7 +148,7 @@ pub enum BorrowKind {
145148

146149
/// A "variable" is a binding declared by the user as part of the fn
147150
/// decl, a let, etc.
148-
#[derive(Clone, RustcEncodable, RustcDecodable)]
151+
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
149152
pub struct VarDecl<'tcx> {
150153
pub mutability: Mutability,
151154
pub name: Name,
@@ -154,7 +157,7 @@ pub struct VarDecl<'tcx> {
154157

155158
/// A "temp" is a temporary that we place on the stack. They are
156159
/// anonymous, always mutable, and have only a type.
157-
#[derive(Clone, RustcEncodable, RustcDecodable)]
160+
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
158161
pub struct TempDecl<'tcx> {
159162
pub ty: Ty<'tcx>,
160163
}
@@ -170,7 +173,7 @@ pub struct TempDecl<'tcx> {
170173
///
171174
/// there is only one argument, of type `(i32, u32)`, but two bindings
172175
/// (`x` and `y`).
173-
#[derive(Clone, RustcEncodable, RustcDecodable)]
176+
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
174177
pub struct ArgDecl<'tcx> {
175178
pub ty: Ty<'tcx>,
176179
}
@@ -499,7 +502,7 @@ pub struct Projection<'tcx, B, V> {
499502
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
500503
pub enum ProjectionElem<'tcx, V> {
501504
Deref,
502-
Field(Field),
505+
Field(Field, Ty<'tcx>),
503506
Index(V),
504507

505508
/// These indices are generated by slice patterns. Easiest to explain
@@ -550,8 +553,8 @@ impl Field {
550553
}
551554

552555
impl<'tcx> Lvalue<'tcx> {
553-
pub fn field(self, f: Field) -> Lvalue<'tcx> {
554-
self.elem(ProjectionElem::Field(f))
556+
pub fn field(self, f: Field, ty: Ty<'tcx>) -> Lvalue<'tcx> {
557+
self.elem(ProjectionElem::Field(f, ty))
555558
}
556559

557560
pub fn deref(self) -> Lvalue<'tcx> {
@@ -591,8 +594,8 @@ impl<'tcx> Debug for Lvalue<'tcx> {
591594
write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].name),
592595
ProjectionElem::Deref =>
593596
write!(fmt, "(*{:?})", data.base),
594-
ProjectionElem::Field(field) =>
595-
write!(fmt, "{:?}.{:?}", data.base, field.index()),
597+
ProjectionElem::Field(field, ty) =>
598+
write!(fmt, "({:?}.{:?}: {:?})", data.base, field.index(), ty),
596599
ProjectionElem::Index(ref index) =>
597600
write!(fmt, "{:?}[{:?}]", data.base, index),
598601
ProjectionElem::ConstantIndex { offset, min_length, from_end: false } =>

src/librustc/mir/tcx.rs

+70-18
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
*/
1515

1616
use mir::repr::*;
17-
use middle::subst::Substs;
17+
use middle::const_eval::ConstVal;
18+
use middle::subst::{Subst, Substs};
1819
use middle::ty::{self, AdtDef, Ty};
1920
use rustc_front::hir;
2021

@@ -72,23 +73,7 @@ impl<'tcx> LvalueTy<'tcx> {
7273
tcx.sess.bug(&format!("cannot downcast non-enum type: `{:?}`", self))
7374
}
7475
},
75-
ProjectionElem::Field(field) => {
76-
let field_ty = match self {
77-
LvalueTy::Ty { ty } => match ty.sty {
78-
ty::TyStruct(adt_def, substs) =>
79-
adt_def.struct_variant().fields[field.index()].ty(tcx, substs),
80-
ty::TyTuple(ref tys) =>
81-
tys[field.index()],
82-
ty::TyClosure(_, ref closure_substs) =>
83-
closure_substs.upvar_tys[field.index()],
84-
_ =>
85-
tcx.sess.bug(&format!("cannot get field of type: `{:?}`", ty)),
86-
},
87-
LvalueTy::Downcast { adt_def, substs, variant_index } =>
88-
adt_def.variants[variant_index].fields[field.index()].ty(tcx, substs),
89-
};
90-
LvalueTy::Ty { ty: field_ty }
91-
}
76+
ProjectionElem::Field(_, fty) => LvalueTy::Ty { ty: fty }
9277
}
9378
}
9479
}
@@ -150,6 +135,73 @@ impl<'tcx> Mir<'tcx> {
150135
self.lvalue_ty(tcx, &proj.base).projection_ty(tcx, &proj.elem)
151136
}
152137
}
138+
139+
pub fn rvalue_ty(&self,
140+
tcx: &ty::ctxt<'tcx>,
141+
rvalue: &Rvalue<'tcx>)
142+
-> Option<Ty<'tcx>>
143+
{
144+
match *rvalue {
145+
Rvalue::Use(ref operand) => Some(self.operand_ty(tcx, operand)),
146+
Rvalue::Repeat(ref operand, ref count) => {
147+
if let ConstVal::Uint(u) = count.value {
148+
let op_ty = self.operand_ty(tcx, operand);
149+
Some(tcx.mk_array(op_ty, u as usize))
150+
} else {
151+
None
152+
}
153+
}
154+
Rvalue::Ref(reg, bk, ref lv) => {
155+
let lv_ty = self.lvalue_ty(tcx, lv).to_ty(tcx);
156+
Some(tcx.mk_ref(
157+
tcx.mk_region(reg),
158+
ty::TypeAndMut {
159+
ty: lv_ty,
160+
mutbl: bk.to_mutbl_lossy()
161+
}
162+
))
163+
}
164+
Rvalue::Len(..) => Some(tcx.types.usize),
165+
Rvalue::Cast(_, _, ty) => Some(ty),
166+
Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
167+
let lhs_ty = self.operand_ty(tcx, lhs);
168+
let rhs_ty = self.operand_ty(tcx, rhs);
169+
Some(self.binop_ty(tcx, op, lhs_ty, rhs_ty))
170+
}
171+
Rvalue::UnaryOp(_, ref operand) => {
172+
Some(self.operand_ty(tcx, operand))
173+
}
174+
Rvalue::Box(t) => {
175+
Some(tcx.mk_box(t))
176+
}
177+
Rvalue::Aggregate(ref ak, ref ops) => {
178+
match *ak {
179+
AggregateKind::Vec => {
180+
if let Some(operand) = ops.get(0) {
181+
let ty = self.operand_ty(tcx, operand);
182+
Some(tcx.mk_array(ty, ops.len()))
183+
} else {
184+
None
185+
}
186+
}
187+
AggregateKind::Tuple => {
188+
Some(tcx.mk_tup(
189+
ops.iter().map(|op| self.operand_ty(tcx, op)).collect()
190+
))
191+
}
192+
AggregateKind::Adt(def, _, substs) => {
193+
Some(def.type_scheme(tcx).ty.subst(tcx, substs))
194+
}
195+
AggregateKind::Closure(did, substs) => {
196+
Some(tcx.mk_closure_from_closure_substs(
197+
did, Box::new(substs.clone())))
198+
}
199+
}
200+
}
201+
Rvalue::Slice { .. } => None,
202+
Rvalue::InlineAsm(..) => None
203+
}
204+
}
153205
}
154206

155207
impl BorrowKind {

src/librustc/mir/transform.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
// except according to those terms.
1010

1111
use mir::repr::Mir;
12-
use middle::ty::ctxt;
12+
use middle::infer::InferCtxt;
1313

1414
pub trait MirPass {
15-
fn run_on_mir<'tcx>(&mut self, mir: &mut Mir<'tcx>, tcx: &ctxt<'tcx>);
15+
fn run_on_mir<'a, 'tcx>(&mut self, mir: &mut Mir<'tcx>, infcx: &InferCtxt<'a, 'tcx>);
1616
}

src/librustc/session/config.rs

+6
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ pub struct Options {
138138
pub no_trans: bool,
139139
pub error_format: ErrorOutputType,
140140
pub treat_err_as_bug: bool,
141+
pub mir_opt_level: usize,
141142

142143
/// if true, build up the dep-graph
143144
pub build_dep_graph: bool,
@@ -254,6 +255,7 @@ pub fn basic_options() -> Options {
254255
parse_only: false,
255256
no_trans: false,
256257
treat_err_as_bug: false,
258+
mir_opt_level: 1,
257259
build_dep_graph: false,
258260
dump_dep_graph: false,
259261
no_analysis: false,
@@ -655,6 +657,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
655657
"show spans for compiler debugging (expr|pat|ty)"),
656658
print_trans_items: Option<String> = (None, parse_opt_string,
657659
"print the result of the translation item collection pass"),
660+
mir_opt_level: Option<usize> = (None, parse_opt_uint,
661+
"set the MIR optimization level (0-3)"),
658662
}
659663

660664
pub fn default_lib_output() -> CrateType {
@@ -988,6 +992,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
988992
let parse_only = debugging_opts.parse_only;
989993
let no_trans = debugging_opts.no_trans;
990994
let treat_err_as_bug = debugging_opts.treat_err_as_bug;
995+
let mir_opt_level = debugging_opts.mir_opt_level.unwrap_or(1);
991996
let incremental_compilation = debugging_opts.incr_comp;
992997
let dump_dep_graph = debugging_opts.dump_dep_graph;
993998
let no_analysis = debugging_opts.no_analysis;
@@ -1166,6 +1171,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
11661171
parse_only: parse_only,
11671172
no_trans: no_trans,
11681173
treat_err_as_bug: treat_err_as_bug,
1174+
mir_opt_level: mir_opt_level,
11691175
build_dep_graph: incremental_compilation || dump_dep_graph,
11701176
dump_dep_graph: dump_dep_graph,
11711177
no_analysis: no_analysis,

src/librustc/util/ppaux.rs

+3
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,9 @@ impl<'tcx> fmt::Debug for ty::adjustment::AutoAdjustment<'tcx> {
396396
ty::adjustment::AdjustUnsafeFnPointer => {
397397
write!(f, "AdjustUnsafeFnPointer")
398398
}
399+
ty::adjustment::AdjustMutToConstPointer => {
400+
write!(f, "AdjustMutToConstPointer")
401+
}
399402
ty::adjustment::AdjustDerefRef(ref data) => {
400403
write!(f, "{:?}", data)
401404
}

0 commit comments

Comments
 (0)