]> git.lizzy.rs Git - rust.git/commitdiff
rustc: desugar UFCS as much as possible during HIR lowering.
authorEduard Burtescu <edy.burt@gmail.com>
Thu, 27 Oct 2016 02:17:42 +0000 (05:17 +0300)
committerEduard-Mihai Burtescu <edy.burt@gmail.com>
Mon, 28 Nov 2016 02:18:10 +0000 (04:18 +0200)
41 files changed:
src/librustc/cfg/construct.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/mod.rs
src/librustc/hir/pat_util.rs
src/librustc/hir/print.rs
src/librustc/infer/error_reporting.rs
src/librustc/middle/astconv_util.rs
src/librustc/middle/dead.rs
src/librustc/middle/effect.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/intrinsicck.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/reachable.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/stability.rs
src/librustc/ty/mod.rs
src/librustc_const_eval/_match.rs
src/librustc_const_eval/eval.rs
src/librustc_incremental/calculate_svh/svh_visitor.rs
src/librustc_lint/bad_style.rs
src/librustc_lint/builtin.rs
src/librustc_lint/unused.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_passes/consts.rs
src/librustc_passes/hir_stats.rs
src/librustc_passes/static_recursion.rs
src/librustc_privacy/lib.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/collect.rs
src/librustdoc/clean/mod.rs
src/test/compile-fail/issue-28992-empty.rs
src/test/compile-fail/method-path-in-pattern.rs
src/test/compile-fail/qualified-path-params.rs
src/test/compile-fail/unspecified-self-in-trait-ref.rs
src/test/pretty/issue-4264.pp

index c399623462b5d732368fe2fab0ac64b762521ee2..609d492a93aec5e9930547963e7407ea4f1a5c5e 100644 (file)
@@ -100,7 +100,7 @@ fn decl(&mut self, decl: &hir::Decl, pred: CFGIndex) -> CFGIndex {
     fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex {
         match pat.node {
             PatKind::Binding(.., None) |
-            PatKind::Path(..) |
+            PatKind::Path(_) |
             PatKind::Lit(..) |
             PatKind::Range(..) |
             PatKind::Wild => {
@@ -361,7 +361,7 @@ fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex {
 
             hir::ExprClosure(..) |
             hir::ExprLit(..) |
-            hir::ExprPath(..) => {
+            hir::ExprPath(_) => {
                 self.straightline(expr, pred, None::<hir::Expr>.iter())
             }
         }
index 7dd88e36dd1f55ca7fe93d2092f2f893e801fe8c..743eed74d0cea6856babb2bc15c5e4021810f958 100644 (file)
@@ -244,6 +244,9 @@ fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
     fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) {
         walk_lifetime_def(self, lifetime)
     }
+    fn visit_qpath(&mut self, qpath: &'v QPath, id: NodeId, span: Span) {
+        walk_qpath(self, qpath, id, span)
+    }
     fn visit_path(&mut self, path: &'v Path, _id: NodeId) {
         walk_path(self, path)
     }
@@ -481,11 +484,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             walk_fn_decl(visitor, &function_declaration.decl);
             walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes);
         }
-        TyPath(ref maybe_qself, ref path) => {
-            if let Some(ref qself) = *maybe_qself {
-                visitor.visit_ty(&qself.ty);
-            }
-            visitor.visit_path(path, typ.id);
+        TyPath(ref qpath) => {
+            visitor.visit_qpath(qpath, typ.id, typ.span);
         }
         TyObjectSum(ref ty, ref bounds) => {
             visitor.visit_ty(ty);
@@ -508,6 +508,21 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
     }
 }
 
+pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath, id: NodeId, span: Span) {
+    match *qpath {
+        QPath::Resolved(ref maybe_qself, ref path) => {
+            if let Some(ref qself) = *maybe_qself {
+                visitor.visit_ty(qself);
+            }
+            visitor.visit_path(path, id)
+        }
+        QPath::TypeRelative(ref qself, ref segment) => {
+            visitor.visit_ty(qself);
+            visitor.visit_path_segment(span, segment);
+        }
+    }
+}
+
 pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
     for segment in &path.segments {
         visitor.visit_path_segment(path.span, segment);
@@ -555,18 +570,15 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
 pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
     visitor.visit_id(pattern.id);
     match pattern.node {
-        PatKind::TupleStruct(ref path, ref children, _) => {
-            visitor.visit_path(path, pattern.id);
+        PatKind::TupleStruct(ref qpath, ref children, _) => {
+            visitor.visit_qpath(qpath, pattern.id, pattern.span);
             walk_list!(visitor, visit_pat, children);
         }
-        PatKind::Path(ref opt_qself, ref path) => {
-            if let Some(ref qself) = *opt_qself {
-                visitor.visit_ty(&qself.ty);
-            }
-            visitor.visit_path(path, pattern.id)
+        PatKind::Path(ref qpath) => {
+            visitor.visit_qpath(qpath, pattern.id, pattern.span);
         }
-        PatKind::Struct(ref path, ref fields, _) => {
-            visitor.visit_path(path, pattern.id);
+        PatKind::Struct(ref qpath, ref fields, _) => {
+            visitor.visit_qpath(qpath, pattern.id, pattern.span);
             for field in fields {
                 visitor.visit_name(field.span, field.node.name);
                 visitor.visit_pat(&field.node.pat)
@@ -840,8 +852,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             visitor.visit_expr(element);
             visitor.visit_expr(count)
         }
-        ExprStruct(ref path, ref fields, ref optional_base) => {
-            visitor.visit_path(path, expression.id);
+        ExprStruct(ref qpath, ref fields, ref optional_base) => {
+            visitor.visit_qpath(qpath, expression.id, expression.span);
             for field in fields {
                 visitor.visit_name(field.name.span, field.name.node);
                 visitor.visit_expr(&field.expr)
@@ -917,11 +929,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             visitor.visit_expr(main_expression);
             visitor.visit_expr(index_expression)
         }
-        ExprPath(ref maybe_qself, ref path) => {
-            if let Some(ref qself) = *maybe_qself {
-                visitor.visit_ty(&qself.ty);
-            }
-            visitor.visit_path(path, expression.id)
+        ExprPath(ref qpath) => {
+            visitor.visit_qpath(qpath, expression.id, expression.span);
         }
         ExprBreak(ref opt_sp_name, ref opt_expr) => {
             walk_opt_sp_name(visitor, opt_sp_name);
index 264a5722bcd76ad7f8c4f079ee85550769c18c7f..056c1b906206a5492f344d258fa65e458d731b1c 100644 (file)
@@ -188,13 +188,13 @@ fn lower_view_path(&mut self, view_path: &ViewPath) -> P<hir::ViewPath> {
             node: match view_path.node {
                 ViewPathSimple(ident, ref path) => {
                     hir::ViewPathSimple(ident.name,
-                                        self.lower_path(path, None, ParamMode::Explicit))
+                                        self.lower_path(path, ParamMode::Explicit))
                 }
                 ViewPathGlob(ref path) => {
-                    hir::ViewPathGlob(self.lower_path(path, None, ParamMode::Explicit))
+                    hir::ViewPathGlob(self.lower_path(path, ParamMode::Explicit))
                 }
                 ViewPathList(ref path, ref path_list_idents) => {
-                    hir::ViewPathList(self.lower_path(path, None, ParamMode::Explicit),
+                    hir::ViewPathList(self.lower_path(path, ParamMode::Explicit),
                                       path_list_idents.iter()
                                                       .map(|item| self.lower_path_list_item(item))
                                                       .collect())
@@ -259,14 +259,7 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
                     return self.lower_ty(ty);
                 }
                 TyKind::Path(ref qself, ref path) => {
-                    let qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
-                        hir::QSelf {
-                            ty: self.lower_ty(ty),
-                            position: position,
-                        }
-                    });
-                    let path = self.lower_path(path, qself.as_ref(), ParamMode::Explicit);
-                    hir::TyPath(qself, path)
+                    hir::TyPath(self.lower_qpath(t.id, qself, path, ParamMode::Explicit))
                 }
                 TyKind::ObjectSum(ref ty, ref bounds) => {
                     hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds))
@@ -308,17 +301,24 @@ fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
         }
     }
 
-    fn lower_path(&mut self,
-                  p: &Path,
-                  qself: Option<&hir::QSelf>,
-                  param_mode: ParamMode)
-                  -> hir::Path {
-        hir::Path {
+    fn lower_qpath(&mut self,
+                   id: NodeId,
+                   qself: &Option<QSelf>,
+                   p: &Path,
+                   param_mode: ParamMode)
+                   -> hir::QPath {
+        let qself_position = qself.as_ref().map(|q| q.position);
+        let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty));
+
+        let resolution = self.resolver.get_resolution(id)
+                                      .unwrap_or(PathResolution::new(Def::Err));
+
+        let proj_start = p.segments.len() - resolution.depth;
+        let path = P(hir::Path {
             global: p.global,
-            segments: p.segments.iter().enumerate().map(|(i, segment)| {
-                let PathSegment { identifier, ref parameters } = *segment;
-                let param_mode = match (qself, param_mode) {
-                    (Some(qself), ParamMode::Optional) if i < qself.position => {
+            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 => {
                         // This segment is part of the trait path in a
                         // qualified path - one of `a`, `b` or `Trait`
                         // in `<X as a::b::Trait>::T::U::method`.
@@ -326,26 +326,91 @@ fn lower_path(&mut self,
                     }
                     _ => param_mode
                 };
-                hir::PathSegment {
-                    name: identifier.name,
-                    parameters: self.lower_path_parameters(parameters, param_mode),
-                }
+                self.lower_path_segment(segment, param_mode)
             }).collect(),
             span: p.span,
+        });
+
+        // Simple case, either no projections, or only fully-qualified.
+        // E.g. `std::mem::size_of` or `<I as Iterator>::Item`.
+        if resolution.depth == 0 {
+            return hir::QPath::Resolved(qself, path);
         }
+
+        // Create the innermost type that we're projecting from.
+        let mut ty = if path.segments.is_empty() {
+            // If the base path is empty that means there exists a
+            // syntactical `Self`, e.g. `&i32` in `<&i32>::clone`.
+            qself.expect("missing QSelf for <T>::...")
+        } else {
+            // Otherwise, the base path is an implicit `Self` type path,
+            // e.g. `Vec` in `Vec::new` or `<I as Iterator>::Item` in
+            // `<I as Iterator>::Item::default`.
+            let ty = self.ty(p.span, hir::TyPath(hir::QPath::Resolved(qself, path)));
+
+            // Associate that innermost path type with the base Def.
+            self.resolver.record_resolution(ty.id, resolution.base_def);
+
+            ty
+        };
+
+        // Anything after the base path are associated "extensions",
+        // out of which all but the last one are associated types,
+        // e.g. for `std::vec::Vec::<T>::IntoIter::Item::clone`:
+        // * base path is `std::vec::Vec<T>`
+        // * "extensions" are `IntoIter`, `Item` and `clone`
+        // * type nodes are:
+        //   1. `std::vec::Vec<T>` (created above)
+        //   2. `<std::vec::Vec<T>>::IntoIter`
+        //   3. `<<std::vec::Vec<T>>::IntoIter>::Item`
+        // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
+        for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
+            let segment = P(self.lower_path_segment(segment, param_mode));
+            let qpath = hir::QPath::TypeRelative(ty, segment);
+
+            // It's finished, return the extension of the right node type.
+            if i == p.segments.len() - 1 {
+                return qpath;
+            }
+
+            // Wrap the associated extension in another type node.
+            ty = self.ty(p.span, hir::TyPath(qpath));
+        }
+
+        // Should've returned in the for loop above.
+        span_bug!(p.span, "lower_qpath: no final extension segment in {}..{}",
+                  proj_start, p.segments.len())
     }
 
-    fn lower_path_parameters(&mut self,
-                             path_parameters: &PathParameters,
-                             param_mode: ParamMode)
-                             -> hir::PathParameters {
-        match *path_parameters {
+    fn lower_path(&mut self,
+                  p: &Path,
+                  param_mode: ParamMode)
+                  -> hir::Path {
+        hir::Path {
+            global: p.global,
+            segments: p.segments.iter().map(|segment| {
+                self.lower_path_segment(segment, param_mode)
+            }).collect(),
+            span: p.span,
+        }
+    }
+
+    fn lower_path_segment(&mut self,
+                          segment: &PathSegment,
+                          param_mode: ParamMode)
+                          -> hir::PathSegment {
+        let parameters = match segment.parameters {
             PathParameters::AngleBracketed(ref data) => {
                 let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
                 hir::AngleBracketedParameters(data)
             }
             PathParameters::Parenthesized(ref data) =>
                 hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)),
+        };
+
+        hir::PathSegment {
+            name: segment.identifier.name,
+            parameters: parameters,
         }
     }
 
@@ -521,7 +586,7 @@ fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicat
                                                           span}) => {
                 hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
                     id: id,
-                    path: self.lower_path(path, None, ParamMode::Explicit),
+                    path: self.lower_path(path, ParamMode::Explicit),
                     ty: self.lower_ty(ty),
                     span: span,
                 })
@@ -551,7 +616,7 @@ fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
 
     fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef {
         hir::TraitRef {
-            path: self.lower_path(&p.path, None, ParamMode::Explicit),
+            path: self.lower_path(&p.path, ParamMode::Explicit),
             ref_id: p.ref_id,
         }
     }
@@ -908,26 +973,26 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                                                       respan(pth1.span, pth1.node.name),
                                                       sub.as_ref().map(|x| this.lower_pat(x)))
                             }
-                            _ => hir::PatKind::Path(None, hir::Path::from_name(pth1.span,
-                                                                               pth1.node.name))
+                            _ => {
+                                let path = hir::Path::from_name(pth1.span, pth1.node.name);
+                                hir::PatKind::Path(hir::QPath::Resolved(None, P(path)))
+                            }
                         }
                     })
                 }
                 PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
                 PatKind::TupleStruct(ref path, ref pats, ddpos) => {
-                    hir::PatKind::TupleStruct(self.lower_path(path, None, ParamMode::Optional),
+                    let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional);
+                    hir::PatKind::TupleStruct(qpath,
                                               pats.iter().map(|x| self.lower_pat(x)).collect(),
                                               ddpos)
                 }
                 PatKind::Path(ref qself, ref path) => {
-                    let qself = qself.as_ref().map(|qself| {
-                        hir::QSelf { ty: self.lower_ty(&qself.ty), position: qself.position }
-                    });
-                    let path = self.lower_path(path, qself.as_ref(), ParamMode::Optional);
-                    hir::PatKind::Path(qself, path)
+                    hir::PatKind::Path(self.lower_qpath(p.id, qself, path, ParamMode::Optional))
                 }
-                PatKind::Struct(ref pth, ref fields, etc) => {
-                    let pth = self.lower_path(pth, None, ParamMode::Optional);
+                PatKind::Struct(ref path, ref fields, etc) => {
+                    let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional);
+
                     let fs = fields.iter()
                                    .map(|f| {
                                        Spanned {
@@ -940,7 +1005,7 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                                        }
                                    })
                                    .collect();
-                    hir::PatKind::Struct(pth, fs, etc)
+                    hir::PatKind::Struct(qpath, fs, etc)
                 }
                 PatKind::Tuple(ref elts, ddpos) => {
                     hir::PatKind::Tuple(elts.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
@@ -1266,14 +1331,7 @@ fn make_struct(this: &mut LoweringContext,
                     };
                 }
                 ExprKind::Path(ref qself, ref path) => {
-                    let qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
-                        hir::QSelf {
-                            ty: self.lower_ty(ty),
-                            position: position,
-                        }
-                    });
-                    let path = self.lower_path(path, qself.as_ref(), ParamMode::Optional);
-                    hir::ExprPath(qself, path)
+                    hir::ExprPath(self.lower_qpath(e.id, qself, path, ParamMode::Optional))
                 }
                 ExprKind::Break(opt_ident, ref opt_expr) => {
                     hir::ExprBreak(self.lower_opt_sp_ident(opt_ident),
@@ -1306,7 +1364,7 @@ fn make_struct(this: &mut LoweringContext,
                     hir::ExprInlineAsm(P(hir_asm), outputs, inputs)
                 }
                 ExprKind::Struct(ref path, ref fields, ref maybe_expr) => {
-                    hir::ExprStruct(P(self.lower_path(path, None, ParamMode::Optional)),
+                    hir::ExprStruct(self.lower_qpath(e.id, &None, path, ParamMode::Optional),
                                     fields.iter().map(|x| self.lower_field(x)).collect(),
                                     maybe_expr.as_ref().map(|x| P(self.lower_expr(x))))
                 }
@@ -1688,7 +1746,7 @@ fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility {
             Visibility::Crate(_) => hir::Visibility::Crate,
             Visibility::Restricted { ref path, id } => {
                 hir::Visibility::Restricted {
-                    path: P(self.lower_path(path, None, ParamMode::Explicit)),
+                    path: P(self.lower_path(path, ParamMode::Explicit)),
                     id: id
                 }
             }
@@ -1774,7 +1832,8 @@ fn expr_call(&mut self, span: Span, e: P<hir::Expr>, args: hir::HirVec<hir::Expr
     }
 
     fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> hir::Expr {
-        let expr_path = hir::ExprPath(None, self.path_ident(span, id));
+        let path = self.path_ident(span, id);
+        let expr_path = hir::ExprPath(hir::QPath::Resolved(None, P(path)));
         let expr = self.expr(span, expr_path, ThinVec::new());
 
         let def = {
@@ -1792,9 +1851,9 @@ fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>) -> hir::Expr {
 
     fn expr_path(&mut self, path: hir::Path, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
         let def = self.resolver.resolve_generated_global_path(&path, true);
-        let expr = P(self.expr(path.span, hir::ExprPath(None, path), attrs));
+        let expr = self.expr(path.span, hir::ExprPath(hir::QPath::Resolved(None, P(path))), attrs);
         self.resolver.record_resolution(expr.id, def);
-        expr
+        P(expr)
     }
 
     fn expr_match(&mut self,
@@ -1821,9 +1880,10 @@ fn expr_struct(&mut self,
                    e: Option<P<hir::Expr>>,
                    attrs: ThinVec<Attribute>) -> P<hir::Expr> {
         let def = self.resolver.resolve_generated_global_path(&path, false);
-        let expr = P(self.expr(sp, hir::ExprStruct(P(path), fields, e), attrs));
+        let qpath = hir::QPath::Resolved(None, P(path));
+        let expr = self.expr(sp, hir::ExprStruct(qpath, fields, e), attrs);
         self.resolver.record_resolution(expr.id, def);
-        expr
+        P(expr)
     }
 
     fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec<Attribute>) -> hir::Expr {
@@ -1902,10 +1962,11 @@ fn pat_none(&mut self, span: Span) -> P<hir::Pat> {
     fn pat_enum(&mut self, span: Span, path: hir::Path, subpats: hir::HirVec<P<hir::Pat>>)
                 -> P<hir::Pat> {
         let def = self.resolver.resolve_generated_global_path(&path, true);
+        let qpath = hir::QPath::Resolved(None, P(path));
         let pt = if subpats.is_empty() {
-            hir::PatKind::Path(None, path)
+            hir::PatKind::Path(qpath)
         } else {
-            hir::PatKind::TupleStruct(path, subpats, None)
+            hir::PatKind::TupleStruct(qpath, subpats, None)
         };
         let pat = self.pat(span, pt);
         self.resolver.record_resolution(pat.id, def);
@@ -2045,4 +2106,12 @@ fn signal_block_stmt(&mut self,
         });
         self.expr_block(block, attrs)
     }
+
+    fn ty(&mut self, span: Span, node: hir::Ty_) -> P<hir::Ty> {
+        P(hir::Ty {
+            id: self.next_id(),
+            node: node,
+            span: span,
+        })
+    }
 }
index 6f0a3a02380845104df96ce1ef0de7410c40c7ee..e9e84eed3e78c02c96381542d7124d073894a01e 100644 (file)
@@ -533,7 +533,7 @@ fn walk_<G>(&self, it: &mut G) -> bool
             PatKind::Lit(_) |
             PatKind::Range(..) |
             PatKind::Binding(..) |
-            PatKind::Path(..) => {
+            PatKind::Path(_) => {
                 true
             }
         }
@@ -576,16 +576,15 @@ pub enum PatKind {
 
     /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`.
     /// The `bool` is `true` in the presence of a `..`.
-    Struct(Path, HirVec<Spanned<FieldPat>>, bool),
+    Struct(QPath, HirVec<Spanned<FieldPat>>, bool),
 
     /// A tuple struct/variant pattern `Variant(x, y, .., z)`.
     /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
     /// 0 <= position <= subpats.len()
-    TupleStruct(Path, HirVec<P<Pat>>, Option<usize>),
+    TupleStruct(QPath, HirVec<P<Pat>>, Option<usize>),
 
-    /// A possibly qualified path pattern.
-    /// Such pattern can be resolved to a unit struct/variant or a constant.
-    Path(Option<QSelf>, Path),
+    /// A path pattern for an unit struct/variant or a (maybe-associated) constant.
+    Path(QPath),
 
     /// A tuple pattern `(a, b)`.
     /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
@@ -940,12 +939,8 @@ pub enum Expr_ {
     /// An indexing operation (`foo[2]`)
     ExprIndex(P<Expr>, P<Expr>),
 
-    /// Variable reference, possibly containing `::` and/or type
-    /// parameters, e.g. foo::bar::<baz>.
-    ///
-    /// Optionally "qualified",
-    /// e.g. `<HirVec<T> as SomeTrait>::SomeType`.
-    ExprPath(Option<QSelf>, Path),
+    /// Path to a definition, possibly containing lifetime or type parameters.
+    ExprPath(QPath),
 
     /// A referencing operation (`&a` or `&mut a`)
     ExprAddrOf(Mutability, P<Expr>),
@@ -963,7 +958,7 @@ pub enum Expr_ {
     ///
     /// For example, `Foo {x: 1, y: 2}`, or
     /// `Foo {x: 1, .. base}`, where `base` is the `Option<Expr>`.
-    ExprStruct(P<Path>, HirVec<Field>, Option<P<Expr>>),
+    ExprStruct(QPath, HirVec<Field>, Option<P<Expr>>),
 
     /// An array literal constructed from one repeated element.
     ///
@@ -972,22 +967,30 @@ pub enum Expr_ {
     ExprRepeat(P<Expr>, P<Expr>),
 }
 
-/// The explicit Self type in a "qualified path". The actual
-/// path, including the trait and the associated item, is stored
-/// separately. `position` represents the index of the associated
-/// item qualified with this Self type.
-///
-///     <HirVec<T> as a::b::Trait>::AssociatedItem
-///      ^~~~~     ~~~~~~~~~~~~~~^
-///      ty        position = 3
-///
-///     <HirVec<T>>::AssociatedItem
-///      ^~~~~    ^
-///      ty       position = 0
+/// Optionally `Self`-qualified value/type path or associated extension.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct QSelf {
-    pub ty: P<Ty>,
-    pub position: usize,
+pub enum QPath {
+    /// Path to a definition, optionally "fully-qualified" with a `Self`
+    /// type, if the path points to an associated item in a trait.
+    ///
+    /// E.g. an unqualified path like `Clone::clone` has `None` for `Self`,
+    /// while `<Vec<T> as Clone>::clone` has `Some(Vec<T>)` for `Self`,
+    /// even though they both have the same two-segment `Clone::clone` `Path`.
+    Resolved(Option<P<Ty>>, P<Path>),
+
+    /// Type-related paths, e.g. `<T>::default` or `<T>::Output`.
+    /// Will be resolved by type-checking to an associated item.
+    ///
+    /// UFCS source paths can desugar into this, with `Vec::new` turning into
+    /// `<Vec>::new`, and `T::X::Y::method` into `<<<T>::X>::Y>::method`,
+    /// the `X` and `Y` nodes being each a `TyPath(QPath::TypeRelative(..))`.
+    TypeRelative(P<Ty>, P<PathSegment>)
+}
+
+impl fmt::Display for QPath {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", print::qpath_to_string(self))
+    }
 }
 
 /// Hints at the original code for a `match _ { .. }`
@@ -1161,11 +1164,12 @@ pub enum Ty_ {
     TyNever,
     /// A tuple (`(A, B, C, D,...)`)
     TyTup(HirVec<P<Ty>>),
-    /// A path (`module::module::...::Type`), optionally
-    /// "qualified", e.g. `<HirVec<T> as SomeTrait>::SomeType`.
+    /// A path to a type definition (`module::module::...::Type`), or an
+    /// associated type, e.g. `<Vec<T> as Trait>::Type` or `<T>::Target`.
     ///
-    /// Type parameters are stored in the Path itself
-    TyPath(Option<QSelf>, Path),
+    /// Type parameters may be stored in each `PathSegment`.
+    TyPath(QPath),
+
     /// Something like `A+B`. Note that `B` must always be a path.
     TyObjectSum(P<Ty>, TyParamBounds),
     /// A type like `for<'a> Foo<&'a Bar>`
index 0deea941463617f664141b7a86ff8b2e7bd932fc..8e39fde367ba7c6518df27eb659fcab0a56d1b7d 100644 (file)
@@ -53,9 +53,13 @@ fn enumerate_and_adjust(self, expected_len: usize, gap_pos: Option<usize>)
 
 pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
-        PatKind::Lit(_) | PatKind::Range(..) | PatKind::Path(Some(..), _) => true,
+        PatKind::Lit(_) |
+        PatKind::Range(..) |
+        PatKind::Path(hir::QPath::Resolved(Some(..), _)) |
+        PatKind::Path(hir::QPath::TypeRelative(..)) => true,
+
         PatKind::TupleStruct(..) |
-        PatKind::Path(..) |
+        PatKind::Path(hir::QPath::Resolved(..)) |
         PatKind::Struct(..) => {
             match dm.get(&pat.id).map(|d| d.full_def()) {
                 Some(Def::Variant(..)) | Some(Def::VariantCtor(..)) => true,
@@ -69,7 +73,8 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
 
 pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
-        PatKind::Path(..) => {
+        PatKind::Path(hir::QPath::TypeRelative(..)) => true,
+        PatKind::Path(hir::QPath::Resolved(..)) => {
             match dm.get(&pat.id).map(|d| d.full_def()) {
                 Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => true,
                 _ => false
@@ -171,7 +176,7 @@ pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec<DefId> {
     pat.walk(|p| {
         match p.node {
             PatKind::TupleStruct(..) |
-            PatKind::Path(..) |
+            PatKind::Path(hir::QPath::Resolved(..)) |
             PatKind::Struct(..) => {
                 match dm.get(&p.id).map(|d| d.full_def()) {
                     Some(Def::Variant(id)) |
index 9934259c5d19106466f809ae053cdb96961c0549..448139c37e64662f0cf69c556a598601a86b1db3 100644 (file)
@@ -272,7 +272,11 @@ pub fn fn_block_to_string(p: &hir::FnDecl) -> String {
 }
 
 pub fn path_to_string(p: &hir::Path) -> String {
-    to_string(|s| s.print_path(p, false, 0))
+    to_string(|s| s.print_path(p, false))
+}
+
+pub fn qpath_to_string(p: &hir::QPath) -> String {
+    to_string(|s| s.print_qpath(p, false))
 }
 
 pub fn name_to_string(name: ast::Name) -> String {
@@ -528,11 +532,8 @@ pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> {
                 };
                 self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &generics)?;
             }
-            hir::TyPath(None, ref path) => {
-                self.print_path(path, false, 0)?;
-            }
-            hir::TyPath(Some(ref qself), ref path) => {
-                self.print_qpath(path, qself, false)?
+            hir::TyPath(ref qpath) => {
+                self.print_qpath(qpath, false)?
             }
             hir::TyObjectSum(ref ty, ref bounds) => {
                 self.print_type(&ty)?;
@@ -845,7 +846,7 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
     }
 
     fn print_trait_ref(&mut self, t: &hir::TraitRef) -> io::Result<()> {
-        self.print_path(&t.path, false, 0)
+        self.print_path(&t.path, false)
     }
 
     fn print_formal_lifetime_list(&mut self, lifetimes: &[hir::LifetimeDef]) -> io::Result<()> {
@@ -1237,11 +1238,11 @@ fn print_expr_repeat(&mut self, element: &hir::Expr, count: &hir::Expr) -> io::R
     }
 
     fn print_expr_struct(&mut self,
-                         path: &hir::Path,
+                         qpath: &hir::QPath,
                          fields: &[hir::Field],
                          wth: &Option<P<hir::Expr>>)
                          -> io::Result<()> {
-        self.print_path(path, true, 0)?;
+        self.print_qpath(qpath, true)?;
         word(&mut self.s, "{")?;
         self.commasep_cmnt(Consistent,
                            &fields[..],
@@ -1345,8 +1346,8 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
             hir::ExprRepeat(ref element, ref count) => {
                 self.print_expr_repeat(&element, &count)?;
             }
-            hir::ExprStruct(ref path, ref fields, ref wth) => {
-                self.print_expr_struct(path, &fields[..], wth)?;
+            hir::ExprStruct(ref qpath, ref fields, ref wth) => {
+                self.print_expr_struct(qpath, &fields[..], wth)?;
             }
             hir::ExprTup(ref exprs) => {
                 self.print_expr_tup(exprs)?;
@@ -1465,11 +1466,8 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
                 self.print_expr(&index)?;
                 word(&mut self.s, "]")?;
             }
-            hir::ExprPath(None, ref path) => {
-                self.print_path(path, true, 0)?
-            }
-            hir::ExprPath(Some(ref qself), ref path) => {
-                self.print_qpath(path, qself, true)?
+            hir::ExprPath(ref qpath) => {
+                self.print_qpath(qpath, true)?
             }
             hir::ExprBreak(opt_name, ref opt_expr) => {
                 word(&mut self.s, "break")?;
@@ -1622,13 +1620,12 @@ pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) -> io::Resu
 
     fn print_path(&mut self,
                   path: &hir::Path,
-                  colons_before_params: bool,
-                  depth: usize)
+                  colons_before_params: bool)
                   -> io::Result<()> {
         self.maybe_print_comment(path.span.lo)?;
 
         let mut first = !path.global;
-        for segment in &path.segments[..path.segments.len() - depth] {
+        for segment in &path.segments {
             if first {
                 first = false
             } else {
@@ -1644,23 +1641,45 @@ fn print_path(&mut self,
     }
 
     fn print_qpath(&mut self,
-                   path: &hir::Path,
-                   qself: &hir::QSelf,
+                   qpath: &hir::QPath,
                    colons_before_params: bool)
                    -> io::Result<()> {
-        word(&mut self.s, "<")?;
-        self.print_type(&qself.ty)?;
-        if qself.position > 0 {
-            space(&mut self.s)?;
-            self.word_space("as")?;
-            let depth = path.segments.len() - qself.position;
-            self.print_path(&path, false, depth)?;
+        match *qpath {
+            hir::QPath::Resolved(None, ref path) => {
+                self.print_path(path, colons_before_params)
+            }
+            hir::QPath::Resolved(Some(ref qself), ref path) => {
+                word(&mut self.s, "<")?;
+                self.print_type(qself)?;
+                space(&mut self.s)?;
+                self.word_space("as")?;
+
+                let mut first = !path.global;
+                for segment in &path.segments[..path.segments.len() - 1] {
+                    if first {
+                        first = false
+                    } else {
+                        word(&mut self.s, "::")?
+                    }
+                    self.print_name(segment.name)?;
+                    self.print_path_parameters(&segment.parameters, colons_before_params)?;
+                }
+
+                word(&mut self.s, ">")?;
+                word(&mut self.s, "::")?;
+                let item_segment = path.segments.last().unwrap();
+                self.print_name(item_segment.name)?;
+                self.print_path_parameters(&item_segment.parameters, colons_before_params)
+            }
+            hir::QPath::TypeRelative(ref qself, ref item_segment) => {
+                word(&mut self.s, "<")?;
+                self.print_type(qself)?;
+                word(&mut self.s, ">")?;
+                word(&mut self.s, "::")?;
+                self.print_name(item_segment.name)?;
+                self.print_path_parameters(&item_segment.parameters, colons_before_params)
+            }
         }
-        word(&mut self.s, ">")?;
-        word(&mut self.s, "::")?;
-        let item_segment = path.segments.last().unwrap();
-        self.print_name(item_segment.name)?;
-        self.print_path_parameters(&item_segment.parameters, colons_before_params)
     }
 
     fn print_path_parameters(&mut self,
@@ -1668,7 +1687,15 @@ fn print_path_parameters(&mut self,
                              colons_before_params: bool)
                              -> io::Result<()> {
         if parameters.is_empty() {
-            return Ok(());
+            let infer_types = match *parameters {
+                hir::AngleBracketedParameters(ref data) => data.infer_types,
+                hir::ParenthesizedParameters(_) => false
+            };
+
+            // FIXME(eddyb) See the comment below about infer_types.
+            if !(infer_types && false) {
+                return Ok(());
+            }
         }
 
         if colons_before_params {
@@ -1760,8 +1787,8 @@ pub fn print_pat(&mut self, pat: &hir::Pat) -> io::Result<()> {
                     self.print_pat(&p)?;
                 }
             }
-            PatKind::TupleStruct(ref path, ref elts, ddpos) => {
-                self.print_path(path, true, 0)?;
+            PatKind::TupleStruct(ref qpath, ref elts, ddpos) => {
+                self.print_qpath(qpath, true)?;
                 self.popen()?;
                 if let Some(ddpos) = ddpos {
                     self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?;
@@ -1778,14 +1805,11 @@ pub fn print_pat(&mut self, pat: &hir::Pat) -> io::Result<()> {
                 }
                 self.pclose()?;
             }
-            PatKind::Path(None, ref path) => {
-                self.print_path(path, true, 0)?;
-            }
-            PatKind::Path(Some(ref qself), ref path) => {
-                self.print_qpath(path, qself, false)?;
+            PatKind::Path(ref qpath) => {
+                self.print_qpath(qpath, true)?;
             }
-            PatKind::Struct(ref path, ref fields, etc) => {
-                self.print_path(path, true, 0)?;
+            PatKind::Struct(ref qpath, ref fields, etc) => {
+                self.print_qpath(qpath, true)?;
                 self.nbsp()?;
                 self.word_space("{")?;
                 self.commasep_cmnt(Consistent,
@@ -2118,7 +2142,7 @@ pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) -> io::Res
                     }
                 }
                 &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ref path, ref ty, ..}) => {
-                    self.print_path(path, false, 0)?;
+                    self.print_path(path, false)?;
                     space(&mut self.s)?;
                     self.word_space("=")?;
                     self.print_type(&ty)?;
@@ -2132,7 +2156,7 @@ pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) -> io::Res
     pub fn print_view_path(&mut self, vp: &hir::ViewPath) -> io::Result<()> {
         match vp.node {
             hir::ViewPathSimple(name, ref path) => {
-                self.print_path(path, false, 0)?;
+                self.print_path(path, false)?;
 
                 if path.segments.last().unwrap().name != name {
                     space(&mut self.s)?;
@@ -2144,7 +2168,7 @@ pub fn print_view_path(&mut self, vp: &hir::ViewPath) -> io::Result<()> {
             }
 
             hir::ViewPathGlob(ref path) => {
-                self.print_path(path, false, 0)?;
+                self.print_path(path, false)?;
                 word(&mut self.s, "::*")
             }
 
@@ -2152,7 +2176,7 @@ pub fn print_view_path(&mut self, vp: &hir::ViewPath) -> io::Result<()> {
                 if path.segments.is_empty() {
                     word(&mut self.s, "{")?;
                 } else {
-                    self.print_path(path, false, 0)?;
+                    self.print_path(path, false)?;
                     word(&mut self.s, "::{")?;
                 }
                 self.commasep(Inconsistent, &segments[..], |s, w| s.print_name(w.node.name))?;
index b9b974733409fd67df8389dbe6a2f05a36a2a3ed..406d345992a20fa4e0366423f6fc937158010907 100644 (file)
@@ -1440,7 +1440,7 @@ fn rebuild_arg_ty_or_output(&self,
                     }
                     ty_queue.push(&mut_ty.ty);
                 }
-                hir::TyPath(ref maybe_qself, ref path) => {
+                hir::TyPath(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
                     match self.tcx.expect_def(cur_ty.id) {
                         Def::Enum(did) | Def::TyAlias(did) |
                         Def::Struct(did) | Def::Union(did) => {
@@ -1476,15 +1476,12 @@ fn rebuild_arg_ty_or_output(&self,
                             };
                             let new_path = self.rebuild_path(rebuild_info, lifetime);
                             let qself = maybe_qself.as_ref().map(|qself| {
-                                hir::QSelf {
-                                    ty: self.rebuild_arg_ty_or_output(&qself.ty, lifetime,
-                                                                      anon_nums, region_names),
-                                    position: qself.position
-                                }
+                                self.rebuild_arg_ty_or_output(qself, lifetime,
+                                                              anon_nums, region_names)
                             });
                             let to = hir::Ty {
                                 id: cur_ty.id,
-                                node: hir::TyPath(qself, new_path),
+                                node: hir::TyPath(hir::QPath::Resolved(qself, P(new_path))),
                                 span: cur_ty.span
                             };
                             new_ty = self.rebuild_ty(new_ty, P(to));
index 86422835c8cbd0b8d5f1583827eec4503874b17a..5b0f241f8a878e606cfe0146f133e5d94433879f 100644 (file)
  * Almost certainly this could (and should) be refactored out of existence.
  */
 
+use hir;
 use hir::def::Def;
 use ty::{Ty, TyCtxt};
 
 use syntax_pos::Span;
-use hir as ast;
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
-    pub fn prohibit_type_params(self, segments: &[ast::PathSegment]) {
+    pub fn prohibit_type_params(self, segments: &[hir::PathSegment]) {
         for segment in segments {
             for typ in segment.parameters.types() {
                 struct_span_err!(self.sess, typ.span, E0109,
@@ -53,24 +53,24 @@ pub fn prohibit_projection(self, span: Span)
     }
 
     pub fn prim_ty_to_ty(self,
-                         segments: &[ast::PathSegment],
-                         nty: ast::PrimTy)
+                         segments: &[hir::PathSegment],
+                         nty: hir::PrimTy)
                          -> Ty<'tcx> {
         self.prohibit_type_params(segments);
         match nty {
-            ast::TyBool => self.types.bool,
-            ast::TyChar => self.types.char,
-            ast::TyInt(it) => self.mk_mach_int(it),
-            ast::TyUint(uit) => self.mk_mach_uint(uit),
-            ast::TyFloat(ft) => self.mk_mach_float(ft),
-            ast::TyStr => self.mk_str()
+            hir::TyBool => self.types.bool,
+            hir::TyChar => self.types.char,
+            hir::TyInt(it) => self.mk_mach_int(it),
+            hir::TyUint(uit) => self.mk_mach_uint(uit),
+            hir::TyFloat(ft) => self.mk_mach_float(ft),
+            hir::TyStr => self.mk_str()
         }
     }
 
     /// If a type in the AST is a primitive type, return the ty::Ty corresponding
     /// to it.
-    pub fn ast_ty_to_prim_ty(self, ast_ty: &ast::Ty) -> Option<Ty<'tcx>> {
-        if let ast::TyPath(None, ref path) = ast_ty.node {
+    pub fn ast_ty_to_prim_ty(self, ast_ty: &hir::Ty) -> Option<Ty<'tcx>> {
+        if let hir::TyPath(hir::QPath::Resolved(None, ref path)) = ast_ty.node {
             if let Def::PrimTy(nty) = self.expect_def(ast_ty.id) {
                 Some(self.prim_ty_to_ty(&path.segments, nty))
             } else {
index f47eab013c2b216a4789e40e54d1031c10132340..efbec7bf13b9ea03a75d57dce04b0720a7ec80cf 100644 (file)
@@ -240,6 +240,9 @@ fn visit_variant_data(&mut self, def: &hir::VariantData, _: ast::Name,
 
     fn visit_expr(&mut self, expr: &hir::Expr) {
         match expr.node {
+            hir::ExprPath(hir::QPath::TypeRelative(..)) => {
+                self.lookup_and_handle_definition(expr.id);
+            }
             hir::ExprMethodCall(..) => {
                 self.lookup_and_handle_method(expr.id);
             }
index 25fe407271bc02c08e0ee9323faee8cfcc61a6f6..2892f249c5efbd7c0c123edef4005ad2589dfc1d 100644 (file)
@@ -186,7 +186,7 @@ fn visit_expr(&mut self, expr: &hir::Expr) {
             hir::ExprInlineAsm(..) => {
                 self.require_unsafe(expr.span, "use of inline assembly");
             }
-            hir::ExprPath(..) => {
+            hir::ExprPath(hir::QPath::Resolved(..)) => {
                 if let Def::Static(def_id, mutbl) = self.tcx.expect_def(expr.id) {
                     if mutbl {
                         self.require_unsafe(expr.span, "use of mutable static");
index 594ed408d8cd48efed2a73c9c87873d96f384e4c..6c952825554de1157b5ade69b1aad2cdf1395947 100644 (file)
@@ -374,7 +374,7 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) {
         self.walk_adjustment(expr);
 
         match expr.node {
-            hir::ExprPath(..) => { }
+            hir::ExprPath(_) => { }
 
             hir::ExprType(ref subexpr, _) => {
                 self.walk_expr(&subexpr)
index 80cf64865abea7043ded3f20e2c5575c52a85d49..c610c6f75b0caab0b85af0b8097d8d9c54e8edae 100644 (file)
@@ -160,23 +160,27 @@ fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
 
 impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for ExprVisitor<'a, 'gcx, 'tcx> {
     fn visit_expr(&mut self, expr: &hir::Expr) {
-        if let hir::ExprPath(..) = expr.node {
-            match self.infcx.tcx.expect_def(expr.id) {
-                Def::Fn(did) if self.def_id_is_transmute(did) => {
-                    let typ = self.infcx.tcx.tables().node_id_to_type(expr.id);
-                    match typ.sty {
-                        ty::TyFnDef(.., ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
-                            let from = bare_fn_ty.sig.0.inputs[0];
-                            let to = bare_fn_ty.sig.0.output;
-                            self.check_transmute(expr.span, from, to, expr.id);
-                        }
-                        _ => {
-                            span_bug!(expr.span, "transmute wasn't a bare fn?!");
-                        }
+        let def = match expr.node {
+            hir::ExprPath(_) => {
+                self.infcx.tcx.expect_def(expr.id)
+            }
+            _ => Def::Err
+        };
+        match def {
+            Def::Fn(did) if self.def_id_is_transmute(did) => {
+                let typ = self.infcx.tcx.tables().node_id_to_type(expr.id);
+                match typ.sty {
+                    ty::TyFnDef(.., ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
+                        let from = bare_fn_ty.sig.0.inputs[0];
+                        let to = bare_fn_ty.sig.0.output;
+                        self.check_transmute(expr.span, from, to, expr.id);
+                    }
+                    _ => {
+                        span_bug!(expr.span, "transmute wasn't a bare fn?!");
                     }
                 }
-                _ => {}
             }
+            _ => {}
         }
 
         intravisit::walk_expr(self, expr);
index 4b1787ba593cbcae173ec7b63239e4293e3c2983..eefed0a5a74ffec6868fd38204f737cfde833b38 100644 (file)
@@ -443,7 +443,7 @@ fn visit_arm(ir: &mut IrMaps, arm: &hir::Arm) {
 fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
     match expr.node {
       // live nodes required for uses or definitions of variables:
-      hir::ExprPath(..) => {
+      hir::ExprPath(_) => {
         let def = ir.tcx.expect_def(expr.id);
         debug!("expr {}: path that leads to {:?}", expr.id, def);
         if let Def::Local(..) = def {
@@ -922,7 +922,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
         match expr.node {
           // Interesting cases with control flow or which gen/kill
 
-          hir::ExprPath(..) => {
+          hir::ExprPath(hir::QPath::Resolved(..)) => {
               self.access_path(expr, succ, ACC_READ | ACC_USE)
           }
 
@@ -1171,7 +1171,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
             self.propagate_through_exprs(inputs, succ)
           }
 
-          hir::ExprLit(..) => {
+          hir::ExprLit(..) | hir::ExprPath(hir::QPath::TypeRelative(..)) => {
             succ
           }
 
@@ -1235,7 +1235,7 @@ fn propagate_through_lvalue_components(&mut self,
         // just ignore such cases and treat them as reads.
 
         match expr.node {
-            hir::ExprPath(..) => succ,
+            hir::ExprPath(_) => succ,
             hir::ExprField(ref e, _) => self.propagate_through_expr(&e, succ),
             hir::ExprTupField(ref e, _) => self.propagate_through_expr(&e, succ),
             _ => self.propagate_through_expr(expr, succ)
@@ -1246,7 +1246,7 @@ fn propagate_through_lvalue_components(&mut self,
     fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
                     -> LiveNode {
         match expr.node {
-          hir::ExprPath(..) => {
+          hir::ExprPath(hir::QPath::Resolved(..)) => {
               self.access_path(expr, succ, acc)
           }
 
@@ -1431,8 +1431,8 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
       hir::ExprBreak(..) | hir::ExprAgain(..) | hir::ExprLit(_) |
       hir::ExprBlock(..) | hir::ExprAddrOf(..) |
       hir::ExprStruct(..) | hir::ExprRepeat(..) |
-      hir::ExprClosure(..) | hir::ExprPath(..) | hir::ExprBox(..) |
-      hir::ExprType(..) => {
+      hir::ExprClosure(..) | hir::ExprPath(_) |
+      hir::ExprBox(..) | hir::ExprType(..) => {
         intravisit::walk_expr(this, expr);
       }
     }
@@ -1482,7 +1482,7 @@ fn check_ret(&self,
 
     fn check_lvalue(&mut self, expr: &Expr) {
         match expr.node {
-            hir::ExprPath(..) => {
+            hir::ExprPath(hir::QPath::Resolved(..)) => {
                 if let Def::Local(def_id) = self.ir.tcx.expect_def(expr.id) {
                     // Assignment to an immutable variable or argument: only legal
                     // if there is no later assignment. If this local is actually
index fedf8c2ec7472cd57ef6823627c509e52c0ad8a0..1ca078dcd2e4976fb7417f9f8c581413976733c9 100644 (file)
@@ -488,7 +488,7 @@ pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult<cmt<'tcx>> {
             }
           }
 
-          hir::ExprPath(..) => {
+          hir::ExprPath(_) => {
             self.cat_def(expr.id, expr.span, expr_ty, self.tcx().expect_def(expr.id))
           }
 
@@ -1157,7 +1157,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McResul
             }
           }
 
-          PatKind::Path(..) | PatKind::Binding(.., None) |
+          PatKind::Path(_) | PatKind::Binding(.., None) |
           PatKind::Lit(..) | PatKind::Range(..) | PatKind::Wild => {
             // always ok
           }
index 35e0e494771ba131a46b6a488beb2b7a5147e823..0329b4c4a3019bbb77fa6a65e132dfe9d6809757 100644 (file)
@@ -91,7 +91,7 @@ struct ReachableContext<'a, 'tcx: 'a> {
 impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &hir::Expr) {
         match expr.node {
-            hir::ExprPath(..) => {
+            hir::ExprPath(_) => {
                 let def = self.tcx.expect_def(expr.id);
                 let def_id = def.def_id();
                 if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
index 41da5562e23fa4f488bda5112ba63367fa810284..c65fd25950deab808fe80638c0d01258a81c6919 100644 (file)
@@ -244,7 +244,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
                     intravisit::walk_ty(this, ty);
                 });
             }
-            hir::TyPath(None, ref path) => {
+            hir::TyPath(hir::QPath::Resolved(None, ref path)) => {
                 // if this path references a trait, then this will resolve to
                 // a trait ref, which introduces a binding scope.
                 match self.def_map.get(&ty.id).map(|d| (d.base_def, d.depth)) {
@@ -944,13 +944,14 @@ struct ConstrainedCollector {
     impl<'v> Visitor<'v> for ConstrainedCollector {
         fn visit_ty(&mut self, ty: &'v hir::Ty) {
             match ty.node {
-                hir::TyPath(Some(_), _) => {
+                hir::TyPath(hir::QPath::Resolved(Some(_), _)) |
+                hir::TyPath(hir::QPath::TypeRelative(..)) => {
                     // ignore lifetimes appearing in associated type
                     // projections, as they are not *constrained*
                     // (defined above)
                 }
 
-                hir::TyPath(None, ref path) => {
+                hir::TyPath(hir::QPath::Resolved(None, ref path)) => {
                     // consider only the lifetimes on the final
                     // segment; I am not sure it's even currently
                     // valid to have them elsewhere, but even if it
index 86a89eff3a476a9cd5c54a8432250738ba642a2d..a044ffd9a7f85e27b06147f4f7e96e6928f5f131 100644 (file)
@@ -486,6 +486,12 @@ fn visit_pat(&mut self, pat: &'tcx hir::Pat) {
         intravisit::walk_pat(self, pat)
     }
 
+    fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
+        check_ty(self.tcx, ty,
+                 &mut |id, sp, stab, depr| self.check(id, sp, stab, depr));
+        intravisit::walk_ty(self, ty)
+    }
+
     fn visit_block(&mut self, b: &'tcx hir::Block) {
         let old_skip_count = self.in_skip_block;
         match b.rules {
@@ -553,6 +559,10 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr,
             let method_call = ty::MethodCall::expr(e.id);
             tcx.tables().method_map[&method_call].def_id
         }
+        hir::ExprPath(hir::QPath::TypeRelative(..)) => {
+            span = e.span;
+            tcx.expect_def(e.id).def_id()
+        }
         hir::ExprField(ref base_e, ref field) => {
             span = field.span;
             match tcx.tables().expr_ty_adjusted(base_e).sty {
@@ -633,6 +643,11 @@ pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat,
     debug!("check_pat(pat = {:?})", pat);
     if is_internal(tcx, pat.span) { return; }
 
+    if let PatKind::Path(hir::QPath::TypeRelative(..)) = pat.node {
+        let def_id = tcx.expect_def(pat.id).def_id();
+        maybe_do_stability_check(tcx, def_id, pat.span, cb)
+    }
+
     let v = match tcx.tables().pat_ty_opt(pat).map(|ty| &ty.sty) {
         Some(&ty::TyAdt(adt, _)) if !adt.is_enum() => adt.struct_variant(),
         _ => return,
@@ -656,6 +671,19 @@ pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat,
     }
 }
 
+pub fn check_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: &hir::Ty,
+                          cb: &mut FnMut(DefId, Span,
+                                         &Option<&Stability>,
+                                         &Option<DeprecationEntry>)) {
+    debug!("check_ty(ty = {:?})", ty);
+    if is_internal(tcx, ty.span) { return; }
+
+    if let hir::TyPath(hir::QPath::TypeRelative(..)) = ty.node {
+        let def_id = tcx.expect_def(ty.id).def_id();
+        maybe_do_stability_check(tcx, def_id, ty.span, cb);
+    }
+}
+
 fn maybe_do_stability_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                       id: DefId, span: Span,
                                       cb: &mut FnMut(DefId, Span,
index 7982c641ede5cbefbbef80337319e3976f478b8a..3d02ff4651f885deb9c7c90fd592cf4583d45fe9 100644 (file)
@@ -2059,11 +2059,8 @@ pub fn local_var_name_str(self, id: NodeId) -> InternedString {
 
     pub fn expr_is_lval(self, expr: &hir::Expr) -> bool {
          match expr.node {
-            hir::ExprPath(..) => {
-                // This function can be used during type checking when not all paths are
-                // fully resolved. Partially resolved paths in expressions can only legally
-                // refer to associated items which are always rvalues.
-                match self.expect_resolution(expr.id).base_def {
+            hir::ExprPath(hir::QPath::Resolved(..)) => {
+                match self.expect_def(expr.id) {
                     Def::Local(..) | Def::Upvar(..) | Def::Static(..) | Def::Err => true,
                     _ => false,
                 }
@@ -2080,6 +2077,10 @@ pub fn expr_is_lval(self, expr: &hir::Expr) -> bool {
                 true
             }
 
+            // Partially qualified paths in expressions can only legally
+            // refer to associated items which are always rvalues.
+            hir::ExprPath(hir::QPath::TypeRelative(..)) |
+
             hir::ExprCall(..) |
             hir::ExprMethodCall(..) |
             hir::ExprStruct(..) |
index c48811cb295bd60d681e82c29138a42b04764938..4731cea02065bf48992623325d8c1c74ea0eb94a 100644 (file)
@@ -324,6 +324,7 @@ fn apply_constructor<'a, 'tcx>(
 
                 ty::TyAdt(adt, _) => {
                     let v = ctor.variant_for_adt(adt);
+                    let qpath = hir::QPath::Resolved(None, P(def_to_path(cx.tcx, v.did)));
                     match v.ctor_kind {
                         CtorKind::Fictive => {
                             let field_pats: hir::HirVec<_> = v.fields.iter()
@@ -338,16 +339,12 @@ fn apply_constructor<'a, 'tcx>(
                                     }
                                 }).collect();
                             let has_more_fields = field_pats.len() < arity;
-                            PatKind::Struct(
-                                def_to_path(cx.tcx, v.did), field_pats, has_more_fields)
+                            PatKind::Struct(qpath, field_pats, has_more_fields)
                         }
                         CtorKind::Fn => {
-                            PatKind::TupleStruct(
-                                def_to_path(cx.tcx, v.did), pats.collect(), None)
-                        }
-                        CtorKind::Const => {
-                            PatKind::Path(None, def_to_path(cx.tcx, v.did))
+                            PatKind::TupleStruct(qpath, pats.collect(), None)
                         }
+                        CtorKind::Const => PatKind::Path(qpath)
                     }
                 }
 
index b594fe9853a43ac35a2b5bf8ca247300fd18fdde..e8c05ec1a35ae11ac3372297758256180dd37319 100644 (file)
@@ -286,9 +286,11 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             if let Vacant(entry) = tcx.def_map.borrow_mut().entry(expr.id) {
                entry.insert(PathResolution::new(def));
             }
-            let path = match def {
+            let qpath = match def {
                 Def::StructCtor(def_id, CtorKind::Fn) |
-                Def::VariantCtor(def_id, CtorKind::Fn) => def_to_path(tcx, def_id),
+                Def::VariantCtor(def_id, CtorKind::Fn) => {
+                    hir::QPath::Resolved(None, P(def_to_path(tcx, def_id)))
+                }
                 Def::Fn(..) | Def::Method(..) => return Ok(P(hir::Pat {
                     id: expr.id,
                     node: PatKind::Lit(P(expr.clone())),
@@ -299,10 +301,10 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             let pats = args.iter()
                            .map(|expr| const_expr_to_pat(tcx, &*expr, pat_id, span))
                            .collect::<Result<_, _>>()?;
-            PatKind::TupleStruct(path, pats, None)
+            PatKind::TupleStruct(qpath, pats, None)
         }
 
-        hir::ExprStruct(ref path, ref fields, None) => {
+        hir::ExprStruct(ref qpath, ref fields, None) => {
             let field_pats =
                 fields.iter()
                       .map(|field| Ok(codemap::Spanned {
@@ -314,7 +316,7 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           },
                       }))
                       .collect::<Result<_, _>>()?;
-            PatKind::Struct((**path).clone(), field_pats, false)
+            PatKind::Struct(qpath.clone(), field_pats, false)
         }
 
         hir::ExprArray(ref exprs) => {
@@ -324,10 +326,17 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             PatKind::Slice(pats, None, hir::HirVec::new())
         }
 
-        hir::ExprPath(_, ref path) => {
+        hir::ExprPath(_) => {
             match tcx.expect_def(expr.id) {
                 Def::StructCtor(_, CtorKind::Const) |
-                Def::VariantCtor(_, CtorKind::Const) => PatKind::Path(None, path.clone()),
+                Def::VariantCtor(_, CtorKind::Const) => {
+                    match expr.node {
+                        hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
+                            PatKind::Path(hir::QPath::Resolved(None, path.clone()))
+                        }
+                        _ => bug!()
+                    }
+                }
                 Def::Const(def_id) | Def::AssociatedConst(def_id) => {
                     let substs = Some(tcx.tables().node_id_item_substs(expr.id)
                         .unwrap_or_else(|| tcx.intern_substs(&[])));
@@ -788,14 +797,14 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             Err(kind) => return Err(ConstEvalErr { span: e.span, kind: kind }),
         }
       }
-      hir::ExprPath(..) => {
+      hir::ExprPath(_) => {
           // This function can be used before type checking when not all paths are fully resolved.
           // FIXME: There's probably a better way to make sure we don't panic here.
-          let resolution = tcx.expect_resolution(e.id);
-          if resolution.depth != 0 {
-              signal!(e, UnresolvedPath);
-          }
-          match resolution.base_def {
+          let def = match tcx.expect_def_or_none(e.id) {
+              Some(def) => def,
+              None => signal!(e, UnresolvedPath)
+          };
+          match def {
               Def::Const(def_id) |
               Def::AssociatedConst(def_id) => {
                   let substs = if let ExprTypeChecked = ty_hint {
@@ -1358,17 +1367,12 @@ pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             let mut diag = report_const_eval_err(
                 tcx, &err, count_expr.span, reason);
 
-            match count_expr.node {
-                hir::ExprPath(None, hir::Path {
-                    global: false,
-                    ref segments,
-                    ..
-                }) if segments.len() == 1 => {
+            if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = count_expr.node {
+                if !path.global && path.segments.len() == 1 {
                     if let Some(Def::Local(..)) = tcx.expect_def_or_none(count_expr.id) {
-                        diag.note(&format!("`{}` is a variable", segments[0].name));
+                        diag.note(&format!("`{}` is a variable", path.segments[0].name));
                     }
                 }
-                _ => {}
             }
 
             diag.emit();
index fd0856393fc1b3b9c8b39bbe0d9a5e5cd73f3568..ec405311012592231027300d7cb2f21bffd6e5f6 100644 (file)
@@ -185,6 +185,7 @@ enum SawAbiComponent<'a> {
     SawImplItem(SawTraitOrImplItemComponent),
     SawStructField,
     SawVariant,
+    SawQPath,
     SawPath(bool),
     SawPathSegment,
     SawPathParameters,
@@ -259,7 +260,7 @@ enum SawExprComponent<'a> {
     SawExprAssign,
     SawExprAssignOp(hir::BinOp_),
     SawExprIndex,
-    SawExprPath(Option<usize>),
+    SawExprPath,
     SawExprAddrOf(hir::Mutability),
     SawExprRet,
     SawExprInlineAsm(&'a hir::InlineAsm),
@@ -333,7 +334,7 @@ fn saw_expr<'a>(node: &'a Expr_,
         ExprField(_, name)       => (SawExprField(name.node.as_str()), false),
         ExprTupField(_, id)      => (SawExprTupField(id.node), false),
         ExprIndex(..)            => (SawExprIndex, true),
-        ExprPath(ref qself, _)   => (SawExprPath(qself.as_ref().map(|q| q.position)), false),
+        ExprPath(_)              => (SawExprPath, false),
         ExprAddrOf(m, _)         => (SawExprAddrOf(m), false),
         ExprBreak(id, _)         => (SawExprBreak(id.map(|id| id.node.as_str())), false),
         ExprAgain(id)            => (SawExprAgain(id.map(|id| id.node.as_str())), false),
@@ -411,7 +412,7 @@ fn saw_pat(node: &PatKind) -> SawPatComponent {
         PatKind::Binding(bindingmode, ..) => SawPatBinding(bindingmode),
         PatKind::Struct(..) => SawPatStruct,
         PatKind::TupleStruct(..) => SawPatTupleStruct,
-        PatKind::Path(..) => SawPatPath,
+        PatKind::Path(_) => SawPatPath,
         PatKind::Tuple(..) => SawPatTuple,
         PatKind::Box(..) => SawPatBox,
         PatKind::Ref(_, mutability) => SawPatRef(mutability),
@@ -447,7 +448,7 @@ fn saw_ty(node: &Ty_) -> SawTyComponent {
       TyBareFn(ref barefnty) => SawTyBareFn(barefnty.unsafety, barefnty.abi),
       TyNever => SawTyNever,
       TyTup(..) => SawTyTup,
-      TyPath(..) => SawTyPath,
+      TyPath(_) => SawTyPath,
       TyObjectSum(..) => SawTyObjectSum,
       TyPolyTraitRef(..) => SawTyPolyTraitRef,
       TyImplTrait(..) => SawTyImplTrait,
@@ -655,6 +656,13 @@ fn visit_struct_field(&mut self, s: &'tcx StructField) {
         visit::walk_struct_field(self, s)
     }
 
+    fn visit_qpath(&mut self, qpath: &'tcx QPath, id: NodeId, span: Span) {
+        debug!("visit_qpath: st={:?}", self.st);
+        SawQPath.hash(self.st);
+        self.hash_discriminant(qpath);
+        visit::walk_qpath(self, qpath, id, span)
+    }
+
     fn visit_path(&mut self, path: &'tcx Path, _: ast::NodeId) {
         debug!("visit_path: st={:?}", self.st);
         SawPath(path.global).hash(self.st);
index 4440cb41dc5f20051a8a4c883d4d41a1185f6bfc..25ea3d65993a49c3d35e18010cbedb3e9899af3a 100644 (file)
@@ -376,7 +376,7 @@ fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) {
 
     fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
         // Lint for constants that look like binding identifiers (#7526)
-        if let PatKind::Path(None, ref path) = p.node {
+        if let PatKind::Path(hir::QPath::Resolved(None, ref path)) = p.node {
             if !path.global && path.segments.len() == 1 && path.segments[0].parameters.is_empty() {
                 if let Def::Const(..) = cx.tcx.expect_def(p.id) {
                     NonUpperCaseGlobals::check_upper_case(cx,
index 0b2ae58852300806d9ec81392a42a0d183c27d53..7be591293c91bb2583c2577e9e914125d722ced4 100644 (file)
@@ -718,6 +718,12 @@ fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
                              &mut |id, sp, stab, depr| self.lint(cx, id, sp, &stab, &depr));
     }
 
+    fn check_ty(&mut self, cx: &LateContext, ty: &hir::Ty) {
+        stability::check_ty(cx.tcx, ty,
+                            &mut |id, sp, stab, depr|
+                               self.lint(cx, id, sp, &stab, &depr));
+    }
+
     fn check_impl_item(&mut self, _: &LateContext, item: &hir::ImplItem) {
         self.push_item(item.id);
     }
@@ -1204,7 +1210,7 @@ fn get_transmute_from_to<'a, 'tcx>
              expr: &hir::Expr)
              -> Option<(&'tcx ty::TypeVariants<'tcx>, &'tcx ty::TypeVariants<'tcx>)> {
             match expr.node {
-                hir::ExprPath(..) => (),
+                hir::ExprPath(_) => (),
                 _ => return None,
             }
             if let Def::Fn(did) = cx.tcx.expect_def(expr.id) {
index fa452017f0cf1d7fecbdb7a1ddbdc6fcf4ae3e97..d0ad682fb58a60a7547a9e918a6eda22b4cf7f0f 100644 (file)
@@ -218,7 +218,7 @@ fn get_lints(&self) -> LintArray {
 impl LateLintPass for PathStatements {
     fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
         if let hir::StmtSemi(ref expr, _) = s.node {
-            if let hir::ExprPath(..) = expr.node {
+            if let hir::ExprPath(_) = expr.node {
                 cx.span_lint(PATH_STATEMENTS, s.span, "path statement with no effect");
             }
         }
index 6fa2672593587b2f0885fa08f4e1cc73e67ff58b..0c796ad42bbc2c87bd7ef8d0ad264c6d8c388089 100644 (file)
@@ -265,7 +265,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                     args: vec![fun.to_ref(), tupled_args.to_ref()]
                 }
             } else {
-                let adt_data = if let hir::ExprPath(..) = fun.node {
+                let adt_data = if let hir::ExprPath(hir::QPath::Resolved(..)) = fun.node {
                     // Tuple-like ADTs are represented as ExprCall. We convert them here.
                     expr_ty.ty_adt_def().and_then(|adt_def|{
                         match cx.tcx.expect_def(fun.id) {
@@ -531,7 +531,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             }
         }
 
-        hir::ExprPath(..) => {
+        hir::ExprPath(_) => {
             convert_path_expr(cx, expr)
         }
 
index 4d8520ed0440a1259fc0124ad9160bf27c2da03b..ff46273a997c855f9b62cf9e27c799bbf69b6ae2 100644 (file)
@@ -487,7 +487,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
                 _ => {}
             }
         }
-        hir::ExprPath(..) => {
+        hir::ExprPath(_) => {
             match v.tcx.expect_def(e.id) {
                 Def::VariantCtor(_, CtorKind::Const) => {
                     // Size is determined by the whole enum, may be non-zero.
index dafb7bc6e60996d67482cb982f4e83b19071e9cf..9028821ef116d760719f7a673c75bf30297c50f5 100644 (file)
@@ -218,6 +218,10 @@ fn visit_lifetime_def(&mut self, lifetime: &'v hir::LifetimeDef) {
         self.record("LifetimeDef", Id::None, lifetime);
         hir_visit::walk_lifetime_def(self, lifetime)
     }
+    fn visit_qpath(&mut self, qpath: &'v hir::QPath, id: NodeId, span: Span) {
+        self.record("QPath", Id::None, qpath);
+        hir_visit::walk_qpath(self, qpath, id, span)
+    }
     fn visit_path(&mut self, path: &'v hir::Path, _id: NodeId) {
         self.record("Path", Id::None, path);
         hir_visit::walk_path(self, path)
@@ -234,7 +238,6 @@ fn visit_path_segment(&mut self,
         self.record("PathSegment", Id::None, path_segment);
         hir_visit::walk_path_segment(self, path_span, path_segment)
     }
-
     fn visit_assoc_type_binding(&mut self, type_binding: &'v hir::TypeBinding) {
         self.record("TypeBinding", Id::Node(type_binding.id), type_binding);
         hir_visit::walk_assoc_type_binding(self, type_binding)
index 5f76f865c4acaa9f42fcf042a0ca1ee414d8dcd1..b98cf7e602b10198dbe63aa42446029c01ca2768 100644 (file)
@@ -250,7 +250,7 @@ fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
 
     fn visit_expr(&mut self, e: &'ast hir::Expr) {
         match e.node {
-            hir::ExprPath(..) => {
+            hir::ExprPath(_) => {
                 match self.def_map.get(&e.id).map(|d| d.base_def) {
                     Some(Def::Static(def_id, _)) |
                     Some(Def::AssociatedConst(def_id)) |
index b116408269e4dd10a3236b75ace6d4e961698295..55e11caac6d02e5304ae4d16c582cea6575f62d2 100644 (file)
@@ -67,7 +67,7 @@ struct ReachEverythingInTheInterfaceVisitor<'b, 'a: 'b, 'tcx: 'a> {
 
 impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
     fn ty_level(&self, ty: &hir::Ty) -> Option<AccessLevel> {
-        if let hir::TyPath(..) = ty.node {
+        if let hir::TyPath(_) = ty.node {
             match self.tcx.expect_def(ty.id) {
                 Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {
                     Some(AccessLevel::Public)
@@ -306,11 +306,11 @@ fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
 
 impl<'b, 'a, 'tcx: 'a> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
     // Make the type hidden under a type alias reachable
-    fn reach_aliased_type(&mut self, item: &'tcx hir::Item, path: &'tcx hir::Path) {
+    fn reach_aliased_type(&mut self, item: &'tcx hir::Item, segment: &'tcx hir::PathSegment) {
         if let hir::ItemTy(ref ty, ref generics) = item.node {
             // See `fn is_public_type_alias` for details
             self.visit_ty(ty);
-            let provided_params = path.segments.last().unwrap().parameters.types().len();
+            let provided_params = segment.parameters.types().len();
             for ty_param in &generics.ty_params[provided_params..] {
                 if let Some(ref default_ty) = ty_param.default {
                     self.visit_ty(default_ty);
@@ -328,7 +328,12 @@ fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) {
     }
 
     fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
-        if let hir::TyPath(_, ref path) = ty.node {
+        let path_segment = match ty.node {
+            hir::TyPath(hir::QPath::Resolved(_, ref path)) => path.segments.last(),
+            hir::TyPath(hir::QPath::TypeRelative(_, ref segment)) => Some(&**segment),
+            _ => None
+        };
+        if let Some(segment) = path_segment {
             let def = self.ev.tcx.expect_def(ty.id);
             match def {
                 Def::Struct(def_id) | Def::Union(def_id) | Def::Enum(def_id) |
@@ -344,7 +349,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
                             // Type aliases are substituted. Associated type aliases are not
                             // substituted yet, but ideally they should be.
                             if self.ev.get(item.id).is_none() {
-                                self.reach_aliased_type(item, path);
+                                self.reach_aliased_type(item, segment);
                             }
                         } else {
                             self.ev.update(item.id, Some(AccessLevel::Reachable));
@@ -461,7 +466,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
                     }
                 }
             }
-            hir::ExprPath(..) => {
+            hir::ExprPath(hir::QPath::Resolved(..)) => {
                 if let def @ Def::StructCtor(_, CtorKind::Fn) = self.tcx.expect_def(expr.id) {
                     let adt_def = self.tcx.expect_variant_def(def);
                     let private_indexes = adt_def.fields.iter().enumerate().filter(|&(_, field)| {
@@ -606,7 +611,7 @@ fn item_is_public(&self, id: &ast::NodeId, vis: &hir::Visibility) -> bool {
 
 impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
     fn visit_ty(&mut self, ty: &hir::Ty) {
-        if let hir::TyPath(..) = ty.node {
+        if let hir::TyPath(_) = ty.node {
             if self.inner.path_is_private_type(ty.id) {
                 self.contains_private = true;
                 // found what we're looking for so let's stop
@@ -844,7 +849,7 @@ fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem) {
     }
 
     fn visit_ty(&mut self, t: &'tcx hir::Ty) {
-        if let hir::TyPath(..) = t.node {
+        if let hir::TyPath(_) = t.node {
             if self.path_is_private_type(t.id) {
                 self.old_error_set.insert(t.id);
             }
@@ -906,7 +911,7 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, old_error_set: &'a NodeSet) -> Self {
 
 impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
     // Return the visibility of the type alias's least visible component type when substituted
-    fn substituted_alias_visibility(&self, item: &hir::Item, path: &hir::Path)
+    fn substituted_alias_visibility(&self, item: &hir::Item, segment: &hir::PathSegment)
                                     -> Option<ty::Visibility> {
         // Type alias is considered public if the aliased type is
         // public, even if the type alias itself is private. So, something
@@ -921,7 +926,7 @@ fn substituted_alias_visibility(&self, item: &hir::Item, path: &hir::Path)
             // type Alias<T = Private> = T;
             // pub fn f() -> Alias {...} // `Private` is implicitly used here, so it must be public
             // ```
-            let provided_params = path.segments.last().unwrap().parameters.types().len();
+            let provided_params = segment.parameters.types().len();
             for ty_param in &generics.ty_params[provided_params..] {
                 if let Some(ref default_ty) = ty_param.default {
                     check.visit_ty(default_ty);
@@ -936,7 +941,12 @@ fn substituted_alias_visibility(&self, item: &hir::Item, path: &hir::Path)
 
 impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
     fn visit_ty(&mut self, ty: &hir::Ty) {
-        if let hir::TyPath(_, ref path) = ty.node {
+        let path_segment = match ty.node {
+            hir::TyPath(hir::QPath::Resolved(_, ref path)) => path.segments.last(),
+            hir::TyPath(hir::QPath::TypeRelative(_, ref segment)) => Some(&**segment),
+            _ => None
+        };
+        if let Some(segment) = path_segment {
             match self.tcx.expect_def(ty.id) {
                 Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {
                     // Public
@@ -961,7 +971,7 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
                         }
 
                         let item = self.tcx.map.expect_item(node_id);
-                        let vis = match self.substituted_alias_visibility(item, path) {
+                        let vis = match self.substituted_alias_visibility(item, segment) {
                             Some(vis) => vis,
                             None => ty::Visibility::from_hir(&item.vis, node_id, self.tcx),
                         };
index 831426c3f06b67bada3a7fc9cae9bdd4e1dd278a..7d02678679ac6845606c4c0e21d8eb7e4f71518f 100644 (file)
@@ -952,7 +952,7 @@ fn ast_ty_to_object_trait_ref(&self,
 
         let tcx = self.tcx();
         match ty.node {
-            hir::TyPath(None, ref path) => {
+            hir::TyPath(hir::QPath::Resolved(None, ref path)) => {
                 let resolution = tcx.expect_resolution(ty.id);
                 match resolution.base_def {
                     Def::Trait(trait_def_id) if resolution.depth == 0 => {
@@ -1261,12 +1261,12 @@ fn one_bound_for_assoc_type(&self,
     // the whole path.
     // Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type
     // parameter or Self.
-    fn associated_path_def_to_ty(&self,
-                                 span: Span,
-                                 ty: Ty<'tcx>,
-                                 ty_path_def: Def,
-                                 item_segment: &hir::PathSegment)
-                                 -> (Ty<'tcx>, Def)
+    pub fn associated_path_def_to_ty(&self,
+                                     span: Span,
+                                     ty: Ty<'tcx>,
+                                     ty_path_def: Def,
+                                     item_segment: &hir::PathSegment)
+                                     -> (Ty<'tcx>, Def)
     {
         let tcx = self.tcx();
         let assoc_name = item_segment.name;
@@ -1412,54 +1412,55 @@ fn ast_ty_arg_to_ty(&self,
         }
     }
 
-    // Check the base def in a PathResolution and convert it to a Ty. If there are
-    // associated types in the PathResolution, these will need to be separately
-    // resolved.
-    fn base_def_to_ty(&self,
-                      rscope: &RegionScope,
-                      span: Span,
-                      def: Def,
-                      opt_self_ty: Option<Ty<'tcx>>,
-                      base_path_ref_id: ast::NodeId,
-                      base_segments: &[hir::PathSegment],
-                      permit_variants: bool)
-                      -> Ty<'tcx> {
+    // Check a type Def and convert it to a Ty.
+    pub fn def_to_ty(&self,
+                     rscope: &RegionScope,
+                     span: Span,
+                     def: Def,
+                     opt_self_ty: Option<Ty<'tcx>>,
+                     path_id: ast::NodeId,
+                     path_segments: &[hir::PathSegment],
+                     permit_variants: bool)
+                     -> Ty<'tcx> {
         let tcx = self.tcx();
 
-        debug!("base_def_to_ty(def={:?}, opt_self_ty={:?}, base_segments={:?})",
-               def, opt_self_ty, base_segments);
+        debug!("base_def_to_ty(def={:?}, opt_self_ty={:?}, path_segments={:?})",
+               def, opt_self_ty, path_segments);
 
         match def {
             Def::Trait(trait_def_id) => {
                 // N.B. this case overlaps somewhat with
                 // TyObjectSum, see that fn for details
 
-                tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
+                assert_eq!(opt_self_ty, None);
+                tcx.prohibit_type_params(path_segments.split_last().unwrap().1);
 
                 self.trait_path_to_object_type(rscope,
                                                span,
                                                trait_def_id,
-                                               base_path_ref_id,
-                                               base_segments.last().unwrap(),
+                                               path_id,
+                                               path_segments.last().unwrap(),
                                                span,
                                                partition_bounds(tcx, span, &[]))
             }
             Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) | Def::Union(did) => {
-                tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
-                self.ast_path_to_ty(rscope, span, did, base_segments.last().unwrap())
+                assert_eq!(opt_self_ty, None);
+                tcx.prohibit_type_params(path_segments.split_last().unwrap().1);
+                self.ast_path_to_ty(rscope, span, did, path_segments.last().unwrap())
             }
             Def::Variant(did) if permit_variants => {
                 // Convert "variant type" as if it were a real type.
                 // The resulting `Ty` is type of the variant's enum for now.
-                tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
+                assert_eq!(opt_self_ty, None);
+                tcx.prohibit_type_params(path_segments.split_last().unwrap().1);
                 self.ast_path_to_ty(rscope,
                                     span,
-                                    param_mode,
                                     tcx.parent_def_id(did).unwrap(),
-                                    base_segments.last().unwrap())
+                                    path_segments.last().unwrap())
             }
             Def::TyParam(did) => {
-                tcx.prohibit_type_params(base_segments);
+                assert_eq!(opt_self_ty, None);
+                tcx.prohibit_type_params(path_segments);
 
                 let node_id = tcx.map.as_local_node_id(did).unwrap();
                 let param = tcx.ty_param_defs.borrow().get(&node_id)
@@ -1481,7 +1482,8 @@ fn base_def_to_ty(&self,
             Def::SelfTy(_, Some(def_id)) => {
                 // Self in impl (we know the concrete type).
 
-                tcx.prohibit_type_params(base_segments);
+                assert_eq!(opt_self_ty, None);
+                tcx.prohibit_type_params(path_segments);
                 let ty = tcx.item_type(def_id);
                 if let Some(free_substs) = self.get_free_substs() {
                     ty.subst(tcx, free_substs)
@@ -1491,34 +1493,23 @@ fn base_def_to_ty(&self,
             }
             Def::SelfTy(Some(_), None) => {
                 // Self in trait.
-                tcx.prohibit_type_params(base_segments);
+                assert_eq!(opt_self_ty, None);
+                tcx.prohibit_type_params(path_segments);
                 tcx.mk_self_type()
             }
             Def::AssociatedTy(def_id) => {
-                tcx.prohibit_type_params(&base_segments[..base_segments.len()-2]);
+                tcx.prohibit_type_params(&path_segments[..path_segments.len()-2]);
                 let trait_did = tcx.parent_def_id(def_id).unwrap();
                 self.qpath_to_ty(rscope,
                                  span,
                                  opt_self_ty,
                                  trait_did,
-                                 &base_segments[base_segments.len()-2],
-                                 base_segments.last().unwrap())
-            }
-            Def::Mod(..) => {
-                // Used as sentinel by callers to indicate the `<T>::A::B::C` form.
-                // FIXME(#22519) This part of the resolution logic should be
-                // avoided entirely for that form, once we stop needed a Def
-                // for `associated_path_def_to_ty`.
-                // Fixing this will also let use resolve <Self>::Foo the same way we
-                // resolve Self::Foo, at the moment we can't resolve the former because
-                // we don't have the trait information around, which is just sad.
-
-                assert!(base_segments.is_empty());
-
-                opt_self_ty.expect("missing T in <T>::a::b::c")
+                                 &path_segments[path_segments.len()-2],
+                                 path_segments.last().unwrap())
             }
             Def::PrimTy(prim_ty) => {
-                tcx.prim_ty_to_ty(base_segments, prim_ty)
+                assert_eq!(opt_self_ty, None);
+                tcx.prim_ty_to_ty(path_segments, prim_ty)
             }
             Def::Err => {
                 self.set_tainted_by_errors();
@@ -1535,50 +1526,6 @@ fn base_def_to_ty(&self,
         }
     }
 
-    // Resolve possibly associated type path into a type and final definition.
-    // Note that both base_segments and assoc_segments may be empty, although not at same time.
-    pub fn finish_resolving_def_to_ty(&self,
-                                      rscope: &RegionScope,
-                                      span: Span,
-                                      base_def: Def,
-                                      opt_self_ty: Option<Ty<'tcx>>,
-                                      base_path_ref_id: ast::NodeId,
-                                      base_segments: &[hir::PathSegment],
-                                      assoc_segments: &[hir::PathSegment],
-                                      permit_variants: bool)
-                                      -> (Ty<'tcx>, Def) {
-        // Convert the base type.
-        debug!("finish_resolving_def_to_ty(base_def={:?}, \
-                base_segments={:?}, \
-                assoc_segments={:?})",
-               base_def,
-               base_segments,
-               assoc_segments);
-        let base_ty = self.base_def_to_ty(rscope,
-                                          span,
-                                          base_def,
-                                          opt_self_ty,
-                                          base_path_ref_id,
-                                          base_segments,
-                                          permit_variants);
-        debug!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", base_ty);
-
-        // If any associated type segments remain, attempt to resolve them.
-        let (mut ty, mut def) = (base_ty, base_def);
-        for segment in assoc_segments {
-            debug!("finish_resolving_def_to_ty: segment={:?}", segment);
-            // This is pretty bad (it will fail except for T::A and Self::A).
-            let (new_ty, new_def) = self.associated_path_def_to_ty(span, ty, def, segment);
-            ty = new_ty;
-            def = new_def;
-
-            if def == Def::Err {
-                break;
-            }
-        }
-        (ty, def)
-    }
-
     /// Parses the programmer's textual representation of a type into our
     /// internal notion of a type.
     pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
@@ -1701,26 +1648,28 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
                     tcx.types.err
                 }
             }
-            hir::TyPath(ref maybe_qself, ref path) => {
+            hir::TyPath(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
                 debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
-                let path_res = tcx.expect_resolution(ast_ty.id);
-                let base_ty_end = path.segments.len() - path_res.depth;
                 let opt_self_ty = maybe_qself.as_ref().map(|qself| {
-                    self.ast_ty_to_ty(rscope, &qself.ty)
+                    self.ast_ty_to_ty(rscope, qself)
                 });
-                let (ty, def) = self.finish_resolving_def_to_ty(rscope,
-                                                                ast_ty.span,
-                                                                path_res.base_def,
-                                                                opt_self_ty,
-                                                                ast_ty.id,
-                                                                &path.segments[..base_ty_end],
-                                                                &path.segments[base_ty_end..],
-                                                                false);
+                self.def_to_ty(rscope,
+                               ast_ty.span,
+                               tcx.expect_def(ast_ty.id),
+                               opt_self_ty,
+                               ast_ty.id,
+                               &path.segments,
+                               false)
+            }
+            hir::TyPath(hir::QPath::TypeRelative(ref qself, ref segment)) => {
+                debug!("ast_ty_to_ty: qself={:?} segment={:?}", qself, segment);
+                let ty = self.ast_ty_to_ty(rscope, qself);
+
+                let def = tcx.expect_def_or_none(qself.id).unwrap_or(Def::Err);
+                let (ty, def) = self.associated_path_def_to_ty(ast_ty.span, ty, def, segment);
 
                 // Write back the new resolution.
-                if path_res.depth != 0 {
-                    tcx.def_map.borrow_mut().insert(ast_ty.id, PathResolution::new(def));
-                }
+                tcx.def_map.borrow_mut().insert(ast_ty.id, PathResolution::new(def));
 
                 ty
             }
index 556d1f84fccdc2ff5276139d1c12c3b3d2ef9718..3e62b22d36f999546ef64c7caa7c1d5c8958ea89 100644 (file)
@@ -148,15 +148,14 @@ pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
 
                 typ
             }
-            PatKind::TupleStruct(ref path, ref subpats, ddpos) => {
-                self.check_pat_tuple_struct(pat, path, &subpats, ddpos, expected)
+            PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
+                self.check_pat_tuple_struct(pat, qpath, &subpats, ddpos, expected)
             }
-            PatKind::Path(ref opt_qself, ref path) => {
-                let opt_qself_ty = opt_qself.as_ref().map(|qself| self.to_ty(&qself.ty));
-                self.check_pat_path(pat, opt_qself_ty, path, expected)
+            PatKind::Path(ref qpath) => {
+                self.check_pat_path(pat, qpath, expected)
             }
-            PatKind::Struct(ref path, ref fields, etc) => {
-                self.check_pat_struct(pat, path, fields, etc, expected)
+            PatKind::Struct(ref qpath, ref fields, etc) => {
+                self.check_pat_struct(pat, qpath, fields, etc, expected)
             }
             PatKind::Tuple(ref elements, ddpos) => {
                 let mut expected_len = elements.len();
@@ -496,13 +495,13 @@ pub fn check_match(&self,
 
     fn check_pat_struct(&self,
                         pat: &'gcx hir::Pat,
-                        path: &hir::Path,
+                        qpath: &hir::QPath,
                         fields: &'gcx [Spanned<hir::FieldPat>],
                         etc: bool,
                         expected: Ty<'tcx>) -> Ty<'tcx>
     {
         // Resolve the path and check the definition for errors.
-        let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(path, pat.id) {
+        let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.id) {
             variant_ty
         } else {
             for field in fields {
@@ -521,20 +520,18 @@ fn check_pat_struct(&self,
 
     fn check_pat_path(&self,
                       pat: &hir::Pat,
-                      opt_self_ty: Option<Ty<'tcx>>,
-                      path: &hir::Path,
+                      qpath: &hir::QPath,
                       expected: Ty<'tcx>) -> Ty<'tcx>
     {
         let tcx = self.tcx;
         let report_unexpected_def = |def: Def| {
             span_err!(tcx.sess, pat.span, E0533,
                       "expected unit struct/variant or constant, found {} `{}`",
-                      def.kind_name(), path);
+                      def.kind_name(), qpath);
         };
 
         // Resolve the path and check the definition for errors.
-        let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path,
-                                                                   pat.id, pat.span);
+        let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
         match def {
             Def::Err => {
                 self.set_tainted_by_errors();
@@ -558,7 +555,7 @@ fn check_pat_path(&self,
 
     fn check_pat_tuple_struct(&self,
                               pat: &hir::Pat,
-                              path: &hir::Path,
+                              qpath: &hir::QPath,
                               subpats: &'gcx [P<hir::Pat>],
                               ddpos: Option<usize>,
                               expected: Ty<'tcx>) -> Ty<'tcx>
@@ -571,14 +568,14 @@ fn check_pat_tuple_struct(&self,
         };
         let report_unexpected_def = |def: Def| {
             let msg = format!("expected tuple struct/variant, found {} `{}`",
-                              def.kind_name(), path);
+                              def.kind_name(), qpath);
             struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
                 .span_label(pat.span, &format!("not a tuple variant or struct")).emit();
             on_error();
         };
 
         // Resolve the path and check the definition for errors.
-        let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(None, path, pat.id, pat.span);
+        let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
         let variant = match def {
             Def::Err => {
                 self.set_tainted_by_errors();
index 4ae15740cf2a66a66a3065a5b9b99a994cbc28f5..6598790355e8243f977f27bce3ba60631f3ced87 100644 (file)
@@ -28,7 +28,6 @@
 
 use rustc::hir::print as pprust;
 use rustc::hir;
-use rustc::hir::Expr_;
 
 use std::cell;
 use std::cmp::Ordering;
@@ -210,7 +209,7 @@ macro_rules! report_function {
                     if let Some(expr) = rcvr_expr {
                         if let Ok(expr_string) = tcx.sess.codemap().span_to_snippet(expr.span) {
                             report_function!(expr.span, expr_string);
-                        } else if let Expr_::ExprPath(_, path) = expr.node.clone() {
+                        } else if let hir::ExprPath(hir::QPath::Resolved(_, ref path)) = expr.node {
                             if let Some(segment) = path.segments.last() {
                                 report_function!(expr.span, segment.name);
                             }
index ea84786e06b986ffdaf6fdcab8ba62848c07ca9d..33b123d0a6d8f7c993f6ccf25176717c7c63a02c 100644 (file)
@@ -3301,10 +3301,14 @@ fn check_struct_fields_on_error(&self,
     }
 
     pub fn check_struct_path(&self,
-                             path: &hir::Path,
+                             qpath: &hir::QPath,
                              node_id: ast::NodeId)
                              -> Option<(ty::VariantDef<'tcx>,  Ty<'tcx>)> {
-        let (def, ty) = self.finish_resolving_struct_path(path, node_id);
+        let path_span = match *qpath {
+            hir::QPath::Resolved(_, ref path) => path.span,
+            hir::QPath::TypeRelative(ref qself, _) => qself.span
+        };
+        let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, node_id);
         let variant = match def {
             Def::Err => {
                 self.set_tainted_by_errors();
@@ -3324,7 +3328,7 @@ pub fn check_struct_path(&self,
                     Def::AssociatedTy(..) | Def::SelfTy(..)
                             if !self.tcx.sess.features.borrow().more_struct_aliases => {
                         emit_feature_err(&self.tcx.sess.parse_sess,
-                                         "more_struct_aliases", path.span, GateIssue::Language,
+                                         "more_struct_aliases", path_span, GateIssue::Language,
                                          "`Self` and associated types in struct \
                                           expressions and patterns are unstable");
                     }
@@ -3342,17 +3346,17 @@ pub fn check_struct_path(&self,
 
         if let Some((variant, did, substs)) = variant {
             // Check bounds on type arguments used in the path.
-            let bounds = self.instantiate_bounds(path.span, did, substs);
-            let cause = traits::ObligationCause::new(path.span, self.body_id,
+            let bounds = self.instantiate_bounds(path_span, did, substs);
+            let cause = traits::ObligationCause::new(path_span, self.body_id,
                                                      traits::ItemObligation(did));
             self.add_obligations_for_parameters(cause, &bounds);
 
             Some((variant, ty))
         } else {
-            struct_span_err!(self.tcx.sess, path.span, E0071,
+            struct_span_err!(self.tcx.sess, path_span, E0071,
                              "expected struct, variant or union type, found {}",
                              ty.sort_string(self.tcx))
-                .span_label(path.span, &format!("not a struct"))
+                .span_label(path_span, &format!("not a struct"))
                 .emit();
             None
         }
@@ -3360,19 +3364,25 @@ pub fn check_struct_path(&self,
 
     fn check_expr_struct(&self,
                          expr: &hir::Expr,
-                         path: &hir::Path,
+                         qpath: &hir::QPath,
                          fields: &'gcx [hir::Field],
                          base_expr: &'gcx Option<P<hir::Expr>>) -> Ty<'tcx>
     {
         // Find the relevant variant
-        let (variant, struct_ty) = if let Some(variant_ty) = self.check_struct_path(path, expr.id) {
+        let (variant, struct_ty) =
+        if let Some(variant_ty) = self.check_struct_path(qpath, expr.id) {
             variant_ty
         } else {
             self.check_struct_fields_on_error(fields, base_expr);
             return self.tcx.types.err;
         };
 
-        self.check_expr_struct_fields(struct_ty, path.span, variant, fields,
+        let path_span = match *qpath {
+            hir::QPath::Resolved(_, ref path) => path.span,
+            hir::QPath::TypeRelative(ref qself, _) => qself.span
+        };
+
+        self.check_expr_struct_fields(struct_ty, path_span, variant, fields,
                                       base_expr.is_none());
         if let &Some(ref base_expr) = base_expr {
             self.check_expr_has_type(base_expr, struct_ty);
@@ -3590,9 +3600,8 @@ fn check_expr_kind(&self,
                 tcx.mk_ref(region, tm)
             }
           }
-          hir::ExprPath(ref opt_qself, ref path) => {
-              let opt_self_ty = opt_qself.as_ref().map(|qself| self.to_ty(&qself.ty));
-              let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path,
+          hir::ExprPath(ref qpath) => {
+              let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath,
                                                                          expr.id, expr.span);
               let ty = if def != Def::Err {
                   self.instantiate_value_path(segments, opt_ty, def, expr.span, id)
@@ -3930,8 +3939,8 @@ fn check_expr_kind(&self,
                 tuple
             }
           }
-          hir::ExprStruct(ref path, ref fields, ref base_expr) => {
-            self.check_expr_struct(expr, path, fields, base_expr)
+          hir::ExprStruct(ref qpath, ref fields, ref base_expr) => {
+            self.check_expr_struct(expr, qpath, fields, base_expr)
           }
           hir::ExprField(ref base, ref field) => {
             self.check_field(expr, lvalue_pref, &base, field)
@@ -3999,72 +4008,75 @@ fn check_expr_kind(&self,
     // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
     // The newly resolved definition is written into `def_map`.
     fn finish_resolving_struct_path(&self,
-                                    path: &hir::Path,
+                                    qpath: &hir::QPath,
+                                    path_span: Span,
                                     node_id: ast::NodeId)
                                     -> (Def, Ty<'tcx>)
     {
-        let path_res = self.tcx.expect_resolution(node_id);
-        let base_ty_end = path.segments.len() - path_res.depth;
-        let (ty, def) = AstConv::finish_resolving_def_to_ty(self, self, path.span,
-                                                            path_res.base_def,
-                                                            None,
-                                                            node_id,
-                                                            &path.segments[..base_ty_end],
-                                                            &path.segments[base_ty_end..],
-                                                            true);
-        // Write back the new resolution.
-        if path_res.depth != 0 {
-            self.tcx.def_map.borrow_mut().insert(node_id, PathResolution::new(def));
+        match *qpath {
+            hir::QPath::Resolved(ref maybe_qself, ref path) => {
+                let opt_self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself));
+                let def = self.tcx.expect_def(node_id);
+                let ty = AstConv::def_to_ty(self, self,
+                                            path.span,
+                                            def,
+                                            opt_self_ty,
+                                            node_id,
+                                            &path.segments,
+                                            true);
+                (def, ty)
+            }
+            hir::QPath::TypeRelative(ref qself, ref segment) => {
+                let ty = self.to_ty(qself);
+
+                let def = self.tcx.expect_def_or_none(qself.id).unwrap_or(Def::Err);
+                let (ty, def) = AstConv::associated_path_def_to_ty(self, path_span,
+                                                                   ty, def, segment);
+
+                // Write back the new resolution.
+                self.tcx.def_map.borrow_mut().insert(node_id, PathResolution::new(def));
+
+                (def, ty)
+            }
         }
-        (def, ty)
     }
 
     // Resolve associated value path into a base type and associated constant or method definition.
     // The newly resolved definition is written into `def_map`.
     pub fn resolve_ty_and_def_ufcs<'b>(&self,
-                                       opt_self_ty: Option<Ty<'tcx>>,
-                                       path: &'b hir::Path,
+                                       qpath: &'b hir::QPath,
                                        node_id: ast::NodeId,
                                        span: Span)
                                        -> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment])
     {
-        let path_res = self.tcx.expect_resolution(node_id);
-        if path_res.depth == 0 {
-            // If fully resolved already, we don't have to do anything.
-            (path_res.base_def, opt_self_ty, &path.segments)
-        } else {
-            // Try to resolve everything except for the last segment as a type.
-            let ty_segments = path.segments.split_last().unwrap().1;
-            let base_ty_end = path.segments.len() - path_res.depth;
-            let (ty, _def) = AstConv::finish_resolving_def_to_ty(self, self, span,
-                                                                 path_res.base_def,
-                                                                 opt_self_ty,
-                                                                 node_id,
-                                                                 &ty_segments[..base_ty_end],
-                                                                 &ty_segments[base_ty_end..],
-                                                                 false);
-
-            // Resolve an associated constant or method on the previously resolved type.
-            let item_segment = path.segments.last().unwrap();
-            let item_name = item_segment.name;
-            let def = match self.resolve_ufcs(span, item_name, ty, node_id) {
-                Ok(def) => def,
-                Err(error) => {
-                    let def = match error {
-                        method::MethodError::PrivateMatch(def) => def,
-                        _ => Def::Err,
-                    };
-                    if item_name != keywords::Invalid.name() {
-                        self.report_method_error(span, ty, item_name, None, error);
-                    }
-                    def
+        let (ty, item_segment) = match *qpath {
+            hir::QPath::Resolved(ref opt_qself, ref path) => {
+                return (self.tcx.expect_def(node_id),
+                        opt_qself.as_ref().map(|qself| self.to_ty(qself)),
+                        &path.segments[..]);
+            }
+            hir::QPath::TypeRelative(ref qself, ref segment) => {
+                (self.to_ty(qself), segment)
+            }
+        };
+        let item_name = item_segment.name;
+        let def = match self.resolve_ufcs(span, item_name, ty, node_id) {
+            Ok(def) => def,
+            Err(error) => {
+                let def = match error {
+                    method::MethodError::PrivateMatch(def) => def,
+                    _ => Def::Err,
+                };
+                if item_name != keywords::Invalid.name() {
+                    self.report_method_error(span, ty, item_name, None, error);
                 }
-            };
+                def
+            }
+        };
 
-            // Write back the new resolution.
-            self.tcx.def_map.borrow_mut().insert(node_id, PathResolution::new(def));
-            (def, Some(ty), slice::ref_slice(item_segment))
-        }
+        // Write back the new resolution.
+        self.tcx.def_map.borrow_mut().insert(node_id, PathResolution::new(def));
+        (def, Some(ty), slice::ref_slice(&**item_segment))
     }
 
     pub fn check_decl_initializer(&self,
index c613b62bf2d82b4a3589f01d6f909986588d58b8..2b1bea89c526035753fa112847df629adc6290b1 100644 (file)
@@ -603,7 +603,7 @@ fn visit_expr(&mut self, expr: &hir::Expr) {
         debug!("regionck::visit_expr(e={:?}, repeating_scope={}) - visiting subexprs",
                expr, self.repeating_scope);
         match expr.node {
-            hir::ExprPath(..) => {
+            hir::ExprPath(_) => {
                 self.fcx.opt_node_ty_substs(expr.id, |item_substs| {
                     let origin = infer::ParameterOrigin::Path;
                     self.substs_wf_in_scope(origin, &item_substs.substs, expr.span, expr_region);
index 48d79a3ba4c87bb7b5fd932e0abbf7bb6f22d9ab..ca5208b7a035aae6dbdcb1f0c62cb6d27f67db70 100644 (file)
@@ -542,7 +542,7 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                       param_id: ast::NodeId)
                       -> bool
 {
-    if let hir::TyPath(None, _) = ast_ty.node {
+    if let hir::TyPath(hir::QPath::Resolved(None, _)) = ast_ty.node {
         let path_res = tcx.expect_resolution(ast_ty.id);
         match path_res.base_def {
             Def::SelfTy(Some(def_id), None) |
index a19ec4e8b5edbf6bd57d71163b324764f2f7db5b..aff384043497e0b5988e8f7411d2eabd4c6f132c 100644 (file)
@@ -1727,7 +1727,7 @@ fn clean(&self, cx: &DocContext) -> Type {
                 FixedVector(box ty.clean(cx), n)
             },
             TyTup(ref tys) => Tuple(tys.clean(cx)),
-            TyPath(None, ref path) => {
+            TyPath(hir::QPath::Resolved(None, ref path)) => {
                 let def = cx.tcx.expect_def(self.id);
                 if let Some(new_ty) = cx.ty_substs.borrow().get(&def).cloned() {
                     return new_ty;
@@ -1766,7 +1766,7 @@ fn clean(&self, cx: &DocContext) -> Type {
                 }
                 resolve_type(cx, path.clean(cx), self.id)
             }
-            TyPath(Some(ref qself), ref p) => {
+            TyPath(hir::QPath::Resolved(Some(ref qself), ref p)) => {
                 let mut segments: Vec<_> = p.segments.clone().into();
                 segments.pop();
                 let trait_path = hir::Path {
@@ -1776,7 +1776,19 @@ fn clean(&self, cx: &DocContext) -> Type {
                 };
                 Type::QPath {
                     name: p.segments.last().unwrap().name.clean(cx),
-                    self_type: box qself.ty.clean(cx),
+                    self_type: box qself.clean(cx),
+                    trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
+                }
+            }
+            TyPath(hir::QPath::TypeRelative(ref qself, ref segment)) => {
+                let trait_path = hir::Path {
+                    span: self.span,
+                    global: false,
+                    segments: vec![].into(),
+                };
+                Type::QPath {
+                    name: segment.name.clean(cx),
+                    self_type: box qself.clean(cx),
                     trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
                 }
             }
@@ -2263,11 +2275,20 @@ fn clean(&self, cx: &DocContext) -> PathSegment {
     }
 }
 
-fn path_to_string(p: &hir::Path) -> String {
+fn qpath_to_string(p: &hir::QPath) -> String {
+    let (segments, global) = match *p {
+        hir::QPath::Resolved(_, ref path) => {
+            (&path.segments, path.global)
+        }
+        hir::QPath::TypeRelative(_, ref segment) => {
+            return segment.name.to_string()
+        }
+    };
+
     let mut s = String::new();
     let mut first = true;
-    for i in p.segments.iter().map(|x| x.name.as_str()) {
-        if !first || p.global {
+    for i in segments.iter().map(|x| x.name.as_str()) {
+        if !first || global {
             s.push_str("::");
         } else {
             first = false;
@@ -2725,17 +2746,15 @@ fn name_from_pat(p: &hir::Pat) -> String {
     match p.node {
         PatKind::Wild => "_".to_string(),
         PatKind::Binding(_, ref p, _) => p.node.to_string(),
-        PatKind::TupleStruct(ref p, ..) | PatKind::Path(None, ref p) => path_to_string(p),
-        PatKind::Path(..) => panic!("tried to get argument name from qualified PatKind::Path, \
-                                     which is not allowed in function arguments"),
+        PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
         PatKind::Struct(ref name, ref fields, etc) => {
-            format!("{} {{ {}{} }}", path_to_string(name),
+            format!("{} {{ {}{} }}", qpath_to_string(name),
                 fields.iter().map(|&Spanned { node: ref fp, .. }|
                                   format!("{}: {}", fp.name, name_from_pat(&*fp.pat)))
                              .collect::<Vec<String>>().join(", "),
                 if etc { ", ..." } else { "" }
             )
-        },
+        }
         PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
                                             .collect::<Vec<String>>().join(", ")),
         PatKind::Box(ref p) => name_from_pat(&**p),
index d47fdda0203e8f0e38e92233d5d5816496935dee..48aabce708eab277d3bcfb944a5fbe15734272f0 100644 (file)
@@ -23,5 +23,5 @@ impl S {
 fn main() {
     if let C1(..) = 0 {} //~ ERROR expected tuple struct/variant, found constant `C1`
     if let S::C2(..) = 0 {}
-    //~^ ERROR expected tuple struct/variant, found associated constant `S::C2`
+    //~^ ERROR expected tuple struct/variant, found associated constant `<S>::C2`
 }
index aaa89b2282967318a630f10e7a6df2706c447bba..671a518073c376e478eca2bfea872473ac763c9c 100644 (file)
@@ -22,13 +22,15 @@ impl MyTrait for Foo {}
 
 fn main() {
     match 0u32 {
-        Foo::bar => {} //~ ERROR expected unit struct/variant or constant, found method `Foo::bar`
+        Foo::bar => {}
+        //~^ ERROR expected unit struct/variant or constant, found method `<Foo>::bar`
     }
     match 0u32 {
-        <Foo>::bar => {} //~ ERROR expected unit struct/variant or constant, found method `bar`
+        <Foo>::bar => {}
+        //~^ ERROR expected unit struct/variant or constant, found method `<Foo>::bar`
     }
     match 0u32 {
         <Foo>::trait_bar => {}
-        //~^ ERROR expected unit struct/variant or constant, found method `trait_bar`
+        //~^ ERROR expected unit struct/variant or constant, found method `<Foo>::trait_bar`
     }
 }
index 82b0536a64ad4ab840fc5e4982fb7409e10fbc97..a7bc27e1749182e0f1de42ab64f52992979e4216 100644 (file)
@@ -28,7 +28,7 @@ fn f<T>() {}
 fn main() {
     match 10 {
         <S as Tr>::A::f::<u8> => {}
-        //~^ ERROR expected unit struct/variant or constant, found method `Tr::A::f<u8>`
+        //~^ ERROR expected unit struct/variant or constant, found method `<<S as Tr>::A>::f<u8>`
         0 ... <S as Tr>::A::f::<u8> => {} //~ ERROR only char and numeric types are allowed in range
     }
 }
index 2c2f113a7790c48d9a885794cb01bba763a5e834..84bcca3fc7bd3a3726c6387ea087e21b2d6b926a 100644 (file)
@@ -9,11 +9,11 @@
 // except according to those terms.
 
 pub trait Foo<A=Self> {
-    fn foo();
+    fn foo(&self);
 }
 
 pub trait Bar<X=usize, A=Self> {
-    fn foo();
+    fn foo(&self);
 }
 
 fn main() {
index 24b0f90d08e4d21cc56bf8c2e15e4ea142e8ce25..fdb7f9c68b99db54189764c305f92df4223d482e 100644 (file)
@@ -40,7 +40,7 @@ pub fn bar() ({
 
 
                   (($crate::fmt::format as
-                       fn(std::fmt::Arguments<'_>) -> std::string::String {std::fmt::format})(((::std::fmt::Arguments::new_v1
+                       fn(std::fmt::Arguments<'_>) -> std::string::String {std::fmt::format})(((<::std::fmt::Arguments>::new_v1
                                                                                                    as
                                                                                                    fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments<'_>::new_v1})(({
                                                                                                                                                                                                                static __STATIC_FMTSTR: