diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index bfd8a6f1f61..8a196768ae5 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -205,51 +205,6 @@ about what constitutes an Item declaration and what does not: https://doc.rust-lang.org/reference.html#statements "##, -E0317: r##" -User-defined types or type parameters cannot shadow the primitive types. -This error indicates you tried to define a type, struct or enum with the same -name as an existing primitive type: - -```compile_fail -struct u8 { - // ... -} -``` - -To fix this, simply name it something else. - -Such an error may also occur if you define a type parameter which shadows a -primitive type. An example would be something like: - -```compile_fail -impl MyTrait for Option { - // ... -} -``` - -In such a case, if you meant for `u8` to be a generic type parameter (i.e. any -type can be used in its place), use something like `T` instead: - -```ignore -impl MyTrait for Option { - // ... -} -``` - -On the other hand, if you wished to refer to the specific type `u8`, remove it -from the type parameter list: - -```ignore -impl MyTrait for Option { - // ... -} - -See the Types section of the reference for more information about the primitive -types: - -https://doc.rust-lang.org/reference.html#types -"##, - E0364: r##" Private items cannot be publicly re-exported. This error indicates that you attempted to `pub use` a type or value that was not itself public. diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 77fdc657b88..ab1d708f952 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1619,15 +1619,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { intravisit::walk_crate(self, krate); } - fn check_if_primitive_type_name(&self, name: Name, span: Span) { - if let Some(_) = self.primitive_type_table.primitive_types.get(&name) { - span_err!(self.session, - span, - E0317, - "user-defined types or type parameters cannot shadow the primitive types"); - } - } - fn resolve_item(&mut self, item: &Item) { let name = item.name; @@ -1637,8 +1628,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ItemEnum(_, ref generics) | ItemTy(_, ref generics) | ItemStruct(_, ref generics) => { - self.check_if_primitive_type_name(name, item.span); - self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, ItemRibKind), |this| intravisit::walk_item(this, item)); } @@ -1659,8 +1648,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } ItemTrait(_, ref generics, ref bounds, ref trait_items) => { - self.check_if_primitive_type_name(name, item.span); - // Create a new rib for the trait-wide type parameters. self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, @@ -1695,8 +1682,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); } hir::TypeTraitItem(..) => { - this.check_if_primitive_type_name(trait_item.name, - trait_item.span); this.with_type_parameter_rib(NoTypeParameters, |this| { intravisit::walk_trait_item(this, trait_item) }); @@ -1720,28 +1705,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } ItemUse(ref view_path) => { - // check for imports shadowing primitive types - let check_rename = |this: &Self, id, name| { - match this.def_map.borrow().get(&id).map(|d| d.full_def()) { - Some(Def::Enum(..)) | Some(Def::TyAlias(..)) | Some(Def::Struct(..)) | - Some(Def::Trait(..)) | None => { - this.check_if_primitive_type_name(name, item.span); - } - _ => {} - } - }; - match view_path.node { - hir::ViewPathSimple(name, _) => { - check_rename(self, item.id, name); - } hir::ViewPathList(ref prefix, ref items) => { - for item in items { - if let Some(name) = item.node.rename() { - check_rename(self, item.node.id(), name); - } - } - // Resolve prefix of an import with empty braces (issue #28388) if items.is_empty() && !prefix.segments.is_empty() { match self.resolve_crate_relative_path(prefix.span, @@ -1922,9 +1887,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } fn resolve_generics(&mut self, generics: &Generics) { - for type_parameter in generics.ty_params.iter() { - self.check_if_primitive_type_name(type_parameter.name, type_parameter.span); - } for predicate in &generics.where_clause.predicates { match predicate { &hir::WherePredicate::BoundPredicate(_) | @@ -2658,15 +2620,37 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Try to find a path to an item in a module. let last_ident = segments.last().unwrap().identifier; - if segments.len() <= 1 { - let unqualified_def = self.resolve_identifier(last_ident, namespace, true); - return unqualified_def.and_then(|def| self.adjust_local_def(def, span)) - .map(|def| { - PathResolution::new(def, path_depth) - }); + // Resolve a single identifier with fallback to primitive types + let resolve_identifier_with_fallback = |this: &mut Self, record_used| { + let def = this.resolve_identifier(last_ident, namespace, record_used); + match def { + None | Some(LocalDef{def: Def::Mod(..), ..}) if namespace == TypeNS => + this.primitive_type_table + .primitive_types + .get(&last_ident.unhygienic_name) + .map_or(def, |prim_ty| Some(LocalDef::from_def(Def::PrimTy(*prim_ty)))), + _ => def + } + }; + + if segments.len() == 1 { + // In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we + // don't report an error right away, but try to fallback to a primitive type. + // So, we are still able to successfully resolve something like + // + // use std::u8; // bring module u8 in scope + // fn f() -> u8 { // OK, resolves to primitive u8, not to std::u8 + // u8::max_value() // OK, resolves to associated function ::max_value, + // // not to non-existent std::u8::max_value + // } + // + // Such behavior is required for backward compatibility. + // The same fallback is used when `a` resolves to nothing. + let unqualified_def = resolve_identifier_with_fallback(self, true); + return unqualified_def.and_then(|def| self.adjust_local_def(def, span)).map(mk_res); } - let unqualified_def = self.resolve_identifier(last_ident, namespace, false); + let unqualified_def = resolve_identifier_with_fallback(self, false); let def = self.resolve_module_relative_path(span, segments, namespace); match (def, unqualified_def) { (Some(d), Some(ref ud)) if d == ud.def => { @@ -2692,15 +2676,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return Some(LocalDef::from_def(Def::Err)); } - // First, check to see whether the name is a primitive type. - if namespace == TypeNS { - if let Some(&prim_ty) = self.primitive_type_table - .primitive_types - .get(&identifier.unhygienic_name) { - return Some(LocalDef::from_def(Def::PrimTy(prim_ty))); - } - } - self.resolve_identifier_in_local_ribs(identifier, namespace, record_used) } diff --git a/src/test/compile-fail/issue-20427.rs b/src/test/run-pass/issue-20427.rs similarity index 55% rename from src/test/compile-fail/issue-20427.rs rename to src/test/run-pass/issue-20427.rs index 99dd22a888c..dd3d952224c 100644 --- a/src/test/compile-fail/issue-20427.rs +++ b/src/test/run-pass/issue-20427.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -9,17 +9,17 @@ // except according to those terms. // aux-build:i8.rs +// ignore-pretty (#23623) + extern crate i8; use std::string as i16; static i32: i32 = 0; const i64: i64 = 0; fn u8(f32: f32) {} fn f(f64: f64) {} -//~^ ERROR user-defined types or type parameters cannot shadow the primitive types -type u16 = u16; //~ ERROR user-defined types or type parameters cannot shadow the primitive types -enum u32 {} //~ ERROR user-defined types or type parameters cannot shadow the primitive types -struct u64; //~ ERROR user-defined types or type parameters cannot shadow the primitive types -trait bool {} //~ ERROR user-defined types or type parameters cannot shadow the primitive types +enum u32 {} +struct u64; +trait bool {} mod char { extern crate i8; @@ -40,29 +40,52 @@ mod char { use super::u8_ as u8; use super::f_ as f64; use super::u16_ as u16; - //~^ ERROR user-defined types or type parameters cannot shadow the primitive types use super::u32_ as u32; - //~^ ERROR user-defined types or type parameters cannot shadow the primitive types use super::u64_ as u64; - //~^ ERROR user-defined types or type parameters cannot shadow the primitive types use super::bool_ as bool; - //~^ ERROR user-defined types or type parameters cannot shadow the primitive types use super::{bool_ as str}; - //~^ ERROR user-defined types or type parameters cannot shadow the primitive types use super::char_ as char; } } trait isize_ { - type isize; //~ ERROR user-defined types or type parameters cannot shadow the primitive types + type isize; } fn usize<'usize>(usize: &'usize usize) -> &'usize usize { usize } +mod reuse { + use std::mem::size_of; + + type u8 = u64; + use std::string::String as i16; + + pub fn check() { + assert_eq!(size_of::(), 8); + assert_eq!(size_of::<::u64>(), 0); + assert_eq!(size_of::(), 3 * size_of::<*const ()>()); + assert_eq!(size_of::(), 0); + } +} + +mod guard { + pub fn check() { + use std::u8; // bring module u8 in scope + fn f() -> u8 { // OK, resolves to primitive u8, not to std::u8 + u8::max_value() // OK, resolves to associated function ::max_value, + // not to non-existent std::u8::max_value + } + assert_eq!(f(), u8::MAX); // OK, resolves to std::u8::MAX + } +} + fn main() { let bool = true; - match bool { + let _ = match bool { str @ true => if str { i32 as i64 } else { i64 }, false => i64, }; + + reuse::check::(); + guard::check(); }