diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 972f9e2c64d0e..a33142433463a 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -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}; @@ -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 => {} } } } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 23d1617e5c658..e746f3ac57914 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -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::*; @@ -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 + }); } } } @@ -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); } @@ -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); } } @@ -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(_) => { } } diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index 6ca39d3ba7a87..1b0dfc7322961 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -314,10 +314,19 @@ impl<'tcx> CallKind<'tcx> { } } - pub fn destination(&self) -> Option> { + 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 } diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index df181aec4ea4c..2d30b827750ac 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -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; @@ -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 @@ -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. diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index 62404a73ad3be..735e618cc732b 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -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}; @@ -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 { diff --git a/src/librustc_mir/pretty.rs b/src/librustc_mir/pretty.rs index 163559f279281..ea4036a4d375f 100644 --- a/src/librustc_mir/pretty.rs +++ b/src/librustc_mir/pretty.rs @@ -39,7 +39,7 @@ fn write_basic_block(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) } diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 20a14cf415404..9679654d958e9 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -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); diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 1d3f2b79844ea..8ed47300a1708 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -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()); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a5a22fd7f3904..c7031f72af463 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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 @@ -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, @@ -1297,12 +1307,8 @@ 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, @@ -1310,6 +1316,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { "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. @@ -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)); } } diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs index aa0b3a25ebb0c..18a9aad0e915d 100644 --- a/src/librustc_trans/trans/mir/block.rs +++ b/src/librustc_trans/trans/mir/block.rs @@ -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) { diff --git a/src/librustc_trans/trans/mir/constant.rs b/src/librustc_trans/trans/mir/constant.rs index e461a1c05bcf3..84cc87e9b1385 100644 --- a/src/librustc_trans/trans/mir/constant.rs +++ b/src/librustc_trans/trans/mir/constant.rs @@ -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>, @@ -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 diff --git a/src/test/run-pass/mir_constval_adts.rs b/src/test/run-pass/mir_constval_adts.rs new file mode 100644 index 0000000000000..8a1f68dbea3ee --- /dev/null +++ b/src/test/run-pass/mir_constval_adts.rs @@ -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 or the MIT license +// , 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)); +} +