Introduce name resolution fallback for primitive types
This commit is contained in:
parent
dcfb8d72e9
commit
8d4b1d1cf3
@ -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 => {
|
||||
@ -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,
|
||||
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user