Skip to content

Commit

Permalink
Auto merge of #31474 - arielb1:mir-typeck, r=nikomatsakis
Browse files Browse the repository at this point in the history
This should stop broken MIR from annoying us when we try to implement things
  • Loading branch information
bors committed Feb 20, 2016
2 parents cfabd17 + d84658e commit 6c751e0
Show file tree
Hide file tree
Showing 43 changed files with 1,509 additions and 190 deletions.
5 changes: 3 additions & 2 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,10 +721,11 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
if let Some(adjustment) = adj {
match adjustment {
adjustment::AdjustReifyFnPointer |
adjustment::AdjustUnsafeFnPointer => {
adjustment::AdjustUnsafeFnPointer |
adjustment::AdjustMutToConstPointer => {
// Creating a closure/fn-pointer or unsizing consumes
// the input and stores it into the resulting rvalue.
debug!("walk_adjustment(AdjustReifyFnPointer|AdjustUnsafeFnPointer)");
debug!("walk_adjustment: trivial adjustment");
let cmt_unadjusted =
return_if_err!(self.mc.cat_expr_unadjusted(expr));
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {

adjustment::AdjustReifyFnPointer |
adjustment::AdjustUnsafeFnPointer |
adjustment::AdjustMutToConstPointer |
adjustment::AdjustDerefRef(_) => {
debug!("cat_expr({:?}): {:?}",
adjustment,
Expand Down
31 changes: 24 additions & 7 deletions src/librustc/middle/ty/adjustment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ use rustc_front::hir;

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

Expand Down Expand Up @@ -106,7 +107,8 @@ impl<'tcx> AutoAdjustment<'tcx> {
pub fn is_identity(&self) -> bool {
match *self {
AdjustReifyFnPointer |
AdjustUnsafeFnPointer => false,
AdjustUnsafeFnPointer |
AdjustMutToConstPointer => false,
AdjustDerefRef(ref r) => r.is_identity(),
}
}
Expand Down Expand Up @@ -151,7 +153,7 @@ impl<'tcx> ty::TyS<'tcx> {
return match adjustment {
Some(adjustment) => {
match *adjustment {
AdjustReifyFnPointer => {
AdjustReifyFnPointer => {
match self.sty {
ty::TyBareFn(Some(_), b) => {
cx.mk_fn(None, b)
Expand All @@ -164,17 +166,32 @@ impl<'tcx> ty::TyS<'tcx> {
}
}

AdjustUnsafeFnPointer => {
AdjustUnsafeFnPointer => {
match self.sty {
ty::TyBareFn(None, b) => cx.safe_to_unsafe_fn_ty(b),
ref b => {
cx.sess.bug(
&format!("AdjustReifyFnPointer adjustment on non-fn-item: \
&format!("AdjustUnsafeFnPointer adjustment on non-fn-ptr: \
{:?}",
b));
}
}
}
}

AdjustMutToConstPointer => {
match self.sty {
ty::TyRawPtr(mt) => cx.mk_ptr(ty::TypeAndMut {
ty: mt.ty,
mutbl: hir::MutImmutable
}),
ref b => {
cx.sess.bug(
&format!("AdjustMutToConstPointer on non-raw-ptr: \
{:?}",
b));
}
}
}

AdjustDerefRef(ref adj) => {
let mut adjusted_ty = self;
Expand Down
7 changes: 7 additions & 0 deletions src/librustc/middle/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ pub struct Tables<'tcx> {
/// equivalents. This table is not used in trans (since regions
/// are erased there) and hence is not serialized to metadata.
pub liberated_fn_sigs: NodeMap<ty::FnSig<'tcx>>,

/// For each FRU expression, record the normalized types of the fields
/// of the struct - this is needed because it is non-trivial to
/// normalize while preserving regions. This table is used only in
/// MIR construction and hence is not serialized to metadata.
pub fru_field_types: NodeMap<Vec<Ty<'tcx>>>
}

impl<'tcx> Tables<'tcx> {
Expand All @@ -144,6 +150,7 @@ impl<'tcx> Tables<'tcx> {
closure_tys: DefIdMap(),
closure_kinds: DefIdMap(),
liberated_fn_sigs: NodeMap(),
fru_field_types: NodeMap()
}
}

Expand Down
14 changes: 12 additions & 2 deletions src/librustc/mir/mir_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,30 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use dep_graph::DepNode;
use util::nodemap::NodeMap;
use mir::repr::Mir;
use mir::transform::MirPass;
use middle::ty;
use middle::infer;

pub struct MirMap<'tcx> {
pub map: NodeMap<Mir<'tcx>>,
}

impl<'tcx> MirMap<'tcx> {
pub fn run_passes(&mut self, passes: &mut [Box<MirPass>], tcx: &ty::ctxt<'tcx>) {
for (_, ref mut mir) in &mut self.map {
if passes.is_empty() { return; }

for (&id, mir) in &mut self.map {
let did = tcx.map.local_def_id(id);
let _task = tcx.dep_graph.in_task(DepNode::MirMapConstruction(did));

let param_env = ty::ParameterEnvironment::for_item(tcx, id);
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env));

for pass in &mut *passes {
pass.run_on_mir(mir, tcx)
pass.run_on_mir(mir, &infcx)
}
}
}
Expand Down
19 changes: 11 additions & 8 deletions src/librustc/mir/repr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ pub struct Mir<'tcx> {
/// values in that it is possible to borrow them and mutate them
/// through the resulting reference.
pub temp_decls: Vec<TempDecl<'tcx>>,

/// A span representing this MIR, for error reporting
pub span: Span,
}

/// where execution begins
Expand Down Expand Up @@ -145,7 +148,7 @@ pub enum BorrowKind {

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

/// A "temp" is a temporary that we place on the stack. They are
/// anonymous, always mutable, and have only a type.
#[derive(Clone, RustcEncodable, RustcDecodable)]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct TempDecl<'tcx> {
pub ty: Ty<'tcx>,
}
Expand All @@ -170,7 +173,7 @@ pub struct TempDecl<'tcx> {
///
/// there is only one argument, of type `(i32, u32)`, but two bindings
/// (`x` and `y`).
#[derive(Clone, RustcEncodable, RustcDecodable)]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct ArgDecl<'tcx> {
pub ty: Ty<'tcx>,
}
Expand Down Expand Up @@ -499,7 +502,7 @@ pub struct Projection<'tcx, B, V> {
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub enum ProjectionElem<'tcx, V> {
Deref,
Field(Field),
Field(Field, Ty<'tcx>),
Index(V),

/// These indices are generated by slice patterns. Easiest to explain
Expand Down Expand Up @@ -550,8 +553,8 @@ impl Field {
}

impl<'tcx> Lvalue<'tcx> {
pub fn field(self, f: Field) -> Lvalue<'tcx> {
self.elem(ProjectionElem::Field(f))
pub fn field(self, f: Field, ty: Ty<'tcx>) -> Lvalue<'tcx> {
self.elem(ProjectionElem::Field(f, ty))
}

pub fn deref(self) -> Lvalue<'tcx> {
Expand Down Expand Up @@ -591,8 +594,8 @@ impl<'tcx> Debug for Lvalue<'tcx> {
write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].name),
ProjectionElem::Deref =>
write!(fmt, "(*{:?})", data.base),
ProjectionElem::Field(field) =>
write!(fmt, "{:?}.{:?}", data.base, field.index()),
ProjectionElem::Field(field, ty) =>
write!(fmt, "({:?}.{:?}: {:?})", data.base, field.index(), ty),
ProjectionElem::Index(ref index) =>
write!(fmt, "{:?}[{:?}]", data.base, index),
ProjectionElem::ConstantIndex { offset, min_length, from_end: false } =>
Expand Down
88 changes: 70 additions & 18 deletions src/librustc/mir/tcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
*/

use mir::repr::*;
use middle::subst::Substs;
use middle::const_eval::ConstVal;
use middle::subst::{Subst, Substs};
use middle::ty::{self, AdtDef, Ty};
use rustc_front::hir;

Expand Down Expand Up @@ -72,23 +73,7 @@ impl<'tcx> LvalueTy<'tcx> {
tcx.sess.bug(&format!("cannot downcast non-enum type: `{:?}`", self))
}
},
ProjectionElem::Field(field) => {
let field_ty = match self {
LvalueTy::Ty { ty } => match ty.sty {
ty::TyStruct(adt_def, substs) =>
adt_def.struct_variant().fields[field.index()].ty(tcx, substs),
ty::TyTuple(ref tys) =>
tys[field.index()],
ty::TyClosure(_, ref closure_substs) =>
closure_substs.upvar_tys[field.index()],
_ =>
tcx.sess.bug(&format!("cannot get field of type: `{:?}`", ty)),
},
LvalueTy::Downcast { adt_def, substs, variant_index } =>
adt_def.variants[variant_index].fields[field.index()].ty(tcx, substs),
};
LvalueTy::Ty { ty: field_ty }
}
ProjectionElem::Field(_, fty) => LvalueTy::Ty { ty: fty }
}
}
}
Expand Down Expand Up @@ -150,6 +135,73 @@ impl<'tcx> Mir<'tcx> {
self.lvalue_ty(tcx, &proj.base).projection_ty(tcx, &proj.elem)
}
}

pub fn rvalue_ty(&self,
tcx: &ty::ctxt<'tcx>,
rvalue: &Rvalue<'tcx>)
-> Option<Ty<'tcx>>
{
match *rvalue {
Rvalue::Use(ref operand) => Some(self.operand_ty(tcx, operand)),
Rvalue::Repeat(ref operand, ref count) => {
if let ConstVal::Uint(u) = count.value {
let op_ty = self.operand_ty(tcx, operand);
Some(tcx.mk_array(op_ty, u as usize))
} else {
None
}
}
Rvalue::Ref(reg, bk, ref lv) => {
let lv_ty = self.lvalue_ty(tcx, lv).to_ty(tcx);
Some(tcx.mk_ref(
tcx.mk_region(reg),
ty::TypeAndMut {
ty: lv_ty,
mutbl: bk.to_mutbl_lossy()
}
))
}
Rvalue::Len(..) => Some(tcx.types.usize),
Rvalue::Cast(_, _, ty) => Some(ty),
Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
let lhs_ty = self.operand_ty(tcx, lhs);
let rhs_ty = self.operand_ty(tcx, rhs);
Some(self.binop_ty(tcx, op, lhs_ty, rhs_ty))
}
Rvalue::UnaryOp(_, ref operand) => {
Some(self.operand_ty(tcx, operand))
}
Rvalue::Box(t) => {
Some(tcx.mk_box(t))
}
Rvalue::Aggregate(ref ak, ref ops) => {
match *ak {
AggregateKind::Vec => {
if let Some(operand) = ops.get(0) {
let ty = self.operand_ty(tcx, operand);
Some(tcx.mk_array(ty, ops.len()))
} else {
None
}
}
AggregateKind::Tuple => {
Some(tcx.mk_tup(
ops.iter().map(|op| self.operand_ty(tcx, op)).collect()
))
}
AggregateKind::Adt(def, _, substs) => {
Some(def.type_scheme(tcx).ty.subst(tcx, substs))
}
AggregateKind::Closure(did, substs) => {
Some(tcx.mk_closure_from_closure_substs(
did, Box::new(substs.clone())))
}
}
}
Rvalue::Slice { .. } => None,
Rvalue::InlineAsm(..) => None
}
}
}

impl BorrowKind {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/mir/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
// except according to those terms.

use mir::repr::Mir;
use middle::ty::ctxt;
use middle::infer::InferCtxt;

pub trait MirPass {
fn run_on_mir<'tcx>(&mut self, mir: &mut Mir<'tcx>, tcx: &ctxt<'tcx>);
fn run_on_mir<'a, 'tcx>(&mut self, mir: &mut Mir<'tcx>, infcx: &InferCtxt<'a, 'tcx>);
}
6 changes: 6 additions & 0 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ pub struct Options {
pub no_trans: bool,
pub error_format: ErrorOutputType,
pub treat_err_as_bug: bool,
pub mir_opt_level: usize,

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

pub fn default_lib_output() -> CrateType {
Expand Down Expand Up @@ -988,6 +992,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
let parse_only = debugging_opts.parse_only;
let no_trans = debugging_opts.no_trans;
let treat_err_as_bug = debugging_opts.treat_err_as_bug;
let mir_opt_level = debugging_opts.mir_opt_level.unwrap_or(1);
let incremental_compilation = debugging_opts.incr_comp;
let dump_dep_graph = debugging_opts.dump_dep_graph;
let no_analysis = debugging_opts.no_analysis;
Expand Down Expand Up @@ -1166,6 +1171,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
parse_only: parse_only,
no_trans: no_trans,
treat_err_as_bug: treat_err_as_bug,
mir_opt_level: mir_opt_level,
build_dep_graph: incremental_compilation || dump_dep_graph,
dump_dep_graph: dump_dep_graph,
no_analysis: no_analysis,
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/util/ppaux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,9 @@ impl<'tcx> fmt::Debug for ty::adjustment::AutoAdjustment<'tcx> {
ty::adjustment::AdjustUnsafeFnPointer => {
write!(f, "AdjustUnsafeFnPointer")
}
ty::adjustment::AdjustMutToConstPointer => {
write!(f, "AdjustMutToConstPointer")
}
ty::adjustment::AdjustDerefRef(ref data) => {
write!(f, "{:?}", data)
}
Expand Down
Loading

0 comments on commit 6c751e0

Please sign in to comment.