From f53314cd70dd194ea40c55a5d8ceae7b94409aea Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 29 Dec 2014 09:33:25 +1300 Subject: [PATCH 1/6] Remove the glob/shadowing exception bug [breaking-change] This and the other commit in this PR change the rules for shadowing and globs to be stricter. There were previously bugs where some glob imports would not be checked for shadowing. Those are now fixed and you may have to adjust your imports to use fewer globs. --- src/librustc_resolve/lib.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 720883a8e9a..b228f45e640 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -345,9 +345,6 @@ impl Rib { #[deriving(Show,PartialEq,Clone,Copy)] enum Shadowable { Always, - /// Means that the recorded import obeys the glob shadowing rules, i.e., can - /// only be shadowed by another glob import. - Glob, Never } @@ -1719,11 +1716,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { view_path.span, id, is_public, - if shadowable == Shadowable::Never { - Shadowable::Glob - } else { - shadowable - }); + shadowable); } } } From 9c1567e62250fa681f73b997ca252f99e99728cd Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 29 Dec 2014 10:22:37 +1300 Subject: [PATCH 2/6] Fallout from glob shadowing --- src/librustc_trans/trans/base.rs | 3 +- src/librustc_trans/trans/common.rs | 4 +- src/libstd/comm/mod.rs | 93 +++++++++++------------ src/test/run-pass/issue-7663.rs | 16 +--- src/test/run-pass/tcp-connect-timeouts.rs | 1 - 5 files changed, 50 insertions(+), 67 deletions(-) diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index f49fc7f06c5..8ac9869121c 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -1554,8 +1554,7 @@ pub fn arg_kind<'a, 'tcx>(cx: &FunctionContext<'a, 'tcx>, t: Ty<'tcx>) } // work around bizarre resolve errors -pub type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>; -pub type LvalueDatum<'tcx> = datum::Datum<'tcx, datum::Lvalue>; +type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>; // create_datums_for_fn_args: creates rvalue datums for each of the // incoming function arguments. These will later be stored into diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index ea2a4ef6b28..78410dc650d 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -190,8 +190,8 @@ pub fn validate_substs(substs: &Substs) { } // work around bizarre resolve errors -pub type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>; -pub type LvalueDatum<'tcx> = datum::Datum<'tcx, datum::Lvalue>; +type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>; +type LvalueDatum<'tcx> = datum::Datum<'tcx, datum::Lvalue>; // Function context. Every LLVM function we create will have one of // these. diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs index c85bea87218..4b0b21ec8d8 100644 --- a/src/libstd/comm/mod.rs +++ b/src/libstd/comm/mod.rs @@ -181,7 +181,7 @@ // senders. Under the hood, however, there are actually three flavors of // channels in play. // -// * Oneshots - these channels are highly optimized for the one-send use case. +// * Flavor::Oneshots - these channels are highly optimized for the one-send use case. // They contain as few atomics as possible and involve one and // exactly one allocation. // * Streams - these channels are optimized for the non-shared use case. They @@ -316,7 +316,6 @@ use core::prelude::*; pub use self::TryRecvError::*; pub use self::TrySendError::*; -use self::Flavor::*; use alloc::arc::Arc; use core::kinds; @@ -478,7 +477,7 @@ impl UnsafeFlavor for Receiver { #[unstable] pub fn channel() -> (Sender, Receiver) { let a = Arc::new(RacyCell::new(oneshot::Packet::new())); - (Sender::new(Oneshot(a.clone())), Receiver::new(Oneshot(a))) + (Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a))) } /// Creates a new synchronous, bounded channel. @@ -518,7 +517,7 @@ pub fn channel() -> (Sender, Receiver) { of channel that is is creating"] pub fn sync_channel(bound: uint) -> (SyncSender, Receiver) { let a = Arc::new(RacyCell::new(sync::Packet::new(bound))); - (SyncSender::new(a.clone()), Receiver::new(Sync(a))) + (SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a))) } //////////////////////////////////////////////////////////////////////////////// @@ -592,7 +591,7 @@ impl Sender { #[unstable = "this function may be renamed to send() in the future"] pub fn send_opt(&self, t: T) -> Result<(), T> { let (new_inner, ret) = match *unsafe { self.inner() } { - Oneshot(ref p) => { + Flavor::Oneshot(ref p) => { unsafe { let p = p.get(); if !(*p).sent() { @@ -600,7 +599,7 @@ impl Sender { } else { let a = Arc::new(RacyCell::new(stream::Packet::new())); - match (*p).upgrade(Receiver::new(Stream(a.clone()))) { + match (*p).upgrade(Receiver::new(Flavor::Stream(a.clone()))) { oneshot::UpSuccess => { let ret = (*a.get()).send(t); (a, ret) @@ -618,13 +617,13 @@ impl Sender { } } } - Stream(ref p) => return unsafe { (*p.get()).send(t) }, - Shared(ref p) => return unsafe { (*p.get()).send(t) }, - Sync(..) => unreachable!(), + Flavor::Stream(ref p) => return unsafe { (*p.get()).send(t) }, + Flavor::Shared(ref p) => return unsafe { (*p.get()).send(t) }, + Flavor::Sync(..) => unreachable!(), }; unsafe { - let tmp = Sender::new(Stream(new_inner)); + let tmp = Sender::new(Flavor::Stream(new_inner)); mem::swap(self.inner_mut(), tmp.inner_mut()); } return ret; @@ -635,42 +634,42 @@ impl Sender { impl Clone for Sender { fn clone(&self) -> Sender { let (packet, sleeper, guard) = match *unsafe { self.inner() } { - Oneshot(ref p) => { + Flavor::Oneshot(ref p) => { let a = Arc::new(RacyCell::new(shared::Packet::new())); unsafe { let guard = (*a.get()).postinit_lock(); - match (*p.get()).upgrade(Receiver::new(Shared(a.clone()))) { + match (*p.get()).upgrade(Receiver::new(Flavor::Shared(a.clone()))) { oneshot::UpSuccess | oneshot::UpDisconnected => (a, None, guard), oneshot::UpWoke(task) => (a, Some(task), guard) } } } - Stream(ref p) => { + Flavor::Stream(ref p) => { let a = Arc::new(RacyCell::new(shared::Packet::new())); unsafe { let guard = (*a.get()).postinit_lock(); - match (*p.get()).upgrade(Receiver::new(Shared(a.clone()))) { + match (*p.get()).upgrade(Receiver::new(Flavor::Shared(a.clone()))) { stream::UpSuccess | stream::UpDisconnected => (a, None, guard), stream::UpWoke(task) => (a, Some(task), guard), } } } - Shared(ref p) => { + Flavor::Shared(ref p) => { unsafe { (*p.get()).clone_chan(); } - return Sender::new(Shared(p.clone())); + return Sender::new(Flavor::Shared(p.clone())); } - Sync(..) => unreachable!(), + Flavor::Sync(..) => unreachable!(), }; unsafe { (*packet.get()).inherit_blocker(sleeper, guard); - let tmp = Sender::new(Shared(packet.clone())); + let tmp = Sender::new(Flavor::Shared(packet.clone())); mem::swap(self.inner_mut(), tmp.inner_mut()); } - Sender::new(Shared(packet)) + Sender::new(Flavor::Shared(packet)) } } @@ -678,10 +677,10 @@ impl Clone for Sender { impl Drop for Sender { fn drop(&mut self) { match *unsafe { self.inner_mut() } { - Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); }, - Stream(ref mut p) => unsafe { (*p.get()).drop_chan(); }, - Shared(ref mut p) => unsafe { (*p.get()).drop_chan(); }, - Sync(..) => unreachable!(), + Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); }, + Flavor::Stream(ref mut p) => unsafe { (*p.get()).drop_chan(); }, + Flavor::Shared(ref mut p) => unsafe { (*p.get()).drop_chan(); }, + Flavor::Sync(..) => unreachable!(), } } } @@ -827,7 +826,7 @@ impl Receiver { pub fn try_recv(&self) -> Result { loop { let new_port = match *unsafe { self.inner() } { - Oneshot(ref p) => { + Flavor::Oneshot(ref p) => { match unsafe { (*p.get()).try_recv() } { Ok(t) => return Ok(t), Err(oneshot::Empty) => return Err(Empty), @@ -835,7 +834,7 @@ impl Receiver { Err(oneshot::Upgraded(rx)) => rx, } } - Stream(ref p) => { + Flavor::Stream(ref p) => { match unsafe { (*p.get()).try_recv() } { Ok(t) => return Ok(t), Err(stream::Empty) => return Err(Empty), @@ -843,14 +842,14 @@ impl Receiver { Err(stream::Upgraded(rx)) => rx, } } - Shared(ref p) => { + Flavor::Shared(ref p) => { match unsafe { (*p.get()).try_recv() } { Ok(t) => return Ok(t), Err(shared::Empty) => return Err(Empty), Err(shared::Disconnected) => return Err(Disconnected), } } - Sync(ref p) => { + Flavor::Sync(ref p) => { match unsafe { (*p.get()).try_recv() } { Ok(t) => return Ok(t), Err(sync::Empty) => return Err(Empty), @@ -881,7 +880,7 @@ impl Receiver { pub fn recv_opt(&self) -> Result { loop { let new_port = match *unsafe { self.inner() } { - Oneshot(ref p) => { + Flavor::Oneshot(ref p) => { match unsafe { (*p.get()).recv() } { Ok(t) => return Ok(t), Err(oneshot::Empty) => return unreachable!(), @@ -889,7 +888,7 @@ impl Receiver { Err(oneshot::Upgraded(rx)) => rx, } } - Stream(ref p) => { + Flavor::Stream(ref p) => { match unsafe { (*p.get()).recv() } { Ok(t) => return Ok(t), Err(stream::Empty) => return unreachable!(), @@ -897,14 +896,14 @@ impl Receiver { Err(stream::Upgraded(rx)) => rx, } } - Shared(ref p) => { + Flavor::Shared(ref p) => { match unsafe { (*p.get()).recv() } { Ok(t) => return Ok(t), Err(shared::Empty) => return unreachable!(), Err(shared::Disconnected) => return Err(()), } } - Sync(ref p) => return unsafe { (*p.get()).recv() } + Flavor::Sync(ref p) => return unsafe { (*p.get()).recv() } }; unsafe { mem::swap(self.inner_mut(), new_port.inner_mut()); @@ -924,22 +923,22 @@ impl select::Packet for Receiver { fn can_recv(&self) -> bool { loop { let new_port = match *unsafe { self.inner() } { - Oneshot(ref p) => { + Flavor::Oneshot(ref p) => { match unsafe { (*p.get()).can_recv() } { Ok(ret) => return ret, Err(upgrade) => upgrade, } } - Stream(ref p) => { + Flavor::Stream(ref p) => { match unsafe { (*p.get()).can_recv() } { Ok(ret) => return ret, Err(upgrade) => upgrade, } } - Shared(ref p) => { + Flavor::Shared(ref p) => { return unsafe { (*p.get()).can_recv() }; } - Sync(ref p) => { + Flavor::Sync(ref p) => { return unsafe { (*p.get()).can_recv() }; } }; @@ -953,24 +952,24 @@ impl select::Packet for Receiver { fn start_selection(&self, mut token: SignalToken) -> StartResult { loop { let (t, new_port) = match *unsafe { self.inner() } { - Oneshot(ref p) => { + Flavor::Oneshot(ref p) => { match unsafe { (*p.get()).start_selection(token) } { oneshot::SelSuccess => return Installed, oneshot::SelCanceled => return Abort, oneshot::SelUpgraded(t, rx) => (t, rx), } } - Stream(ref p) => { + Flavor::Stream(ref p) => { match unsafe { (*p.get()).start_selection(token) } { stream::SelSuccess => return Installed, stream::SelCanceled => return Abort, stream::SelUpgraded(t, rx) => (t, rx), } } - Shared(ref p) => { + Flavor::Shared(ref p) => { return unsafe { (*p.get()).start_selection(token) }; } - Sync(ref p) => { + Flavor::Sync(ref p) => { return unsafe { (*p.get()).start_selection(token) }; } }; @@ -985,14 +984,14 @@ impl select::Packet for Receiver { let mut was_upgrade = false; loop { let result = match *unsafe { self.inner() } { - Oneshot(ref p) => unsafe { (*p.get()).abort_selection() }, - Stream(ref p) => unsafe { + Flavor::Oneshot(ref p) => unsafe { (*p.get()).abort_selection() }, + Flavor::Stream(ref p) => unsafe { (*p.get()).abort_selection(was_upgrade) }, - Shared(ref p) => return unsafe { + Flavor::Shared(ref p) => return unsafe { (*p.get()).abort_selection(was_upgrade) }, - Sync(ref p) => return unsafe { + Flavor::Sync(ref p) => return unsafe { (*p.get()).abort_selection() }, }; @@ -1015,10 +1014,10 @@ impl<'a, T: Send> Iterator for Messages<'a, T> { impl Drop for Receiver { fn drop(&mut self) { match *unsafe { self.inner_mut() } { - Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); }, - Stream(ref mut p) => unsafe { (*p.get()).drop_port(); }, - Shared(ref mut p) => unsafe { (*p.get()).drop_port(); }, - Sync(ref mut p) => unsafe { (*p.get()).drop_port(); }, + Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); }, + Flavor::Stream(ref mut p) => unsafe { (*p.get()).drop_port(); }, + Flavor::Shared(ref mut p) => unsafe { (*p.get()).drop_port(); }, + Flavor::Sync(ref mut p) => unsafe { (*p.get()).drop_port(); }, } } } diff --git a/src/test/run-pass/issue-7663.rs b/src/test/run-pass/issue-7663.rs index ee500b3d4fa..39b0711721b 100644 --- a/src/test/run-pass/issue-7663.rs +++ b/src/test/run-pass/issue-7663.rs @@ -17,8 +17,7 @@ mod test1 { mod bar { pub fn p() -> int { 2 } } pub mod baz { - use test1::foo::*; - use test1::bar::*; + use test1::bar::p; pub fn my_main() { assert!(p() == 2); } } @@ -36,20 +35,7 @@ mod test2 { } } -mod test3 { - - mod foo { pub fn p() -> int { 1 } } - mod bar { pub fn p() -> int { 2 } } - - pub mod baz { - use test3::bar::p; - - pub fn my_main() { assert!(p() == 2); } - } -} - fn main() { test1::baz::my_main(); test2::baz::my_main(); - test3::baz::my_main(); } diff --git a/src/test/run-pass/tcp-connect-timeouts.rs b/src/test/run-pass/tcp-connect-timeouts.rs index 2e4b9da691e..2d087406fd6 100644 --- a/src/test/run-pass/tcp-connect-timeouts.rs +++ b/src/test/run-pass/tcp-connect-timeouts.rs @@ -23,7 +23,6 @@ #![allow(unused_imports)] use std::io::*; -use std::io::net::tcp::*; use std::io::test::*; use std::io; use std::time::Duration; From 9a58808785499d730aaa0b1c914b34c204d2a487 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 29 Dec 2014 12:31:17 +1300 Subject: [PATCH 3/6] Little bit of refactoring in resolve --- src/librustc_resolve/lib.rs | 189 ++++++++++++++++++------------------ 1 file changed, 92 insertions(+), 97 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b228f45e640..3f35f99a995 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -459,6 +459,22 @@ impl ImportResolution { target.unwrap().shadowable } + + fn set_target_and_id(&mut self, + namespace: Namespace, + target: Option, + id: NodeId) { + match namespace { + TypeNS => { + self.type_target = target; + self.type_id = id; + } + ValueNS => { + self.value_target = target; + self.value_id = id; + } + } + } } /// The link from a module up to its nearest parent node. @@ -2705,64 +2721,45 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // We've successfully resolved the import. Write the results in. let mut import_resolutions = module_.import_resolutions.borrow_mut(); let import_resolution = &mut (*import_resolutions)[target]; + { + let check_and_write_import = |namespace, result: &_, used_public: &mut bool| { + let namespace_name = match namespace { + TypeNS => "type", + ValueNS => "value", + }; - match value_result { - BoundResult(ref target_module, ref name_bindings) => { - debug!("(resolving single import) found value target: {}", - { name_bindings.value_def.borrow().clone().unwrap().def }); - self.check_for_conflicting_import( - &import_resolution.value_target, - directive.span, - target, - ValueNS); + match *result { + BoundResult(ref target_module, ref name_bindings) => { + debug!("(resolving single import) found {} target: {}", + namespace_name, + name_bindings.def_for_namespace(namespace)); + self.check_for_conflicting_import( + &import_resolution.target_for_namespace(namespace), + directive.span, + target, + namespace); - self.check_that_import_is_importable( - &**name_bindings, - directive.span, - target, - ValueNS); + self.check_that_import_is_importable( + &**name_bindings, + directive.span, + target, + namespace); - import_resolution.value_target = - Some(Target::new(target_module.clone(), - name_bindings.clone(), - directive.shadowable)); - import_resolution.value_id = directive.id; - import_resolution.is_public = directive.is_public; - value_used_public = name_bindings.defined_in_public_namespace(ValueNS); - } - UnboundResult => { /* Continue. */ } - UnknownResult => { - panic!("value result should be known at this point"); - } - } - match type_result { - BoundResult(ref target_module, ref name_bindings) => { - debug!("(resolving single import) found type target: {}", - { name_bindings.type_def.borrow().clone().unwrap().type_def }); - self.check_for_conflicting_import( - &import_resolution.type_target, - directive.span, - target, - TypeNS); - - self.check_that_import_is_importable( - &**name_bindings, - directive.span, - target, - TypeNS); - - import_resolution.type_target = - Some(Target::new(target_module.clone(), - name_bindings.clone(), - directive.shadowable)); - import_resolution.type_id = directive.id; - import_resolution.is_public = directive.is_public; - type_used_public = name_bindings.defined_in_public_namespace(TypeNS); - } - UnboundResult => { /* Continue. */ } - UnknownResult => { - panic!("type result should be known at this point"); - } + let target = Some(Target::new(target_module.clone(), + name_bindings.clone(), + directive.shadowable)); + import_resolution.set_target_and_id(namespace, target, directive.id); + import_resolution.is_public = directive.is_public; + *used_public = name_bindings.defined_in_public_namespace(namespace); + } + UnboundResult => { /* Continue. */ } + UnknownResult => { + panic!("{} result should be known at this point", namespace_name); + } + } + }; + check_and_write_import(ValueNS, &value_result, &mut value_used_public); + check_and_write_import(TypeNS, &type_result, &mut type_used_public); } self.check_for_conflicts_between_imports_and_items( @@ -2818,7 +2815,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Resolves a glob import. Note that this function cannot fail; it either // succeeds or bails out (as importing * from an empty module or a module - // that exports nothing is valid). + // that exports nothing is valid). containing_module is the module we are + // actually importing, i.e., `foo` in `use foo::*`. fn resolve_glob_import(&mut self, module_: &Module, containing_module: Rc, @@ -2844,12 +2842,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { assert_eq!(containing_module.glob_count.get(), 0); // Add all resolved imports from the containing module. - let import_resolutions = containing_module.import_resolutions - .borrow(); + let import_resolutions = containing_module.import_resolutions.borrow(); for (ident, target_import_resolution) in import_resolutions.iter() { debug!("(resolving glob import) writing module resolution \ {} into `{}`", - target_import_resolution.type_target.is_none(), + token::get_name(*ident), self.module_to_string(module_)); if !target_import_resolution.is_public { @@ -2869,8 +2866,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Continue. } Some(ref value_target) => { - dest_import_resolution.value_target = - Some(value_target.clone()); + dest_import_resolution.value_target = Some(value_target.clone()); } } match target_import_resolution.type_target { @@ -2878,8 +2874,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Continue. } Some(ref type_target) => { - dest_import_resolution.type_target = - Some(type_target.clone()); + dest_import_resolution.type_target = Some(type_target.clone()); } } dest_import_resolution.is_public = is_public; @@ -2901,8 +2896,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Add all children from the containing module. self.populate_module_if_necessary(&containing_module); - for (&name, name_bindings) in containing_module.children - .borrow().iter() { + for (&name, name_bindings) in containing_module.children.borrow().iter() { self.merge_import_resolution(module_, containing_module.clone(), import_directive, @@ -2912,8 +2906,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } // Add external module children from the containing module. - for (&name, module) in containing_module.external_module_children - .borrow().iter() { + for (&name, module) in containing_module.external_module_children.borrow().iter() { let name_bindings = Rc::new(Resolver::create_name_bindings_from_module(module.clone())); self.merge_import_resolution(module_, @@ -2958,41 +2951,39 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving glob import) writing resolution `{}` in `{}` \ to `{}`", - token::get_name(name).get().to_string(), + token::get_name(name).get(), self.module_to_string(&*containing_module), self.module_to_string(module_)); // Merge the child item into the import resolution. - if name_bindings.defined_in_namespace_with(ValueNS, IMPORTABLE | PUBLIC) { - debug!("(resolving glob import) ... for value target"); - if dest_import_resolution.shadowable(ValueNS) == Shadowable::Never { - let msg = format!("a value named `{}` has already been imported \ - in this module", - token::get_name(name).get()); - self.session.span_err(import_directive.span, msg.as_slice()); - } else { - dest_import_resolution.value_target = - Some(Target::new(containing_module.clone(), - name_bindings.clone(), - import_directive.shadowable)); - dest_import_resolution.value_id = id; - } - } - if name_bindings.defined_in_namespace_with(TypeNS, IMPORTABLE | PUBLIC) { - debug!("(resolving glob import) ... for type target"); - if dest_import_resolution.shadowable(TypeNS) == Shadowable::Never { - let msg = format!("a type named `{}` has already been imported \ - in this module", - token::get_name(name).get()); - self.session.span_err(import_directive.span, msg.as_slice()); - } else { - dest_import_resolution.type_target = - Some(Target::new(containing_module, - name_bindings.clone(), - import_directive.shadowable)); - dest_import_resolution.type_id = id; - } + { + let merge_child_item = |namespace| { + if name_bindings.defined_in_namespace_with(namespace, IMPORTABLE | PUBLIC) { + let namespace_name = match namespace { + TypeNS => "type", + ValueNS => "value", + }; + debug!("(resolving glob import) ... for {} target", namespace_name); + if dest_import_resolution.shadowable(namespace) == Shadowable::Never { + let msg = format!("a {} named `{}` has already been imported \ + in this module", + namespace_name, + token::get_name(name).get()); + self.session.span_err(import_directive.span, msg.as_slice()); + } else { + let target = Target::new(containing_module.clone(), + name_bindings.clone(), + import_directive.shadowable); + dest_import_resolution.set_target_and_id(namespace, + Some(target), + id); + } + } + }; + merge_child_item(ValueNS); + merge_child_item(TypeNS); } + dest_import_resolution.is_public = is_public; self.check_for_conflicts_between_imports_and_items( @@ -3012,6 +3003,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return } + debug!("check_for_conflicting_import: {}; target exists: {}", + token::get_name(name).get(), + target.is_some()); + match *target { Some(ref target) if target.shadowable != Shadowable::Always => { let msg = format!("a {} named `{}` has already been imported \ From 35dd33c7e24798e8acc030fc5bbf2ca372616bbf Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 29 Dec 2014 14:33:46 +1300 Subject: [PATCH 4/6] Fix glob shadowing bug with re-exports --- src/librustc_resolve/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 3f35f99a995..d42725d19ba 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2866,6 +2866,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Continue. } Some(ref value_target) => { + self.check_for_conflicting_import(&dest_import_resolution.value_target, + import_directive.span, + *ident, + ValueNS); dest_import_resolution.value_target = Some(value_target.clone()); } } @@ -2874,6 +2878,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Continue. } Some(ref type_target) => { + self.check_for_conflicting_import(&dest_import_resolution.type_target, + import_directive.span, + *ident, + TypeNS); dest_import_resolution.type_target = Some(type_target.clone()); } } From ac095351fba2750bddd84c3f434d16c1ed7f1640 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 29 Dec 2014 16:52:10 +1300 Subject: [PATCH 5/6] Fallout from globs/re-export/shadowing change --- src/libcollections/slice.rs | 5 ++++- src/libcollections/str.rs | 2 +- src/libstd/c_str.rs | 3 ++- src/libstd/comm/mod.rs | 5 +++-- src/libstd/io/mem.rs | 4 ++-- src/libstd/io/mod.rs | 4 ++-- src/libstd/io/net/pipe.rs | 2 +- src/libstd/io/net/tcp.rs | 7 +++++-- src/libstd/io/net/udp.rs | 4 ++-- src/libstd/io/process.rs | 6 ++++-- src/libstd/io/util.rs | 2 +- src/libstd/num/mod.rs | 6 ++++-- src/libstd/path/posix.rs | 2 +- src/libstd/sync/atomic.rs | 2 +- 14 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index d6d94f57acf..cca071836dd 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -1343,7 +1343,10 @@ pub mod raw { #[cfg(test)] mod tests { use std::boxed::Box; - use prelude::*; + use prelude::{Some, None, range, Vec, ToString, Clone, Greater, Less, Equal}; + use prelude::{SliceExt, Iterator, IteratorExt, DoubleEndedIteratorExt}; + use prelude::{OrdSliceExt, CloneSliceExt, PartialEqSliceExt, AsSlice}; + use prelude::{RandomAccessIterator, Ord, VectorVector}; use core::cell::Cell; use core::default::Default; use core::mem; diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index bccd2a1198a..5b26dc29478 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -3331,7 +3331,7 @@ mod tests { #[cfg(test)] mod bench { use super::*; - use prelude::*; + use prelude::{SliceExt, IteratorExt, DoubleEndedIteratorExt}; use test::Bencher; use test::black_box; diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index ffe19203769..39c57b99b36 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -537,7 +537,8 @@ pub unsafe fn from_c_multistring(buf: *const libc::c_char, #[cfg(test)] mod tests { use super::*; - use prelude::*; + use prelude::{spawn, Some, None, Option, FnOnce, ToString, CloneSliceExt}; + use prelude::{Clone, RawPtr, Iterator, SliceExt, StrExt}; use ptr; use thread::Thread; use libc; diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs index 4b0b21ec8d8..a405627aecc 100644 --- a/src/libstd/comm/mod.rs +++ b/src/libstd/comm/mod.rs @@ -336,7 +336,8 @@ macro_rules! test { use super::*; use comm::*; use thread::Thread; - use prelude::*; + use prelude::{Ok, Err, spawn, range, drop, Box, Some, None, Option}; + use prelude::{Vec, Buffer, from_str, Clone}; $(#[$a])* #[test] fn f() { $b } } @@ -1046,7 +1047,7 @@ unsafe impl kinds::Sync for RacyCell { } // Oh dear #[cfg(test)] mod test { use super::*; - use prelude::*; + use prelude::{spawn, range, Some, None, from_str, Clone, Str}; use os; pub fn stress_factor() -> uint { diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs index 01151059530..ccece874ce7 100644 --- a/src/libstd/io/mem.rs +++ b/src/libstd/io/mem.rs @@ -400,8 +400,8 @@ impl<'a> Buffer for BufReader<'a> { mod test { extern crate "test" as test_crate; use super::*; - use io::*; - use prelude::*; + use io::{SeekSet, SeekCur, SeekEnd, Reader, Writer, Seek}; + use prelude::{Ok, Err, range, Vec, Buffer, AsSlice, SliceExt, IteratorExt, CloneSliceExt}; use io; use self::test_crate::Bencher; diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index b6f8bb25b65..82aa00dc98e 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1959,8 +1959,8 @@ impl fmt::Show for FilePermission { #[cfg(test)] mod tests { use self::BadReaderBehavior::*; - use super::{IoResult, Reader, MemReader, NoProgress, InvalidInput}; - use prelude::*; + use super::{IoResult, Reader, MemReader, NoProgress, InvalidInput, Writer}; + use prelude::{Ok, Vec, Buffer, CloneSliceExt}; use uint; #[deriving(Clone, PartialEq, Show)] diff --git a/src/libstd/io/net/pipe.rs b/src/libstd/io/net/pipe.rs index 4afc72cde71..93f37a8c98f 100644 --- a/src/libstd/io/net/pipe.rs +++ b/src/libstd/io/net/pipe.rs @@ -269,7 +269,7 @@ mod tests { use super::*; use io::*; use io::test::*; - use prelude::*; + use prelude::{Ok, Err, spawn, range, drop, Some, None, channel, Send, FnOnce, Clone}; use io::fs::PathExtensions; use time::Duration; diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs index 6adb5387f2e..24cf06973cc 100644 --- a/src/libstd/io/net/tcp.rs +++ b/src/libstd/io/net/tcp.rs @@ -484,9 +484,12 @@ impl sys_common::AsInner for TcpAcceptor { mod test { use io::net::tcp::*; use io::net::ip::*; - use io::*; + use io::{EndOfFile, TimedOut, IoError, ShortWrite, OtherIoError, ConnectionAborted}; + use io::{ConnectionRefused, ConnectionReset, BrokenPipe, NotConnected}; + use io::{PermissionDenied, Listener, Acceptor}; use io::test::*; - use prelude::*; + use prelude::{Ok, Err, spawn, range, drop, Some, None, channel, Clone}; + use prelude::{Reader, Writer, IteratorExt}; // FIXME #11530 this fails on android because tests are run as root #[cfg_attr(any(windows, target_os = "android"), ignore)] diff --git a/src/libstd/io/net/udp.rs b/src/libstd/io/net/udp.rs index a36703172c3..a165232c5f5 100644 --- a/src/libstd/io/net/udp.rs +++ b/src/libstd/io/net/udp.rs @@ -250,9 +250,9 @@ impl Writer for UdpStream { mod test { use super::*; use io::net::ip::*; - use io::*; + use io::{ShortWrite, IoError, TimedOut, PermissionDenied}; use io::test::*; - use prelude::*; + use prelude::{Ok, Err, spawn, range, drop, Some, None, channel, Clone, Reader, Writer}; // FIXME #11530 this fails on android because tests are run as root #[cfg_attr(any(windows, target_os = "android"), ignore)] diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs index 93aa627ffba..9e0c76e4e79 100644 --- a/src/libstd/io/process.rs +++ b/src/libstd/io/process.rs @@ -745,8 +745,10 @@ mod tests { use super::*; use io::timer::*; - use io::*; - use prelude::*; + use io::{Truncate, Write, TimedOut, timer, process, FileNotFound}; + use prelude::{Ok, Err, spawn, range, drop, Box, Some, None, Option, Vec, Buffer}; + use prelude::{from_str, Path, String, channel, Reader, Writer, Clone, Slice}; + use prelude::{SliceExt, Str, StrExt, AsSlice, ToString, GenericPath}; use io::fs::PathExtensions; use time::Duration; use str; diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 18fabcbd1a2..79a2b8b84f0 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -280,7 +280,7 @@ mod test { use io; use boxed::Box; use super::*; - use prelude::*; + use prelude::{Ok, range, Vec, Buffer, Writer, Reader, ToString, AsSlice}; #[test] fn test_limit_reader_unlimited() { diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index 7c8763979bb..48ff1a364e9 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -147,8 +147,10 @@ pub fn test_num(ten: T, two: T) where #[cfg(test)] mod tests { - use prelude::*; - use super::*; + use prelude::{range, Some, None, Option, IteratorExt}; + use super::{from_int, from_uint, from_i32, from_i64, from_u64, from_u32}; + use super::{from_f64, from_f32, from_u16, from_i16, from_u8, from_i8, Int}; + use super::{cast, NumCast, ToPrimitive, FromPrimitive, UnsignedInt}; use i8; use i16; use i32; diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index d941665f048..60f147eac9b 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -1239,7 +1239,7 @@ mod bench { extern crate test; use self::test::Bencher; use super::*; - use prelude::*; + use prelude::{Clone, GenericPath}; #[bench] fn join_home_dir(b: &mut Bencher) { diff --git a/src/libstd/sync/atomic.rs b/src/libstd/sync/atomic.rs index 26778ef70b3..bdf947438f3 100644 --- a/src/libstd/sync/atomic.rs +++ b/src/libstd/sync/atomic.rs @@ -180,7 +180,7 @@ impl Drop for AtomicOption { #[cfg(test)] mod test { - use prelude::*; + use prelude::{Some, None}; use super::*; #[test] From 9dce83ccd9234dbc6228bdac6074c0414c6e7b05 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 29 Dec 2014 18:36:59 +1300 Subject: [PATCH 6/6] Tests --- src/test/compile-fail/import-shadow-1.rs | 31 ++++++++++++++++++++++++ src/test/compile-fail/import-shadow-2.rs | 31 ++++++++++++++++++++++++ src/test/compile-fail/import-shadow-3.rs | 31 ++++++++++++++++++++++++ src/test/compile-fail/import-shadow-4.rs | 31 ++++++++++++++++++++++++ src/test/compile-fail/import-shadow-5.rs | 31 ++++++++++++++++++++++++ src/test/compile-fail/import-shadow-6.rs | 31 ++++++++++++++++++++++++ src/test/compile-fail/import-shadow-7.rs | 31 ++++++++++++++++++++++++ 7 files changed, 217 insertions(+) create mode 100644 src/test/compile-fail/import-shadow-1.rs create mode 100644 src/test/compile-fail/import-shadow-2.rs create mode 100644 src/test/compile-fail/import-shadow-3.rs create mode 100644 src/test/compile-fail/import-shadow-4.rs create mode 100644 src/test/compile-fail/import-shadow-5.rs create mode 100644 src/test/compile-fail/import-shadow-6.rs create mode 100644 src/test/compile-fail/import-shadow-7.rs diff --git a/src/test/compile-fail/import-shadow-1.rs b/src/test/compile-fail/import-shadow-1.rs new file mode 100644 index 00000000000..007b28b6924 --- /dev/null +++ b/src/test/compile-fail/import-shadow-1.rs @@ -0,0 +1,31 @@ +// Copyright 2014 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. + +// Test that import shadowing using globs causes errors + +#![no_implicit_prelude] +#![feature(globs)] + +use foo::*; +use bar::*; //~ERROR a type named `Baz` has already been imported in this module + +mod foo { + pub type Baz = int; +} + +mod bar { + pub type Baz = int; +} + +mod qux { + pub use bar::Baz; +} + +fn main() {} diff --git a/src/test/compile-fail/import-shadow-2.rs b/src/test/compile-fail/import-shadow-2.rs new file mode 100644 index 00000000000..e597b557383 --- /dev/null +++ b/src/test/compile-fail/import-shadow-2.rs @@ -0,0 +1,31 @@ +// Copyright 2014 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. + +// Test that import shadowing using globs causes errors + +#![no_implicit_prelude] +#![feature(globs)] + +use foo::*; +use foo::*; //~ERROR a type named `Baz` has already been imported in this module + +mod foo { + pub type Baz = int; +} + +mod bar { + pub type Baz = int; +} + +mod qux { + pub use bar::Baz; +} + +fn main() {} diff --git a/src/test/compile-fail/import-shadow-3.rs b/src/test/compile-fail/import-shadow-3.rs new file mode 100644 index 00000000000..68222fa3fd7 --- /dev/null +++ b/src/test/compile-fail/import-shadow-3.rs @@ -0,0 +1,31 @@ +// Copyright 2014 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. + +// Test that import shadowing using globs causes errors + +#![no_implicit_prelude] +#![feature(globs)] + +use foo::Baz; +use bar::*; //~ERROR a type named `Baz` has already been imported in this module + +mod foo { + pub type Baz = int; +} + +mod bar { + pub type Baz = int; +} + +mod qux { + pub use bar::Baz; +} + +fn main() {} diff --git a/src/test/compile-fail/import-shadow-4.rs b/src/test/compile-fail/import-shadow-4.rs new file mode 100644 index 00000000000..c698004bda0 --- /dev/null +++ b/src/test/compile-fail/import-shadow-4.rs @@ -0,0 +1,31 @@ +// Copyright 2014 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. + +// Test that import shadowing using globs causes errors + +#![no_implicit_prelude] +#![feature(globs)] + +use foo::*; +use bar::Baz; //~ERROR a type named `Baz` has already been imported in this module + +mod foo { + pub type Baz = int; +} + +mod bar { + pub type Baz = int; +} + +mod qux { + pub use bar::Baz; +} + +fn main() {} diff --git a/src/test/compile-fail/import-shadow-5.rs b/src/test/compile-fail/import-shadow-5.rs new file mode 100644 index 00000000000..6ad7e5ec3e2 --- /dev/null +++ b/src/test/compile-fail/import-shadow-5.rs @@ -0,0 +1,31 @@ +// Copyright 2014 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. + +// Test that import shadowing using globs causes errors + +#![no_implicit_prelude] +#![feature(globs)] + +use foo::Baz; +use bar::Baz; //~ERROR a type named `Baz` has already been imported in this module + +mod foo { + pub type Baz = int; +} + +mod bar { + pub type Baz = int; +} + +mod qux { + pub use bar::Baz; +} + +fn main() {} diff --git a/src/test/compile-fail/import-shadow-6.rs b/src/test/compile-fail/import-shadow-6.rs new file mode 100644 index 00000000000..1864251e71b --- /dev/null +++ b/src/test/compile-fail/import-shadow-6.rs @@ -0,0 +1,31 @@ +// Copyright 2014 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. + +// Test that import shadowing using globs causes errors + +#![no_implicit_prelude] +#![feature(globs)] + +use qux::*; +use foo::*; //~ERROR a type named `Baz` has already been imported in this module + +mod foo { + pub type Baz = int; +} + +mod bar { + pub type Baz = int; +} + +mod qux { + pub use bar::Baz; +} + +fn main() {} diff --git a/src/test/compile-fail/import-shadow-7.rs b/src/test/compile-fail/import-shadow-7.rs new file mode 100644 index 00000000000..a2df266fb74 --- /dev/null +++ b/src/test/compile-fail/import-shadow-7.rs @@ -0,0 +1,31 @@ +// Copyright 2014 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. + +// Test that import shadowing using globs causes errors + +#![no_implicit_prelude] +#![feature(globs)] + +use foo::*; +use qux::*; //~ERROR a type named `Baz` has already been imported in this module + +mod foo { + pub type Baz = int; +} + +mod bar { + pub type Baz = int; +} + +mod qux { + pub use bar::Baz; +} + +fn main() {}