]> git.lizzy.rs Git - rust.git/commitdiff
Privatize fields of PathResolution
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sat, 18 Feb 2017 19:11:42 +0000 (22:11 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sat, 18 Feb 2017 21:34:08 +0000 (00:34 +0300)
Ensure Def::Err has depth == 0

src/librustc/hir/def.rs
src/librustc/hir/lowering.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/test/compile-fail/issue-39559.rs [new file with mode: 0644]

index b6fce2d6ca0be1d6474c92e0a36ab43b4e04df75..53b7be74f85037dcaea5d9e7c362f0413d41447b 100644 (file)
@@ -59,32 +59,45 @@ pub enum Def {
     Err,
 }
 
-/// The result of resolving a path.
-/// Before type checking completes, `depth` represents the number of
-/// trailing segments which are yet unresolved. Afterwards, if there
-/// were no errors, all paths should be fully resolved, with `depth`
-/// set to `0` and `base_def` representing the final resolution.
-///
+/// The result of resolving a path before lowering to HIR.
+/// `base_def` is definition of resolved part of the
+/// path, `unresolved_segments` is the number of unresolved
+/// segments.
 ///     module::Type::AssocX::AssocY::MethodOrAssocType
 ///     ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-///     base_def      depth = 3
+///     base_def      unresolved_segments = 3
 ///
 ///     <T as Trait>::AssocX::AssocY::MethodOrAssocType
 ///           ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
-///           base_def        depth = 2
+///           base_def        unresolved_segments = 2
 #[derive(Copy, Clone, Debug)]
 pub struct PathResolution {
-    pub base_def: Def,
-    pub depth: usize
+    base_def: Def,
+    unresolved_segments: usize,
 }
 
 impl PathResolution {
-    pub fn new(def: Def) -> PathResolution {
-        PathResolution { base_def: def, depth: 0 }
+    pub fn new(def: Def) -> Self {
+        PathResolution { base_def: def, unresolved_segments: 0 }
+    }
+
+    pub fn with_unresolved_segments(def: Def, mut unresolved_segments: usize) -> Self {
+        if def == Def::Err { unresolved_segments = 0 }
+        PathResolution { base_def: def, unresolved_segments: unresolved_segments }
+    }
+
+    #[inline]
+    pub fn base_def(&self) -> Def {
+        self.base_def
+    }
+
+    #[inline]
+    pub fn unresolved_segments(&self) -> usize {
+        self.unresolved_segments
     }
 
     pub fn kind_name(&self) -> &'static str {
-        if self.depth != 0 {
+        if self.unresolved_segments != 0 {
             "associated item"
         } else {
             self.base_def.kind_name()
index 8a4acb3d03880b57acd47ec2c2885892f71afe89..c87ce6505fcd505e81bff483904cec8e691ff254 100644 (file)
@@ -217,10 +217,10 @@ fn next_id(&self) -> NodeId {
 
     fn expect_full_def(&mut self, id: NodeId) -> Def {
         self.resolver.get_resolution(id).map_or(Def::Err, |pr| {
-            if pr.depth != 0 {
+            if pr.unresolved_segments() != 0 {
                 bug!("path not fully resolved: {:?}", pr);
             }
-            pr.base_def
+            pr.base_def()
         })
     }
 
@@ -421,9 +421,9 @@ fn lower_qpath(&mut self,
         let resolution = self.resolver.get_resolution(id)
                                       .unwrap_or(PathResolution::new(Def::Err));
 
-        let proj_start = p.segments.len() - resolution.depth;
+        let proj_start = p.segments.len() - resolution.unresolved_segments();
         let path = P(hir::Path {
-            def: resolution.base_def,
+            def: resolution.base_def(),
             segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| {
                 let param_mode = match (qself_position, param_mode) {
                     (Some(j), ParamMode::Optional) if i < j => {
@@ -443,7 +443,7 @@ fn lower_qpath(&mut self,
                         index: this.def_key(def_id).parent.expect("missing parent")
                     }
                 };
-                let type_def_id = match resolution.base_def {
+                let type_def_id = match resolution.base_def() {
                     Def::AssociatedTy(def_id) if i + 2 == proj_start => {
                         Some(parent_def_id(self, def_id))
                     }
@@ -474,7 +474,7 @@ fn lower_qpath(&mut self,
 
         // Simple case, either no projections, or only fully-qualified.
         // E.g. `std::mem::size_of` or `<I as Iterator>::Item`.
-        if resolution.depth == 0 {
+        if resolution.unresolved_segments() == 0 {
             return hir::QPath::Resolved(qself, path);
         }
 
@@ -749,7 +749,7 @@ fn lower_generics(&mut self, g: &Generics) -> hir::Generics {
                                        bound_pred.bound_lifetimes.is_empty() => {
                                 if let Some(Def::TyParam(def_id)) =
                                         self.resolver.get_resolution(bound_pred.bounded_ty.id)
-                                                     .map(|d| d.base_def) {
+                                                     .map(|d| d.base_def()) {
                                     if let Some(node_id) =
                                             self.resolver.definitions().as_local_node_id(def_id) {
                                         for ty_param in &g.ty_params {
@@ -1295,7 +1295,7 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                 PatKind::Wild => hir::PatKind::Wild,
                 PatKind::Ident(ref binding_mode, pth1, ref sub) => {
                     self.with_parent_def(p.id, |this| {
-                        match this.resolver.get_resolution(p.id).map(|d| d.base_def) {
+                        match this.resolver.get_resolution(p.id).map(|d| d.base_def()) {
                             // `None` can occur in body-less function signatures
                             def @ None | def @ Some(Def::Local(_)) => {
                                 let def_id = def.map(|d| d.def_id()).unwrap_or_else(|| {
index fa3c12624c67ebbd38ddf6187977d0fdef64d910..c9e870188aaeccb36199b4d13a3d4178ff4961da 100644 (file)
@@ -1195,7 +1195,8 @@ fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) {
         let path: Vec<_> = segments.iter().map(|seg| Ident::with_empty_ctxt(seg.name)).collect();
         match self.resolve_path(&path, Some(namespace), Some(span)) {
             PathResult::Module(module) => *def = module.def().unwrap(),
-            PathResult::NonModule(path_res) if path_res.depth == 0 => *def = path_res.base_def,
+            PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
+                *def = path_res.base_def(),
             PathResult::NonModule(..) => match self.resolve_path(&path, None, Some(span)) {
                 PathResult::Failed(msg, _) => {
                     resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
@@ -1718,7 +1719,7 @@ fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f:
         let mut new_id = None;
         if let Some(trait_ref) = opt_trait_ref {
             let def = self.smart_resolve_path(trait_ref.ref_id, None,
-                                              &trait_ref.path, PathSource::Trait).base_def;
+                                              &trait_ref.path, PathSource::Trait).base_def();
             if def != Def::Err {
                 new_val = Some((def.def_id(), trait_ref.clone()));
                 new_id = Some(def.def_id());
@@ -1849,8 +1850,8 @@ fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
 
         pat.walk(&mut |pat| {
             if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node {
-                if sub_pat.is_some() || match self.def_map.get(&pat.id) {
-                    Some(&PathResolution { base_def: Def::Local(..), .. }) => true,
+                if sub_pat.is_some() || match self.def_map.get(&pat.id).map(|res| res.base_def()) {
+                    Some(Def::Local(..)) => true,
                     _ => false,
                 } {
                     let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode };
@@ -2248,14 +2249,14 @@ fn smart_resolve_path_fragment(&mut self,
         let resolution = match self.resolve_qpath_anywhere(id, qself, path, ns, span,
                                                            source.defer_to_typeck(),
                                                            source.global_by_default()) {
-            Some(resolution) if resolution.depth == 0 => {
-                if is_expected(resolution.base_def) || resolution.base_def == Def::Err {
+            Some(resolution) if resolution.unresolved_segments() == 0 => {
+                if is_expected(resolution.base_def()) || resolution.base_def() == Def::Err {
                     resolution
                 } else {
                     // Add a temporary hack to smooth the transition to new struct ctor
                     // visibility rules. See #38932 for more details.
                     let mut res = None;
-                    if let Def::Struct(def_id) = resolution.base_def {
+                    if let Def::Struct(def_id) = resolution.base_def() {
                         if let Some((ctor_def, ctor_vis))
                                 = self.struct_constructors.get(&def_id).cloned() {
                             if is_expected(ctor_def) && self.is_accessible(ctor_vis) {
@@ -2268,7 +2269,7 @@ fn smart_resolve_path_fragment(&mut self,
                         }
                     }
 
-                    res.unwrap_or_else(|| report_errors(self, Some(resolution.base_def)))
+                    res.unwrap_or_else(|| report_errors(self, Some(resolution.base_def())))
                 }
             }
             Some(resolution) if source.defer_to_typeck() => {
@@ -2321,7 +2322,8 @@ fn resolve_qpath_anywhere(&mut self,
                 match self.resolve_qpath(id, qself, path, ns, span, global_by_default) {
                     // If defer_to_typeck, then resolution > no resolution,
                     // otherwise full resolution > partial resolution > no resolution.
-                    Some(res) if res.depth == 0 || defer_to_typeck => return Some(res),
+                    Some(res) if res.unresolved_segments() == 0 || defer_to_typeck =>
+                        return Some(res),
                     res => if fin_res.is_none() { fin_res = res },
                 };
             }
@@ -2346,19 +2348,17 @@ fn resolve_qpath(&mut self,
         if let Some(qself) = qself {
             if qself.position == 0 {
                 // FIXME: Create some fake resolution that can't possibly be a type.
-                return Some(PathResolution {
-                    base_def: Def::Mod(DefId::local(CRATE_DEF_INDEX)),
-                    depth: path.len(),
-                });
+                return Some(PathResolution::with_unresolved_segments(
+                    Def::Mod(DefId::local(CRATE_DEF_INDEX)), path.len()
+                ));
             }
             // Make sure `A::B` in `<T as A>::B::C` is a trait item.
             let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
-            let mut res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1],
-                                                           span, PathSource::TraitItem(ns));
-            if res.base_def != Def::Err {
-                res.depth += path.len() - qself.position - 1;
-            }
-            return Some(res);
+            let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1],
+                                                       span, PathSource::TraitItem(ns));
+            return Some(PathResolution::with_unresolved_segments(
+                res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1
+            ));
         }
 
         let result = match self.resolve_path(&path, Some(ns), Some(span)) {
@@ -2393,10 +2393,7 @@ fn resolve_qpath(&mut self,
                     }
                     _ => {}
                 }
-                PathResolution {
-                    base_def: Def::PrimTy(prim),
-                    depth: path.len() - 1,
-                }
+                PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1)
             }
             PathResult::Module(module) => PathResolution::new(module.def().unwrap()),
             PathResult::Failed(msg, false) => {
@@ -2407,16 +2404,16 @@ fn resolve_qpath(&mut self,
             PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"),
         };
 
-        if path.len() > 1 && !global_by_default && result.base_def != Def::Err &&
+        if path.len() > 1 && !global_by_default && result.base_def() != Def::Err &&
            path[0].name != keywords::CrateRoot.name() && path[0].name != "$crate" {
             let unqualified_result = {
                 match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) {
-                    PathResult::NonModule(path_res) => path_res.base_def,
+                    PathResult::NonModule(path_res) => path_res.base_def(),
                     PathResult::Module(module) => module.def().unwrap(),
                     _ => return Some(result),
                 }
             };
-            if result.base_def == unqualified_result {
+            if result.base_def() == unqualified_result {
                 let lint = lint::builtin::UNUSED_QUALIFICATIONS;
                 self.session.add_lint(lint, id, span, "unnecessary qualification".to_string());
             }
@@ -2470,10 +2467,9 @@ fn resolve_path(&mut self,
                     Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
                     Some(LexicalScopeBinding::Def(def))
                             if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => {
-                        return PathResult::NonModule(PathResolution {
-                            base_def: def,
-                            depth: path.len() - 1,
-                        });
+                        return PathResult::NonModule(PathResolution::with_unresolved_segments(
+                            def, path.len() - 1
+                        ));
                     }
                     _ => Err(if record_used.is_some() { Determined } else { Undetermined }),
                 }
@@ -2488,10 +2484,9 @@ fn resolve_path(&mut self,
                     } else if def == Def::Err {
                         return PathResult::NonModule(err_path_resolution());
                     } else if opt_ns.is_some() && (is_last || maybe_assoc) {
-                        return PathResult::NonModule(PathResolution {
-                            base_def: def,
-                            depth: path.len() - i - 1,
-                        });
+                        return PathResult::NonModule(PathResolution::with_unresolved_segments(
+                            def, path.len() - i - 1
+                        ));
                     } else {
                         return PathResult::Failed(format!("Not a module `{}`", ident), is_last);
                     }
@@ -2500,10 +2495,9 @@ fn resolve_path(&mut self,
                 Err(Determined) => {
                     if let Some(module) = module {
                         if opt_ns.is_some() && !module.is_normal() {
-                            return PathResult::NonModule(PathResolution {
-                                base_def: module.def().unwrap(),
-                                depth: path.len() - i,
-                            });
+                            return PathResult::NonModule(PathResolution::with_unresolved_segments(
+                                module.def().unwrap(), path.len() - i
+                            ));
                         }
                     }
                     let msg = if module.and_then(ModuleData::def) == self.graph_root.def() {
@@ -2672,8 +2666,9 @@ fn extract_node_id(t: &Ty) -> Option<NodeId> {
             if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) {
                 // Look for a field with the same name in the current self_type.
                 if let Some(resolution) = self.def_map.get(&node_id) {
-                    match resolution.base_def {
-                        Def::Struct(did) | Def::Union(did) if resolution.depth == 0 => {
+                    match resolution.base_def() {
+                        Def::Struct(did) | Def::Union(did)
+                                if resolution.unresolved_segments() == 0 => {
                             if let Some(field_names) = self.field_names.get(&did) {
                                 if field_names.iter().any(|&field_name| name == field_name) {
                                     return Some(AssocSuggestion::Field);
@@ -3057,7 +3052,6 @@ fn lookup_import_candidates<FilterFn>(&mut self,
 
     fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
         debug!("(recording def) recording {:?} for {}", resolution, node_id);
-        assert!(resolution.depth == 0 || resolution.base_def != Def::Err);
         if let Some(prev_res) = self.def_map.insert(node_id, resolution) {
             panic!("path resolved multiple times ({:?} before, {:?} now)", prev_res, resolution);
         }
@@ -3071,7 +3065,8 @@ fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
                 ty::Visibility::Restricted(self.current_module.normal_ancestor_id)
             }
             ast::Visibility::Restricted { ref path, id } => {
-                let def = self.smart_resolve_path(id, None, path, PathSource::Visibility).base_def;
+                let def = self.smart_resolve_path(id, None, path,
+                                                  PathSource::Visibility).base_def();
                 if def == Def::Err {
                     ty::Visibility::Public
                 } else {
index 880f5f388d0601ff45b34ea137a5566c797d6e1d..8d563d20549c3b8e78108d75231941ce3b54e358 100644 (file)
@@ -262,7 +262,7 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind,
             }
 
             let ext = match self.resolve_path(&path, Some(MacroNS), None) {
-                PathResult::NonModule(path_res) => match path_res.base_def {
+                PathResult::NonModule(path_res) => match path_res.base_def() {
                     Def::Err => Err(Determinacy::Determined),
                     def @ _ => Ok(self.get_macro(def)),
                 },
diff --git a/src/test/compile-fail/issue-39559.rs b/src/test/compile-fail/issue-39559.rs
new file mode 100644 (file)
index 0000000..a56a5e8
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2017 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Dim {
+    fn dim() -> usize;
+}
+
+enum Dim3 {}
+
+impl Dim for Dim3 {
+    fn dim() -> usize {
+        3
+    }
+}
+
+pub struct Vector<T, D: Dim> {
+    entries: [T; D::dim()]
+    //~^ ERROR cannot use an outer type parameter in this context
+    //~| ERROR constant evaluation error
+}
+
+fn main() {
+    let array: [usize; Dim3::dim()] = [0; Dim3::dim()];
+}