Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/librustc/ich/impls_mir.rs
Original file line number Diff line number Diff line change
@@ -22,7 +22,8 @@ impl_stable_hash_for!(struct mir::SourceInfo { span, scope });
impl_stable_hash_for!(enum mir::Mutability { Mut, Not });
impl_stable_hash_for!(enum mir::BorrowKind { Shared, Unique, Mut });
impl_stable_hash_for!(enum mir::LocalKind { Var, Temp, Arg, ReturnPointer });
impl_stable_hash_for!(struct mir::LocalDecl<'tcx> { mutability, ty, name, source_info });
impl_stable_hash_for!(struct mir::LocalDecl<'tcx> { mutability, ty, name, source_info,
is_user_variable});
impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref });
impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator, is_cleanup });
impl_stable_hash_for!(struct mir::Terminator<'tcx> { source_info, kind });
40 changes: 23 additions & 17 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
@@ -197,10 +197,10 @@ impl<'tcx> Mir<'tcx> {
pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
(self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
if self.local_decls[local].source_info.is_none() {
Some(local)
} else {
if self.local_decls[local].is_user_variable {
None
} else {
Some(local)
}
})
}
@@ -210,10 +210,10 @@ impl<'tcx> Mir<'tcx> {
pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
(self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
if self.local_decls[local].source_info.is_none() {
None
} else {
if self.local_decls[local].is_user_variable {
Some(local)
} else {
None
}
})
}
@@ -370,6 +370,9 @@ pub struct LocalDecl<'tcx> {
/// Temporaries and the return pointer are always mutable.
pub mutability: Mutability,

/// True if this corresponds to a user-declared local variable.
pub is_user_variable: bool,

/// Type of this local.
pub ty: Ty<'tcx>,

@@ -379,37 +382,40 @@ pub struct LocalDecl<'tcx> {
/// to generate better debuginfo.
pub name: Option<Name>,

/// For user-declared variables, stores their source information.
///
/// For temporaries, this is `None`.
///
/// This is the primary way to differentiate between user-declared
/// variables and compiler-generated temporaries.
pub source_info: Option<SourceInfo>,
/// Source info of the local.
pub source_info: SourceInfo,
}

impl<'tcx> LocalDecl<'tcx> {
/// Create a new `LocalDecl` for a temporary.
#[inline]
pub fn new_temp(ty: Ty<'tcx>) -> Self {
pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self {
LocalDecl {
mutability: Mutability::Mut,
ty: ty,
name: None,
source_info: None,
source_info: SourceInfo {
span: span,
scope: ARGUMENT_VISIBILITY_SCOPE
},
is_user_variable: false
}
}

/// Builds a `LocalDecl` for the return pointer.
///
/// This must be inserted into the `local_decls` list as the first local.
#[inline]
pub fn new_return_pointer(return_ty: Ty) -> LocalDecl {
pub fn new_return_pointer(return_ty: Ty, span: Span) -> LocalDecl {
LocalDecl {
mutability: Mutability::Mut,
ty: return_ty,
source_info: None,
source_info: SourceInfo {
span: span,
scope: ARGUMENT_VISIBILITY_SCOPE
},
name: None, // FIXME maybe we do want some name here?
is_user_variable: false
}
}
}
5 changes: 2 additions & 3 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
@@ -630,12 +630,11 @@ macro_rules! make_mir_visitor {
ref $($mutability)* ty,
name: _,
ref $($mutability)* source_info,
is_user_variable: _,
} = *local_decl;

self.visit_ty(ty);
if let Some(ref $($mutability)* info) = *source_info {
self.visit_source_info(info);
}
self.visit_source_info(source_info);
}

fn super_visibility_scope(&mut self,
6 changes: 3 additions & 3 deletions src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
Original file line number Diff line number Diff line change
@@ -307,12 +307,12 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
data
}

fn create_drop_flag(&mut self, index: MovePathIndex) {
fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) {
let tcx = self.tcx;
let patch = &mut self.patch;
debug!("create_drop_flag({:?})", self.mir.span);
self.drop_flags.entry(index).or_insert_with(|| {
patch.new_temp(tcx.types.bool)
patch.new_temp(tcx.types.bool, span)
});
}

@@ -374,7 +374,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
debug!("collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}",
child, location, path, (maybe_live, maybe_dead));
if maybe_live && maybe_dead {
self.create_drop_flag(child)
self.create_drop_flag(child, terminator.source_info.span)
}
});
}
8 changes: 2 additions & 6 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ use rustc_typeck as typeck;
use rustc_privacy;
use rustc_plugin::registry::Registry;
use rustc_plugin as plugin;
use rustc_passes::{ast_validation, no_asm, loops, consts, rvalues,
use rustc_passes::{ast_validation, no_asm, loops, consts,
static_recursion, hir_stats, mir_stats};
use rustc_const_eval::check_match;
use super::Compilation;
@@ -957,10 +957,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
"liveness checking",
|| middle::liveness::check_crate(tcx));

time(time_passes,
"rvalue checking",
|| rvalues::check_crate(tcx));

time(time_passes,
"MIR dump",
|| mir::mir_map::build_mir_for_crate(tcx));
@@ -976,8 +972,8 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
// in stage 4 below.
passes.push_hook(box mir::transform::dump_mir::DumpMir);
passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("initial"));
passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants);
passes.push_pass(box mir::transform::type_check::TypeckMir);
passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants);
passes.push_pass(
box mir::transform::simplify_branches::SimplifyBranches::new("initial"));
passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("qualify-consts"));
3 changes: 2 additions & 1 deletion src/librustc_mir/build/expr/as_lvalue.rs
Original file line number Diff line number Diff line change
@@ -62,7 +62,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let idx = unpack!(block = this.as_operand(block, None, index));

// bounds check:
let (len, lt) = (this.temp(usize_ty.clone()), this.temp(bool_ty));
let (len, lt) = (this.temp(usize_ty.clone(), expr_span),
this.temp(bool_ty, expr_span));
this.cfg.push_assign(block, source_info, // len = len(slice)
&len, Rvalue::Len(slice.clone()));
this.cfg.push_assign(block, source_info, // lt = idx < len
14 changes: 7 additions & 7 deletions src/librustc_mir/build/expr/as_rvalue.rs
Original file line number Diff line number Diff line change
@@ -82,7 +82,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let bool_ty = this.hir.bool_ty();

let minval = this.minval_literal(expr_span, expr.ty);
let is_min = this.temp(bool_ty);
let is_min = this.temp(bool_ty, expr_span);

this.cfg.push_assign(block, source_info, &is_min,
Rvalue::BinaryOp(BinOp::Eq, arg.clone(), minval));
@@ -95,7 +95,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
}
ExprKind::Box { value, value_extents } => {
let value = this.hir.mirror(value);
let result = this.temp(expr.ty);
let result = this.temp(expr.ty, expr_span);
// to start, malloc some memory of suitable type (thus far, uninitialized):
this.cfg.push_assign(block, source_info, &result, Rvalue::Box(value.ty));
this.in_scope(value_extents, block, |this| {
@@ -260,7 +260,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let bool_ty = self.hir.bool_ty();
if self.hir.check_overflow() && op.is_checkable() && ty.is_integral() {
let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty], false);
let result_value = self.temp(result_tup);
let result_value = self.temp(result_tup, span);

self.cfg.push_assign(block, source_info,
&result_value, Rvalue::CheckedBinaryOp(op,
@@ -301,7 +301,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
};

// Check for / 0
let is_zero = self.temp(bool_ty);
let is_zero = self.temp(bool_ty, span);
let zero = self.zero_literal(span, ty);
self.cfg.push_assign(block, source_info, &is_zero,
Rvalue::BinaryOp(BinOp::Eq, rhs.clone(), zero));
@@ -315,9 +315,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let neg_1 = self.neg_1_literal(span, ty);
let min = self.minval_literal(span, ty);

let is_neg_1 = self.temp(bool_ty);
let is_min = self.temp(bool_ty);
let of = self.temp(bool_ty);
let is_neg_1 = self.temp(bool_ty, span);
let is_min = self.temp(bool_ty, span);
let of = self.temp(bool_ty, span);

// this does (rhs == -1) & (lhs == MIN). It could short-circuit instead

2 changes: 1 addition & 1 deletion src/librustc_mir/build/expr/as_temp.rs
Original file line number Diff line number Diff line change
@@ -44,8 +44,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
}

let expr_ty = expr.ty.clone();
let temp = this.temp(expr_ty.clone());
let expr_span = expr.span;
let temp = this.temp(expr_ty.clone(), expr_span);
let source_info = this.source_info(expr_span);

if expr.temp_lifetime_was_shrunk && this.hir.needs_drop(expr_ty) {
2 changes: 1 addition & 1 deletion src/librustc_mir/build/expr/stmt.rs
Original file line number Diff line number Diff line change
@@ -138,7 +138,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
}
_ => {
let expr_ty = expr.ty;
let temp = this.temp(expr.ty.clone());
let temp = this.temp(expr.ty.clone(), expr_span);
unpack!(block = this.into(&temp, block, expr));
unpack!(block = this.build_drop(block, expr_span, temp, expr_ty));
block.unit()
3 changes: 2 additions & 1 deletion src/librustc_mir/build/matches/mod.rs
Original file line number Diff line number Diff line change
@@ -710,7 +710,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
mutability: mutability,
ty: var_ty.clone(),
name: Some(name),
source_info: Some(source_info),
source_info: source_info,
is_user_variable: true,
});
self.var_indices.insert(var_id, var);

13 changes: 7 additions & 6 deletions src/librustc_mir/build/matches/test.rs
Original file line number Diff line number Diff line change
@@ -210,7 +210,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
debug!("num_enum_variants: {}, tested variants: {:?}, variants: {:?}",
num_enum_variants, values, variants);
let discr_ty = adt_def.repr.discr_type().to_ty(tcx);
let discr = self.temp(discr_ty);
let discr = self.temp(discr_ty, test.span);
self.cfg.push_assign(block, source_info, &discr,
Rvalue::Discriminant(lvalue.clone()));
assert_eq!(values.len() + 1, targets.len());
@@ -270,7 +270,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
if let ty::TyRef(region, mt) = ty.sty {
if let ty::TyArray(_, _) = mt.ty.sty {
ty = tcx.mk_imm_ref(region, tcx.mk_slice(tcx.types.u8));
let val_slice = self.temp(ty);
let val_slice = self.temp(ty, test.span);
self.cfg.push_assign(block, source_info, &val_slice,
Rvalue::Cast(CastKind::Unsize, val, ty));
val = Operand::Consume(val_slice);
@@ -285,7 +285,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
value: value.clone()
});

let slice = self.temp(ty);
let slice = self.temp(ty, test.span);
self.cfg.push_assign(block, source_info, &slice,
Rvalue::Cast(CastKind::Unsize, array, ty));
Operand::Consume(slice)
@@ -304,7 +304,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty]);

let bool_ty = self.hir.bool_ty();
let eq_result = self.temp(bool_ty);
let eq_result = self.temp(bool_ty, test.span);
let eq_block = self.cfg.start_new_block();
let cleanup = self.diverge_cleanup();
self.cfg.terminate(block, source_info, TerminatorKind::Call {
@@ -349,7 +349,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {

TestKind::Len { len, op } => {
let (usize_ty, bool_ty) = (self.hir.usize_ty(), self.hir.bool_ty());
let (actual, result) = (self.temp(usize_ty), self.temp(bool_ty));
let (actual, result) = (self.temp(usize_ty, test.span),
self.temp(bool_ty, test.span));

// actual = len(lvalue)
self.cfg.push_assign(block, source_info,
@@ -383,7 +384,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
left: Operand<'tcx>,
right: Operand<'tcx>) -> BasicBlock {
let bool_ty = self.hir.bool_ty();
let result = self.temp(bool_ty);
let result = self.temp(bool_ty, span);

// result = op(left, right)
let source_info = self.source_info(span);
6 changes: 3 additions & 3 deletions src/librustc_mir/build/misc.rs
Original file line number Diff line number Diff line change
@@ -27,8 +27,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
///
/// NB: **No cleanup is scheduled for this temporary.** You should
/// call `schedule_drop` once the temporary is initialized.
pub fn temp(&mut self, ty: Ty<'tcx>) -> Lvalue<'tcx> {
let temp = self.local_decls.push(LocalDecl::new_temp(ty));
pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Lvalue<'tcx> {
let temp = self.local_decls.push(LocalDecl::new_temp(ty, span));
let lvalue = Lvalue::Local(temp);
debug!("temp: created temp {:?} with type {:?}",
lvalue, self.local_decls[temp].ty);
@@ -106,7 +106,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
value: u64)
-> Lvalue<'tcx> {
let usize_ty = self.hir.usize_ty();
let temp = self.temp(usize_ty);
let temp = self.temp(usize_ty, source_info.span);
self.cfg.push_assign_constant(
block, source_info, &temp,
Constant {
12 changes: 9 additions & 3 deletions src/librustc_mir/build/mod.rs
Original file line number Diff line number Diff line change
@@ -249,7 +249,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
visibility_scopes: IndexVec::new(),
visibility_scope: ARGUMENT_VISIBILITY_SCOPE,
breakable_scopes: vec![],
local_decls: IndexVec::from_elem_n(LocalDecl::new_return_pointer(return_ty), 1),
local_decls: IndexVec::from_elem_n(LocalDecl::new_return_pointer(return_ty,
span), 1),
var_indices: NodeMap(),
unit_temp: None,
cached_resume_block: None,
@@ -304,8 +305,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
self.local_decls.push(LocalDecl {
mutability: Mutability::Not,
ty: ty,
source_info: None,
source_info: SourceInfo {
scope: ARGUMENT_VISIBILITY_SCOPE,
span: pattern.map_or(self.fn_span, |pat| pat.span)
},
name: name,
is_user_variable: false,
});
}

@@ -341,7 +346,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
Some(ref tmp) => tmp.clone(),
None => {
let ty = self.hir.unit_ty();
let tmp = self.temp(ty);
let fn_span = self.fn_span;
let tmp = self.temp(ty, fn_span);
self.unit_temp = Some(tmp.clone());
tmp
}
33 changes: 33 additions & 0 deletions src/librustc_mir/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -244,6 +244,39 @@ let baz: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
```
"##,

E0161: r##"
A value was moved. However, its size was not known at compile time, and only
values of a known size can be moved.
Erroneous code example:
```compile_fail
#![feature(box_syntax)]
fn main() {
let array: &[isize] = &[1, 2, 3];
let _x: Box<[isize]> = box *array;
// error: cannot move a value of type [isize]: the size of [isize] cannot
// be statically determined
}
```
In Rust, you can only move a value when its size is known at compile time.
To work around this restriction, consider "hiding" the value behind a reference:
either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move
it around as usual. Example:
```
#![feature(box_syntax)]
fn main() {
let array: &[isize] = &[1, 2, 3];
let _x: Box<&[isize]> = box array; // ok!
}
```
"##,

E0396: r##"
The value behind a raw pointer can't be determined at compile-time
(or even link-time), which means it can't be used in a constant
23 changes: 14 additions & 9 deletions src/librustc_mir/shim.rs
Original file line number Diff line number Diff line change
@@ -137,16 +137,20 @@ enum CallKind {
Direct(DefId),
}

fn temp_decl(mutability: Mutability, ty: Ty) -> LocalDecl {
LocalDecl { mutability, ty, name: None, source_info: None }
fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl {
LocalDecl {
mutability, ty, name: None,
source_info: SourceInfo { scope: ARGUMENT_VISIBILITY_SCOPE, span },
is_user_variable: false
}
}

fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>)
fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>, span: Span)
-> IndexVec<Local, LocalDecl<'tcx>>
{
iter::once(temp_decl(Mutability::Mut, sig.output()))
iter::once(temp_decl(Mutability::Mut, sig.output(), span))
.chain(sig.inputs().iter().map(
|ity| temp_decl(Mutability::Not, ity)))
|ity| temp_decl(Mutability::Not, ity, span)))
.collect()
}

@@ -188,7 +192,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
),
IndexVec::new(),
sig.output(),
local_decls_for_sig(&sig),
local_decls_for_sig(&sig, span),
sig.inputs().len(),
vec![],
span
@@ -297,7 +301,7 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,

debug!("build_call_shim: sig={:?}", sig);

let mut local_decls = local_decls_for_sig(&sig);
let mut local_decls = local_decls_for_sig(&sig, span);
let source_info = SourceInfo { span, scope: ARGUMENT_VISIBILITY_SCOPE };

let rcvr_arg = Local::new(1+0);
@@ -317,7 +321,8 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
tcx.mk_ref(re_erased, ty::TypeAndMut {
ty: sig.inputs()[0],
mutbl: hir::Mutability::MutMutable
})
}),
span
));
statements.push(Statement {
source_info: source_info,
@@ -442,7 +447,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,

debug!("build_ctor: def_id={:?} sig={:?} fields={:?}", def_id, sig, fields);

let local_decls = local_decls_for_sig(&sig);
let local_decls = local_decls_for_sig(&sig, span);

let source_info = SourceInfo {
span: span,
15 changes: 6 additions & 9 deletions src/librustc_mir/transform/inline.rs
Original file line number Diff line number Diff line change
@@ -461,11 +461,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
for loc in callee_mir.vars_and_temps_iter() {
let mut local = callee_mir.local_decls[loc].clone();

if let Some(ref mut source_info) = local.source_info {
source_info.scope = scope_map[source_info.scope];

source_info.span = callsite.location.span;
}
local.source_info.scope = scope_map[local.source_info.scope];
local.source_info.span = callsite.location.span;

let idx = caller_mir.local_decls.push(local);
local_map.push(idx);
@@ -506,7 +503,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {

let ty = dest.ty(caller_mir, self.tcx);

let temp = LocalDecl::new_temp(ty);
let temp = LocalDecl::new_temp(ty, callsite.location.span);

let tmp = caller_mir.local_decls.push(temp);
let tmp = Lvalue::Local(tmp);
@@ -590,7 +587,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
arg.deref());

let ty = arg.ty(caller_mir, self.tcx);
let ref_tmp = LocalDecl::new_temp(ty);
let ref_tmp = LocalDecl::new_temp(ty, callsite.location.span);
let ref_tmp = caller_mir.local_decls.push(ref_tmp);
let ref_tmp = Lvalue::Local(ref_tmp);

@@ -611,7 +608,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {

let raw_ptr = Rvalue::Cast(CastKind::Misc, Operand::Consume(ref_tmp), ptr_ty);

let cast_tmp = LocalDecl::new_temp(ptr_ty);
let cast_tmp = LocalDecl::new_temp(ptr_ty, callsite.location.span);
let cast_tmp = caller_mir.local_decls.push(cast_tmp);
let cast_tmp = Lvalue::Local(cast_tmp);

@@ -645,7 +642,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {

let ty = arg.ty(caller_mir, tcx);

let arg_tmp = LocalDecl::new_temp(ty);
let arg_tmp = LocalDecl::new_temp(ty, callsite.location.span);
let arg_tmp = caller_mir.local_decls.push(arg_tmp);
let arg_tmp = Lvalue::Local(arg_tmp);

6 changes: 4 additions & 2 deletions src/librustc_mir/transform/promote_consts.rs
Original file line number Diff line number Diff line change
@@ -208,7 +208,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {

let no_stmts = self.source[loc.block].statements.len();
let new_temp = self.promoted.local_decls.push(
LocalDecl::new_temp(self.source.local_decls[temp].ty));
LocalDecl::new_temp(self.source.local_decls[temp].ty,
self.source.local_decls[temp].source_info.span));

debug!("promote({:?} @ {:?}/{:?}, {:?})",
temp, loc, no_stmts, self.keep_original);
@@ -379,7 +380,8 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
};

// Declare return pointer local
let initial_locals = iter::once(LocalDecl::new_return_pointer(ty)).collect();
let initial_locals = iter::once(LocalDecl::new_return_pointer(ty, span))
.collect();

let mut promoter = Promoter {
promoted: Mir::new(
2 changes: 1 addition & 1 deletion src/librustc_mir/transform/qualify_consts.rs
Original file line number Diff line number Diff line change
@@ -881,7 +881,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
// Avoid a generic error for other uses of arguments.
if self.qualif.intersects(Qualif::FN_ARGUMENT) {
let decl = &self.mir.local_decls[index];
span_err!(self.tcx.sess, decl.source_info.unwrap().span, E0022,
span_err!(self.tcx.sess, decl.source_info.span, E0022,
"arguments of constant functions can only \
be immutable by-value bindings");
return;
52 changes: 48 additions & 4 deletions src/librustc_mir/transform/type_check.rs
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@ use std::fmt;
use syntax::ast;
use syntax_pos::{Span, DUMMY_SP};

use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::indexed_vec::Idx;

fn mirbug(tcx: TyCtxt, span: Span, msg: &str) {
@@ -87,6 +88,11 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
self.sanitize_type(rvalue, rval_ty);
}

fn visit_local_decl(&mut self, local_decl: &LocalDecl<'tcx>) {
self.super_local_decl(local_decl);
self.sanitize_type(local_decl, local_decl.ty);
}

fn visit_mir(&mut self, mir: &Mir<'tcx>) {
self.sanitize_type(&"return type", mir.return_ty);
for local_decl in &mir.local_decls {
@@ -317,6 +323,7 @@ pub struct TypeChecker<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
fulfillment_cx: traits::FulfillmentContext<'tcx>,
last_span: Span,
body_id: ast::NodeId,
reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
}

impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
@@ -326,6 +333,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
fulfillment_cx: traits::FulfillmentContext::new(),
last_span: DUMMY_SP,
body_id: body_id,
reported_errors: FxHashSet(),
}
}

@@ -641,9 +649,43 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
}
}

fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
fn check_local(&mut self, mir: &Mir<'gcx>, local: Local, local_decl: &LocalDecl<'gcx>) {
match mir.local_kind(local) {
LocalKind::ReturnPointer | LocalKind::Arg => {
// return values of normal functions are required to be
// sized by typeck, but return values of ADT constructors are
// not because we don't include a `Self: Sized` bounds on them.
//
// Unbound parts of arguments were never required to be Sized
// - maybe we should make that a warning.
return
}
LocalKind::Var | LocalKind::Temp => {}
}

let span = local_decl.source_info.span;
let ty = local_decl.ty;
if !ty.is_sized(self.tcx().global_tcx(), self.infcx.param_env(), span) {
// in current MIR construction, all non-control-flow rvalue
// expressions evaluate through `as_temp` or `into` a return
// slot or local, so to find all unsized rvalues it is enough
// to check all temps, return slots and locals.
if let None = self.reported_errors.replace((ty, span)) {
span_err!(self.tcx().sess, span, E0161,
"cannot move a value of type {0}: the size of {0} \
cannot be statically determined", ty);
}
}
}

fn typeck_mir(&mut self, mir: &Mir<'gcx>) {
self.last_span = mir.span;
debug!("run_on_mir: {:?}", mir.span);

for (local, local_decl) in mir.local_decls.iter_enumerated() {
self.check_local(mir, local, local_decl);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, can't there be assignments between, say, two dereferences? Is there any guarantee there would be a Local? If so, a comment would be helpful.


for block in mir.basic_blocks() {
for stmt in &block.statements {
if stmt.source_info.span != DUMMY_SP {
@@ -698,16 +740,18 @@ impl TypeckMir {
impl<'tcx> MirPass<'tcx> for TypeckMir {
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource, mir: &mut Mir<'tcx>) {
debug!("run_pass: {}", tcx.node_path_str(src.item_id()));
let item_id = src.item_id();
let def_id = tcx.hir.local_def_id(item_id);
debug!("run_pass: {}", tcx.item_path_str(def_id));

if tcx.sess.err_count() > 0 {
// compiling a broken program can obviously result in a
// broken MIR, so try not to report duplicate errors.
return;
}
let param_env = ty::ParameterEnvironment::for_item(tcx, src.item_id());
let param_env = ty::ParameterEnvironment::for_item(tcx, item_id);
tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
let mut checker = TypeChecker::new(&infcx, src.item_id());
let mut checker = TypeChecker::new(&infcx, item_id);
{
let mut verifier = TypeVerifier::new(&mut checker, mir);
verifier.visit_mir(mir);
2 changes: 1 addition & 1 deletion src/librustc_mir/util/elaborate_drops.rs
Original file line number Diff line number Diff line change
@@ -686,7 +686,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
}

fn new_temp(&mut self, ty: Ty<'tcx>) -> Local {
self.elaborator.patch().new_temp(ty)
self.elaborator.patch().new_temp(ty, self.source_info.span)
}

fn terminator_loc(&mut self, bb: BasicBlock) -> Location {
5 changes: 3 additions & 2 deletions src/librustc_mir/util/patch.rs
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@
use rustc::ty::Ty;
use rustc::mir::*;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use syntax_pos::Span;

/// This struct represents a patch to MIR, which can add
/// new statements and basic blocks and patch over block
@@ -92,10 +93,10 @@ impl<'tcx> MirPatch<'tcx> {
}
}

pub fn new_temp(&mut self, ty: Ty<'tcx>) -> Local {
pub fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local {
let index = self.next_local;
self.next_local += 1;
self.new_locals.push(LocalDecl::new_temp(ty));
self.new_locals.push(LocalDecl::new_temp(ty, span));
Local::new(index as usize)
}

4 changes: 2 additions & 2 deletions src/librustc_mir/util/pretty.rs
Original file line number Diff line number Diff line change
@@ -196,8 +196,8 @@ fn write_scope_tree(tcx: TyCtxt,
// User variable types (including the user's name in a comment).
for local in mir.vars_iter() {
let var = &mir.local_decls[local];
let (name, source_info) = if var.source_info.unwrap().scope == child {
(var.name.unwrap(), var.source_info.unwrap())
let (name, source_info) = if var.source_info.scope == child {
(var.name.unwrap(), var.source_info)
} else {
// Not a variable or not declared in this scope.
continue;
33 changes: 0 additions & 33 deletions src/librustc_passes/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -82,39 +82,6 @@ extern {
```
"##,

E0161: r##"
A value was moved. However, its size was not known at compile time, and only
values of a known size can be moved.
Erroneous code example:
```compile_fail
#![feature(box_syntax)]
fn main() {
let array: &[isize] = &[1, 2, 3];
let _x: Box<[isize]> = box *array;
// error: cannot move a value of type [isize]: the size of [isize] cannot
// be statically determined
}
```
In Rust, you can only move a value when its size is known at compile time.
To work around this restriction, consider "hiding" the value behind a reference:
either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move
it around as usual. Example:
```
#![feature(box_syntax)]
fn main() {
let array: &[isize] = &[1, 2, 3];
let _x: Box<&[isize]> = box array; // ok!
}
```
"##,

E0265: r##"
This error indicates that a static or constant references itself.
All statics and constants need to resolve to a value in an acyclic manner.
1 change: 0 additions & 1 deletion src/librustc_passes/lib.rs
Original file line number Diff line number Diff line change
@@ -47,5 +47,4 @@ pub mod hir_stats;
pub mod loops;
pub mod mir_stats;
pub mod no_asm;
pub mod rvalues;
pub mod static_recursion;
103 changes: 0 additions & 103 deletions src/librustc_passes/rvalues.rs

This file was deleted.

2 changes: 1 addition & 1 deletion src/librustc_trans/debuginfo/create_scope_map.rs
Original file line number Diff line number Diff line change
@@ -65,7 +65,7 @@ pub fn create_mir_scopes(ccx: &CrateContext, mir: &Mir, debug_context: &Function
let mut has_variables = BitVector::new(mir.visibility_scopes.len());
for var in mir.vars_iter() {
let decl = &mir.local_decls[var];
has_variables.insert(decl.source_info.unwrap().scope.index());
has_variables.insert(decl.source_info.scope.index());
}

// Instantiate all scopes.
5 changes: 2 additions & 3 deletions src/librustc_trans/mir/mod.rs
Original file line number Diff line number Diff line change
@@ -255,8 +255,7 @@ pub fn trans_mir<'a, 'tcx: 'a>(

if let Some(name) = decl.name {
// User variable
let source_info = decl.source_info.unwrap();
let debug_scope = mircx.scopes[source_info.scope];
let debug_scope = mircx.scopes[decl.source_info.scope];
let dbg = debug_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo;

if !lvalue_locals.contains(local.index()) && !dbg {
@@ -268,7 +267,7 @@ pub fn trans_mir<'a, 'tcx: 'a>(
assert!(!ty.has_erasable_regions());
let lvalue = LvalueRef::alloca(&bcx, ty, &name.as_str());
if dbg {
let (scope, span) = mircx.debug_loc(source_info);
let (scope, span) = mircx.debug_loc(decl.source_info);
declare_local(&bcx, &mircx.debug_context, name, ty, scope,
VariableAccess::DirectVariable { alloca: lvalue.llval },
VariableKind::LocalVariable, span);
18 changes: 18 additions & 0 deletions src/test/compile-fail/issue-41139.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

trait Trait {}

fn get_function<'a>() -> &'a Fn() -> Trait { panic!("") }

fn main() {
let t : &Trait = &get_function()();
//~^ ERROR cannot move a value of type Trait + 'static
}