]> git.lizzy.rs Git - rust.git/commitdiff
Introduce name resolution fallback for primitive types
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Tue, 8 Mar 2016 18:40:13 +0000 (21:40 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Thu, 24 Mar 2016 21:41:09 +0000 (00:41 +0300)
src/librustc_resolve/lib.rs
src/test/compile-fail/issue-20427.rs

index af8c9d81687421457d089e80ed7cd1e90c040006..8efac52158ecedb73c388b16958a98926c123cb8 100644 (file)
@@ -2654,15 +2654,27 @@ pub fn resolve_path(&mut self,
 
         // 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 @@ pub fn resolve_path(&mut self,
         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 @@ fn resolve_identifier(&mut self,
             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)
     }
 
index 99dd22a888cb56508f759f0a2183cfe23354200e..7dedb9593e13c4c55fc1b66a46da57ef4bd6dbf9 100644 (file)
@@ -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