Skip to content
Closed
9 changes: 4 additions & 5 deletions src/librustc/middle/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ use middle::const_eval::{const_expr_to_pat, lookup_const_by_id};
use middle::const_eval::EvalHint::ExprTypeChecked;
use middle::def::*;
use middle::def_id::{DefId};
use middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Init};
use middle::expr_use_visitor::{JustWrite, LoanCause, MutateMode};
use middle::expr_use_visitor::WriteAndRead;
use middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
use middle::expr_use_visitor::{LoanCause, MutateMode};
use middle::expr_use_visitor as euv;
use middle::infer;
use middle::mem_categorization::{cmt};
Expand Down Expand Up @@ -1161,10 +1160,10 @@ impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> {
fn decl_without_init(&mut self, _: NodeId, _: Span) {}
fn mutate(&mut self, _: NodeId, span: Span, _: cmt, mode: MutateMode) {
match mode {
JustWrite | WriteAndRead => {
MutateMode::JustWrite | MutateMode::WriteAndRead => {
span_err!(self.cx.tcx.sess, span, E0302, "cannot assign in a pattern guard")
}
Init => {}
MutateMode::Init => {}
}
}
}
Expand Down
13 changes: 8 additions & 5 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
//! normal visitor, which just walks the entire body in one shot, the
//! `ExprUseVisitor` determines how expressions are being used.

pub use self::MutateMode::*;
pub use self::LoanCause::*;
pub use self::ConsumeMode::*;
pub use self::MoveReason::*;
Expand Down Expand Up @@ -465,7 +464,11 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
self.consume_expr(&*output.expr);
} else {
self.mutate_expr(expr, &*output.expr,
if output.is_rw { WriteAndRead } else { JustWrite });
if output.is_rw {
MutateMode::WriteAndRead
} else {
MutateMode::JustWrite
});
}
}
}
Expand Down Expand Up @@ -519,7 +522,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
}

hir::ExprAssign(ref lhs, ref rhs) => {
self.mutate_expr(expr, &**lhs, JustWrite);
self.mutate_expr(expr, &**lhs, MutateMode::JustWrite);
self.consume_expr(&**rhs);
}

Expand All @@ -532,7 +535,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
assert!(::rustc_front::util::is_by_value_binop(op.node));

if !self.walk_overloaded_operator(expr, lhs, vec![rhs], PassArgs::ByValue) {
self.mutate_expr(expr, &**lhs, WriteAndRead);
self.mutate_expr(expr, &**lhs, MutateMode::WriteAndRead);
self.consume_expr(&**rhs);
}
}
Expand Down Expand Up @@ -991,7 +994,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
let def = def_map.borrow().get(&pat.id).unwrap().full_def();
match mc.cat_def(pat.id, pat.span, pat_ty, def) {
Ok(binding_cmt) => {
delegate.mutate(pat.id, pat.span, binding_cmt, Init);
delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init);
}
Err(_) => { }
}
Expand Down
13 changes: 11 additions & 2 deletions src/librustc/mir/repr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,10 +314,19 @@ impl<'tcx> CallKind<'tcx> {
}
}

pub fn destination(&self) -> Option<Lvalue<'tcx>> {
pub fn destination(&self) -> Option<&Lvalue<'tcx>> {
match *self {
CallKind::Converging { ref destination, .. } |
CallKind::ConvergingCleanup { ref destination, .. } => Some(destination.clone()),
CallKind::ConvergingCleanup { ref destination, .. } => Some(destination),
CallKind::Diverging |
CallKind::DivergingCleanup(_) => None
}
}

pub fn destination_mut(&mut self) -> Option<&mut Lvalue<'tcx>> {
match *self {
CallKind::Converging { ref mut destination, .. } |
CallKind::ConvergingCleanup { ref mut destination, .. } => Some(destination),
CallKind::Diverging |
CallKind::DivergingCleanup(_) => None
}
Expand Down
5 changes: 3 additions & 2 deletions src/librustc_borrowck/borrowck/check_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use self::UseError::*;
use borrowck::*;
use borrowck::InteriorKind::{InteriorElement, InteriorField};
use rustc::middle::expr_use_visitor as euv;
use rustc::middle::expr_use_visitor::MutateMode;
use rustc::middle::infer;
use rustc::middle::mem_categorization as mc;
use rustc::middle::mem_categorization::Categorization;
Expand Down Expand Up @@ -161,7 +162,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
match opt_loan_path(&assignee_cmt) {
Some(lp) => {
match mode {
euv::Init | euv::JustWrite => {
MutateMode::Init | MutateMode::JustWrite => {
// In a case like `path = 1`, then path does not
// have to be *FULLY* initialized, but we still
// must be careful lest it contains derefs of
Expand All @@ -171,7 +172,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
MovedInUse,
&lp);
}
euv::WriteAndRead => {
MutateMode::WriteAndRead => {
// In a case like `path += 1`, then path must be
// fully initialized, since we will read it before
// we write it.
Expand Down
5 changes: 3 additions & 2 deletions src/librustc_borrowck/borrowck/move_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use rustc::middle::dataflow::BitwiseOperator;
use rustc::middle::dataflow::DataFlowOperator;
use rustc::middle::dataflow::KillFrom;
use rustc::middle::expr_use_visitor as euv;
use rustc::middle::expr_use_visitor::MutateMode;
use rustc::middle::ty;
use rustc::util::nodemap::{FnvHashMap, NodeSet};

Expand Down Expand Up @@ -406,10 +407,10 @@ impl<'tcx> MoveData<'tcx> {
self.fragments.borrow_mut().add_assignment(path_index);

match mode {
euv::Init | euv::JustWrite => {
MutateMode::Init | MutateMode::JustWrite => {
self.assignee_ids.borrow_mut().insert(assignee_id);
}
euv::WriteAndRead => { }
MutateMode::WriteAndRead => { }
}

let assignment = Assignment {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ fn write_basic_block<W: Write>(block: BasicBlock, mir: &Mir, w: &mut W) -> io::R
}

// Terminator at the bottom.
try!(writeln!(w, "{0}{0}{1:?};", INDENT, data.terminator));
try!(writeln!(w, "{0}{0}{1:?};", INDENT, data.terminator()));

writeln!(w, "{}}}", INDENT)
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/transform/erase_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl<'a, 'tcx> EraseRegions<'a, 'tcx> {
*switch_ty = self.tcx.erase_regions(switch_ty);
},
Terminator::Call { ref mut func, ref mut args, ref mut kind } => {
if let Some(ref mut destination) = kind.destination() {
if let Some(destination) = kind.destination_mut() {
self.erase_regions_lvalue(destination);
}
self.erase_regions_operand(func);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {

debug!("(build reduced graph for item) found extern `{}`",
module_to_string(&*external_module));
self.check_for_conflicts_between_external_crates(&**parent, name, sp);
self.check_for_conflicts_for_external_crate(&parent, name, sp);
parent.external_module_children
.borrow_mut()
.insert(name, external_module.clone());
Expand Down
33 changes: 21 additions & 12 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ enum SuggestionType {
}

pub enum ResolutionError<'a> {
/// error E0260: name conflicts with an extern crate
NameConflictsWithExternCrate(Name),
/// error E0401: can't use type parameters from outer function
TypeParametersFromOuterFunction,
/// error E0402: cannot use an outer type parameter in this context
Expand Down Expand Up @@ -228,6 +230,14 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
}

match resolution_error {
ResolutionError::NameConflictsWithExternCrate(name) => {
struct_span_err!(resolver.session,
span,
E0260,
"the name `{}` conflicts with an external crate \
that has been imported into this module",
name)
}
ResolutionError::TypeParametersFromOuterFunction => {
struct_span_err!(resolver.session,
span,
Expand Down Expand Up @@ -1297,19 +1307,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}

/// Checks that the names of external crates don't collide with other
/// external crates.
fn check_for_conflicts_between_external_crates(&self,
module: &Module,
name: Name,
span: Span) {
/// Check that an external crate doesn't collide with items or other external crates.
fn check_for_conflicts_for_external_crate(&self, module: &Module, name: Name, span: Span) {
if module.external_module_children.borrow().contains_key(&name) {
span_err!(self.session,
span,
E0259,
"an external crate named `{}` has already been imported into this module",
name);
}
match module.children.borrow().get(&name) {
Some(name_bindings) if name_bindings.type_ns.defined() => {
resolve_error(self,
name_bindings.type_ns.span().unwrap_or(codemap::DUMMY_SP),
ResolutionError::NameConflictsWithExternCrate(name));
}
_ => {},
}
}

/// Checks that the names of items don't collide with external crates.
Expand All @@ -1318,12 +1332,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
name: Name,
span: Span) {
if module.external_module_children.borrow().contains_key(&name) {
span_err!(self.session,
span,
E0260,
"the name `{}` conflicts with an external crate that has been imported \
into this module",
name);
resolve_error(self, span, ResolutionError::NameConflictsWithExternCrate(name));
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/trans/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
let mut llargs = Vec::with_capacity(args.len() + 1);

// Prepare the return value destination
let (ret_dest_ty, must_copy_dest) = if let Some(ref d) = kind.destination() {
let (ret_dest_ty, must_copy_dest) = if let Some(d) = kind.destination() {
let dest = self.trans_lvalue(bcx, d);
let ret_ty = dest.ty.to_ty(bcx.tcx());
if type_of::return_uses_outptr(bcx.ccx(), ret_ty) {
Expand Down
15 changes: 5 additions & 10 deletions src/librustc_trans/trans/mir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@ use middle::ty::{Ty, TypeFoldable};
use rustc::middle::const_eval::ConstVal;
use rustc::mir::repr as mir;
use trans::common::{self, Block, C_bool, C_bytes, C_floating_f64, C_integral, C_str_slice};
use trans::consts::{self, TrueConst};
use trans::{type_of, expr};

use trans::consts;
use trans::expr;
use trans::type_of;

use super::operand::{OperandRef, OperandValue};
use super::MirContext;


impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
pub fn trans_constval(&mut self,
bcx: Block<'bcx, 'tcx>,
Expand Down Expand Up @@ -66,13 +67,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
ConstVal::Uint(v) => C_integral(llty, v, false),
ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()),
ConstVal::ByteStr(ref v) => consts::addr_of(ccx, C_bytes(ccx, v), 1, "byte_str"),
ConstVal::Struct(id) | ConstVal::Tuple(id) => {
let expr = bcx.tcx().map.expect_expr(id);
match consts::const_expr(ccx, expr, param_substs, None, TrueConst::Yes) {
Ok((val, _)) => val,
Err(e) => panic!("const eval failure: {}", e.description()),
}
},
ConstVal::Struct(id) | ConstVal::Tuple(id) |
ConstVal::Array(id, _) | ConstVal::Repeat(id, _) => {
let expr = bcx.tcx().map.expect_expr(id);
expr::trans(bcx, expr).datum.val
Expand Down
32 changes: 32 additions & 0 deletions src/test/run-pass/mir_constval_adts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2016 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.
#![feature(rustc_attrs)]

#[derive(PartialEq, Debug)]
struct Point {
_x: i32,
_y: i32,
}
const STRUCT: Point = Point { _x: 42, _y: 42 };
const TUPLE1: (i32, i32) = (42, 42);
const TUPLE2: (&'static str, &'static str) = ("hello","world");

#[rustc_mir]
fn mir() -> (Point, (i32, i32), (&'static str, &'static str)){
let struct1 = STRUCT;
let tuple1 = TUPLE1;
let tuple2 = TUPLE2;
(struct1, tuple1, tuple2)
}

fn main(){
assert_eq!(mir(), (STRUCT, TUPLE1, TUPLE2));
}