From 834fb17e9476204dbd5723cd2cc3617bf848b9e9 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 6 Jan 2016 07:04:48 +0000 Subject: [PATCH 1/5] Fix bug in duplicate checking for extern crates. --- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustc_resolve/lib.rs | 33 +++++++++++++-------- 2 files changed, 22 insertions(+), 13 deletions(-) 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 5a17f2528c85b..715f5420cdeb8 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, @@ -1292,12 +1302,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, @@ -1305,6 +1311,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. @@ -1313,12 +1327,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)); } } From 6f0e58fc5f0e0b1d21e033d5068dcb40386e3f9f Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Wed, 6 Jan 2016 13:16:30 +0100 Subject: [PATCH 2/5] Stop re-exporting MutateMode's variants. --- src/librustc/middle/check_match.rs | 9 ++++----- src/librustc/middle/expr_use_visitor.rs | 13 ++++++++----- src/librustc_borrowck/borrowck/check_loans.rs | 5 +++-- src/librustc_borrowck/borrowck/move_data.rs | 5 +++-- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 8439b439d7649..dbf8ce3db3b66 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -18,9 +18,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}; @@ -1160,10 +1159,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 0273d1a76e9a8..9584d118bc3e5 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_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 { From 8e293676eef08b61cef57200927e7cbc5b901337 Mon Sep 17 00:00:00 2001 From: Scott Olson Date: Thu, 7 Jan 2016 15:16:07 -0600 Subject: [PATCH 3/5] Fix MIR text output for terminators since they were made optional. --- src/librustc_mir/pretty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) } From ea52d9ebdaf0e3f345628152fa387d8a69bef643 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Fri, 8 Jan 2016 01:15:59 +0200 Subject: [PATCH 4/5] [MIR] Fix translation of ConstVal::{Struct, Tuple} Fixes #30772 --- src/librustc_trans/trans/mir/constant.rs | 15 ++++------- src/test/run-pass/mir_constval_adts.rs | 32 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 src/test/run-pass/mir_constval_adts.rs diff --git a/src/librustc_trans/trans/mir/constant.rs b/src/librustc_trans/trans/mir/constant.rs index 0f4a0407298c8..e96c8f900b18c 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, HasTypeFlags}; 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)); +} + From 2f86c1605c3a82d0c82c36f1dc84441237a9f5c1 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Thu, 7 Jan 2016 15:08:02 +0200 Subject: [PATCH 5/5] Change destination accessor to return references MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously it was returning a value, mostly for the two reasons: * Cloning Lvalue is very cheap most of the time (i.e. when Lvalue is not a Projection); * There’s users who want &mut lvalue and there’s users who want &lvalue. Returning a value allows to make either one easier when pattern matching (i.e. Some(ref dest) or Some(ref mut dest)). However, I’m now convinced this is an invalid approach. Namely the users which want a mutable reference may modify the Lvalue in-place, but the changes won’t be reflected in the final MIR, since the Lvalue modified is merely a clone. Instead, we have two accessors `destination` and `destination_mut` which return a reference to the destination in desired mode. --- src/librustc/mir/repr.rs | 13 +++++++++++-- src/librustc_mir/transform/erase_regions.rs | 2 +- src/librustc_trans/trans/mir/block.rs | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) 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_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_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) {