Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Introduce name resolution fallback for primitive types
  • Loading branch information
petrochenkov committed Mar 21, 2016
commit 104bc140013bca737af79de659b298bfcdc9f8ea
49 changes: 37 additions & 12 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2654,15 +2654,27 @@ 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);
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 // OK, resolves to associated constant <u8>::MAX,
// // not to non-existent std::u8::MAX
// }
//
// Such behavior is required for backward compatibility.
// The same fallback is used when `a` resolves to nothing.
let unqualified_def = self.resolve_identifier_with_fallback(last_ident, namespace, true);
return unqualified_def.and_then(|def| self.adjust_local_def(def, span))
.map(|def| {
PathResolution::new(def, path_depth)
});
}

let unqualified_def = self.resolve_identifier(last_ident, namespace, false);
let unqualified_def = self.resolve_identifier_with_fallback(last_ident, namespace, false);
let def = self.resolve_module_relative_path(span, segments, namespace);
match (def, unqualified_def) {
(Some(d), Some(ref ud)) if d == ud.def => {
Expand All @@ -2678,6 +2690,28 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
def.map(mk_res)
}

// Resolve a single identifier with fallback to primitive types
fn resolve_identifier_with_fallback(&mut self,
identifier: hir::Ident,
namespace: Namespace,
check_ribs: bool,
record_used: bool)
-> Option<LocalDef> {
let def = self.resolve_identifier(identifier, namespace, check_ribs, record_used);
match def {
None | Some(LocalDef{def: Def::Mod(..), ..}) => {
if let Some(&prim_ty) = self.primitive_type_table
.primitive_types
.get(&identifier.unhygienic_name) {
Some(LocalDef::from_def(Def::PrimTy(prim_ty)))
} else {
def
}
}
_ => def
}
}

// Resolve a single identifier
fn resolve_identifier(&mut self,
identifier: hir::Ident,
Expand All @@ -2688,15 +2722,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)
}

Expand Down
1 change: 1 addition & 0 deletions src/test/compile-fail/issue-20427.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ fn u8(f32: f32) {}
fn f<f64>(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
//~^ ERROR unsupported cyclic reference between types/traits detected
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
Expand Down