From 34d1352f0eb7e7511e34b1e7640e854ffaf3f137 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 17 Oct 2016 06:02:23 +0300 Subject: [PATCH 01/12] rustc: encode the optionality of type parameters in HIR paths. --- src/librustc/hir/lowering.rs | 98 ++++++++++++++++++--------- src/librustc/hir/mod.rs | 6 ++ src/librustc/hir/print.rs | 10 +++ src/librustc/infer/error_reporting.rs | 1 + src/librustc_typeck/astconv.rs | 59 +++------------- src/librustc_typeck/check/mod.rs | 44 ++++++------ 6 files changed, 112 insertions(+), 106 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 5af7c18e1a107..264a5722bcd76 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -101,6 +101,14 @@ pub fn lower_crate(sess: &Session, }.lower_crate(krate) } +#[derive(Copy, Clone, PartialEq, Eq)] +enum ParamMode { + /// Any path in a type context. + Explicit, + /// The `module::Type` in `module::Type::method` in an expression. + Optional +} + impl<'a> LoweringContext<'a> { fn lower_crate(&mut self, c: &Crate) -> hir::Crate { struct ItemLowerer<'lcx, 'interner: 'lcx> { @@ -179,13 +187,14 @@ impl<'a> LoweringContext<'a> { P(Spanned { node: match view_path.node { ViewPathSimple(ident, ref path) => { - hir::ViewPathSimple(ident.name, self.lower_path(path)) + hir::ViewPathSimple(ident.name, + self.lower_path(path, None, ParamMode::Explicit)) } ViewPathGlob(ref path) => { - hir::ViewPathGlob(self.lower_path(path)) + hir::ViewPathGlob(self.lower_path(path, None, ParamMode::Explicit)) } ViewPathList(ref path, ref path_list_idents) => { - hir::ViewPathList(self.lower_path(path), + hir::ViewPathList(self.lower_path(path, None, ParamMode::Explicit), path_list_idents.iter() .map(|item| self.lower_path_list_item(item)) .collect()) @@ -256,7 +265,8 @@ impl<'a> LoweringContext<'a> { position: position, } }); - hir::TyPath(qself, self.lower_path(path)) + let path = self.lower_path(path, qself.as_ref(), ParamMode::Explicit); + hir::TyPath(qself, path) } TyKind::ObjectSum(ref ty, ref bounds) => { hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds)) @@ -298,38 +308,56 @@ impl<'a> LoweringContext<'a> { } } - fn lower_path(&mut self, p: &Path) -> hir::Path { + fn lower_path(&mut self, + p: &Path, + qself: Option<&hir::QSelf>, + param_mode: ParamMode) + -> hir::Path { hir::Path { global: p.global, - segments: p.segments - .iter() - .map(|&PathSegment { identifier, ref parameters }| { - hir::PathSegment { - name: identifier.name, - parameters: self.lower_path_parameters(parameters), - } - }) - .collect(), + 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 => { + // This segment is part of the trait path in a + // qualified path - one of `a`, `b` or `Trait` + // in `::T::U::method`. + ParamMode::Explicit + } + _ => param_mode + }; + hir::PathSegment { + name: identifier.name, + parameters: self.lower_path_parameters(parameters, param_mode), + } + }).collect(), span: p.span, } } - fn lower_path_parameters(&mut self, path_parameters: &PathParameters) -> hir::PathParameters { + fn lower_path_parameters(&mut self, + path_parameters: &PathParameters, + param_mode: ParamMode) + -> hir::PathParameters { match *path_parameters { - PathParameters::AngleBracketed(ref data) => - hir::AngleBracketedParameters(self.lower_angle_bracketed_parameter_data(data)), + 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)), } } fn lower_angle_bracketed_parameter_data(&mut self, - data: &AngleBracketedParameterData) + data: &AngleBracketedParameterData, + param_mode: ParamMode) -> hir::AngleBracketedParameterData { let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data; hir::AngleBracketedParameterData { lifetimes: self.lower_lifetimes(lifetimes), types: types.iter().map(|ty| self.lower_ty(ty)).collect(), + infer_types: types.is_empty() && param_mode == ParamMode::Optional, bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(), } } @@ -493,7 +521,7 @@ impl<'a> LoweringContext<'a> { span}) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { id: id, - path: self.lower_path(path), + path: self.lower_path(path, None, ParamMode::Explicit), ty: self.lower_ty(ty), span: span, }) @@ -523,7 +551,7 @@ impl<'a> LoweringContext<'a> { fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef { hir::TraitRef { - path: self.lower_path(&p.path), + path: self.lower_path(&p.path, None, ParamMode::Explicit), ref_id: p.ref_id, } } @@ -887,17 +915,19 @@ impl<'a> LoweringContext<'a> { } 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), - pats.iter().map(|x| self.lower_pat(x)).collect(), ddpos) + hir::PatKind::TupleStruct(self.lower_path(path, None, ParamMode::Optional), + pats.iter().map(|x| self.lower_pat(x)).collect(), + ddpos) } - PatKind::Path(ref opt_qself, ref path) => { - let opt_qself = opt_qself.as_ref().map(|qself| { + PatKind::Path(ref qself, ref path) => { + let qself = qself.as_ref().map(|qself| { hir::QSelf { ty: self.lower_ty(&qself.ty), position: qself.position } }); - hir::PatKind::Path(opt_qself, self.lower_path(path)) + let path = self.lower_path(path, qself.as_ref(), ParamMode::Optional); + hir::PatKind::Path(qself, path) } PatKind::Struct(ref pth, ref fields, etc) => { - let pth = self.lower_path(pth); + let pth = self.lower_path(pth, None, ParamMode::Optional); let fs = fields.iter() .map(|f| { Spanned { @@ -1236,13 +1266,14 @@ impl<'a> LoweringContext<'a> { }; } ExprKind::Path(ref qself, ref path) => { - let hir_qself = qself.as_ref().map(|&QSelf { ref ty, position }| { + let qself = qself.as_ref().map(|&QSelf { ref ty, position }| { hir::QSelf { ty: self.lower_ty(ty), position: position, } }); - hir::ExprPath(hir_qself, self.lower_path(path)) + let path = self.lower_path(path, qself.as_ref(), ParamMode::Optional); + hir::ExprPath(qself, path) } ExprKind::Break(opt_ident, ref opt_expr) => { hir::ExprBreak(self.lower_opt_sp_ident(opt_ident), @@ -1275,7 +1306,7 @@ impl<'a> LoweringContext<'a> { hir::ExprInlineAsm(P(hir_asm), outputs, inputs) } ExprKind::Struct(ref path, ref fields, ref maybe_expr) => { - hir::ExprStruct(P(self.lower_path(path)), + hir::ExprStruct(P(self.lower_path(path, None, ParamMode::Optional)), fields.iter().map(|x| self.lower_field(x)).collect(), maybe_expr.as_ref().map(|x| P(self.lower_expr(x)))) } @@ -1655,8 +1686,12 @@ impl<'a> LoweringContext<'a> { match *v { Visibility::Public => hir::Public, Visibility::Crate(_) => hir::Visibility::Crate, - Visibility::Restricted { ref path, id } => - hir::Visibility::Restricted { path: P(self.lower_path(path)), id: id }, + Visibility::Restricted { ref path, id } => { + hir::Visibility::Restricted { + path: P(self.lower_path(path, None, ParamMode::Explicit)), + id: id + } + } Visibility::Inherited => hir::Inherited, } } @@ -1949,6 +1984,7 @@ impl<'a> LoweringContext<'a> { parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData { lifetimes: lifetimes, types: types, + infer_types: true, bindings: bindings, }), }); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 3164876522425..6f0a3a0238084 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -167,6 +167,7 @@ impl PathParameters { AngleBracketedParameters(AngleBracketedParameterData { lifetimes: HirVec::new(), types: HirVec::new(), + infer_types: true, bindings: HirVec::new(), }) } @@ -241,6 +242,11 @@ pub struct AngleBracketedParameterData { pub lifetimes: HirVec, /// The type parameters for this path segment, if present. pub types: HirVec>, + /// Whether to infer remaining type parameters, if any. + /// This only applies to expression and pattern paths, and + /// out of those only the segments with no type parameters + /// to begin with, e.g. `Vec::new` is `>::new::<..>`. + pub infer_types: bool, /// Bindings (equality constraints) on associated types, if present. /// E.g., `Foo`. pub bindings: HirVec, diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index c109e84bf6186..9934259c5d191 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1696,6 +1696,16 @@ impl<'a> State<'a> { comma = true; } + // FIXME(eddyb) This would leak into error messages, e.g.: + // "non-exhaustive patterns: `Some::<..>(_)` not covered". + if data.infer_types && false { + if comma { + self.word_space(",")? + } + word(&mut self.s, "..")?; + comma = true; + } + for binding in data.bindings.iter() { if comma { self.word_space(",")? diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index 8db09d0b73d32..b9b974733409f 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -1609,6 +1609,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { hir::AngleBracketedParameters(hir::AngleBracketedParameterData { lifetimes: new_lts.into(), types: new_types, + infer_types: data.infer_types, bindings: new_bindings, }) } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index c5db8bc8cedc7..831426c3f06b6 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -149,14 +149,6 @@ pub trait AstConv<'gcx, 'tcx> { fn set_tainted_by_errors(&self); } -#[derive(PartialEq, Eq)] -pub enum PathParamMode { - // Any path in a type context. - Explicit, - // The `module::Type` in `module::Type::method` in an expression. - Optional -} - struct ConvertedBinding<'tcx> { item_name: ast::Name, ty: Ty<'tcx>, @@ -341,7 +333,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { pub fn ast_path_substs_for_ty(&self, rscope: &RegionScope, span: Span, - param_mode: PathParamMode, def_id: DefId, item_segment: &hir::PathSegment) -> &'tcx Substs<'tcx> @@ -367,7 +358,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let (substs, assoc_bindings) = self.create_substs_for_ast_path(rscope, span, - param_mode, def_id, &item_segment.parameters, None); @@ -385,7 +375,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn create_substs_for_ast_path(&self, rscope: &RegionScope, span: Span, - param_mode: PathParamMode, def_id: DefId, parameters: &hir::PathParameters, self_ty: Option>) @@ -397,15 +386,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { parameters={:?})", def_id, self_ty, parameters); - let (lifetimes, num_types_provided) = match *parameters { + let (lifetimes, num_types_provided, infer_types) = match *parameters { hir::AngleBracketedParameters(ref data) => { - if param_mode == PathParamMode::Optional && data.types.is_empty() { - (&data.lifetimes[..], None) - } else { - (&data.lifetimes[..], Some(data.types.len())) - } + (&data.lifetimes[..], data.types.len(), data.infer_types) } - hir::ParenthesizedParameters(_) => (&[][..], Some(1)) + hir::ParenthesizedParameters(_) => (&[][..], 1, false) }; // If the type is parameterized by this region, then replace this @@ -443,9 +428,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { assert_eq!(decl_generics.has_self, self_ty.is_some()); // Check the number of type parameters supplied by the user. - if let Some(num_provided) = num_types_provided { - let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..]; - check_type_argument_count(tcx, span, num_provided, ty_param_defs); + let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..]; + if !infer_types || num_types_provided > ty_param_defs.len() { + check_type_argument_count(tcx, span, num_types_provided, ty_param_defs); } let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF); @@ -474,7 +459,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } let i = i - self_ty.is_some() as usize - decl_generics.regions.len(); - if num_types_provided.map_or(false, |n| i < n) { + if i < num_types_provided { // A provided type parameter. match *parameters { hir::AngleBracketedParameters(ref data) => { @@ -488,7 +473,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { ty } } - } else if num_types_provided.is_none() { + } else if infer_types { // No type parameters were provided, we can infer all. let ty_var = if !default_needs_object_self(def) { self.ty_infer_for_def(def, substs, span) @@ -664,7 +649,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let trait_def_id = self.trait_def_id(trait_ref); self.ast_path_to_poly_trait_ref(rscope, trait_ref.path.span, - PathParamMode::Explicit, trait_def_id, self_ty, trait_ref.ref_id, @@ -687,7 +671,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let trait_def_id = self.trait_def_id(trait_ref); self.ast_path_to_mono_trait_ref(rscope, trait_ref.path.span, - PathParamMode::Explicit, trait_def_id, self_ty, trait_ref.path.segments.last().unwrap()) @@ -710,7 +693,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn ast_path_to_poly_trait_ref(&self, rscope: &RegionScope, span: Span, - param_mode: PathParamMode, trait_def_id: DefId, self_ty: Ty<'tcx>, path_id: ast::NodeId, @@ -729,7 +711,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let (substs, assoc_bindings) = self.create_substs_for_ast_trait_ref(shifted_rscope, span, - param_mode, trait_def_id, self_ty, trait_segment); @@ -752,7 +733,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn ast_path_to_mono_trait_ref(&self, rscope: &RegionScope, span: Span, - param_mode: PathParamMode, trait_def_id: DefId, self_ty: Ty<'tcx>, trait_segment: &hir::PathSegment) @@ -761,7 +741,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let (substs, assoc_bindings) = self.create_substs_for_ast_trait_ref(rscope, span, - param_mode, trait_def_id, self_ty, trait_segment); @@ -772,7 +751,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn create_substs_for_ast_trait_ref(&self, rscope: &RegionScope, span: Span, - param_mode: PathParamMode, trait_def_id: DefId, self_ty: Ty<'tcx>, trait_segment: &hir::PathSegment) @@ -817,7 +795,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.create_substs_for_ast_path(rscope, span, - param_mode, trait_def_id, &trait_segment.parameters, Some(self_ty)) @@ -929,7 +906,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn ast_path_to_ty(&self, rscope: &RegionScope, span: Span, - param_mode: PathParamMode, did: DefId, item_segment: &hir::PathSegment) -> Ty<'tcx> @@ -944,7 +920,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let substs = self.ast_path_substs_for_ty(rscope, span, - param_mode, did, item_segment); @@ -983,7 +958,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { Def::Trait(trait_def_id) if resolution.depth == 0 => { self.trait_path_to_object_type(rscope, path.span, - PathParamMode::Explicit, trait_def_id, ty.id, path.segments.last().unwrap(), @@ -1055,7 +1029,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn trait_path_to_object_type(&self, rscope: &RegionScope, path_span: Span, - param_mode: PathParamMode, trait_def_id: DefId, trait_path_ref_id: ast::NodeId, trait_segment: &hir::PathSegment, @@ -1068,7 +1041,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let dummy_self = tcx.mk_ty(TRAIT_OBJECT_DUMMY_SELF); let principal = self.ast_path_to_poly_trait_ref(rscope, path_span, - param_mode, trait_def_id, dummy_self, trait_path_ref_id, @@ -1377,7 +1349,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn qpath_to_ty(&self, rscope: &RegionScope, span: Span, - param_mode: PathParamMode, opt_self_ty: Option>, trait_def_id: DefId, trait_segment: &hir::PathSegment, @@ -1403,7 +1374,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let trait_ref = self.ast_path_to_mono_trait_ref(rscope, span, - param_mode, trait_def_id, self_ty, trait_segment); @@ -1448,7 +1418,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn base_def_to_ty(&self, rscope: &RegionScope, span: Span, - param_mode: PathParamMode, def: Def, opt_self_ty: Option>, base_path_ref_id: ast::NodeId, @@ -1469,7 +1438,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.trait_path_to_object_type(rscope, span, - param_mode, trait_def_id, base_path_ref_id, base_segments.last().unwrap(), @@ -1478,11 +1446,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } 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, - param_mode, - did, - base_segments.last().unwrap()) + self.ast_path_to_ty(rscope, span, did, base_segments.last().unwrap()) } Def::Variant(did) if permit_variants => { // Convert "variant type" as if it were a real type. @@ -1535,7 +1499,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let trait_did = tcx.parent_def_id(def_id).unwrap(); self.qpath_to_ty(rscope, span, - param_mode, opt_self_ty, trait_did, &base_segments[base_segments.len()-2], @@ -1577,7 +1540,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { pub fn finish_resolving_def_to_ty(&self, rscope: &RegionScope, span: Span, - param_mode: PathParamMode, base_def: Def, opt_self_ty: Option>, base_path_ref_id: ast::NodeId, @@ -1594,7 +1556,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { assoc_segments); let base_ty = self.base_def_to_ty(rscope, span, - param_mode, base_def, opt_self_ty, base_path_ref_id, @@ -1749,7 +1710,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }); let (ty, def) = self.finish_resolving_def_to_ty(rscope, ast_ty.span, - PathParamMode::Explicit, path_res.base_def, opt_self_ty, ast_ty.id, @@ -2007,7 +1967,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let trait_def_id = self.trait_def_id(trait_ref); self.trait_path_to_object_type(rscope, trait_ref.path.span, - PathParamMode::Explicit, trait_def_id, trait_ref.ref_id, trait_ref.path.segments.last().unwrap(), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index eeb7bb287002f..ea84786e06b98 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -80,7 +80,7 @@ pub use self::Expectation::*; pub use self::compare_method::{compare_impl_method, compare_const_impl}; use self::TupleArgumentsFlag::*; -use astconv::{AstConv, ast_region_to_region, PathParamMode}; +use astconv::{AstConv, ast_region_to_region}; use dep_graph::DepNode; use fmt_macros::{Parser, Piece, Position}; use hir::def::{Def, CtorKind, PathResolution}; @@ -4006,7 +4006,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, '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, - PathParamMode::Optional, path_res.base_def, None, node_id, @@ -4038,7 +4037,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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, - PathParamMode::Optional, path_res.base_def, opt_self_ty, node_id, @@ -4379,11 +4377,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => bug!("unexpected definition: {:?}", def), } - // In `>::method`, `A` and `B` are mandatory, but - // `opt_self_ty` can also be Some for `Foo::method`, where Foo's - // type parameters are not mandatory. - let require_type_space = opt_self_ty.is_some() && ufcs_associated.is_none(); - debug!("type_segment={:?} fn_segment={:?}", type_segment, fn_segment); // Now that we have categorized what space the parameters for each @@ -4414,8 +4407,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // variables. If the user provided some types, we may still need // to add defaults. If the user provided *too many* types, that's // a problem. - self.check_path_parameter_count(span, !require_type_space, &mut type_segment); - self.check_path_parameter_count(span, true, &mut fn_segment); + self.check_path_parameter_count(span, &mut type_segment); + self.check_path_parameter_count(span, &mut fn_segment); let (fn_start, has_self) = match (type_segment, fn_segment) { (_, Some((_, generics))) => { @@ -4450,7 +4443,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }, |def, substs| { let mut i = def.index as usize; - let can_omit = i >= fn_start || !require_type_space; let segment = if i < fn_start { // Handle Self first, so we can adjust the index to match the AST. if has_self && i == 0 { @@ -4464,10 +4456,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { i -= fn_start; fn_segment }; - let types = match segment.map(|(s, _)| &s.parameters) { - Some(&hir::AngleBracketedParameters(ref data)) => &data.types[..], + let (types, infer_types) = match segment.map(|(s, _)| &s.parameters) { + Some(&hir::AngleBracketedParameters(ref data)) => { + (&data.types[..], data.infer_types) + } Some(&hir::ParenthesizedParameters(_)) => bug!(), - None => &[] + None => (&[][..], true) }; // Skip over the lifetimes in the same segment. @@ -4475,11 +4469,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { i -= generics.regions.len(); } - let omitted = can_omit && types.is_empty(); if let Some(ast_ty) = types.get(i) { // A provided type parameter. self.to_ty(ast_ty) - } else if let (false, Some(default)) = (omitted, def.default) { + } else if let (false, Some(default)) = (infer_types, def.default) { // No type parameter provided, but a default exists. default.subst_spanned(self.tcx, substs, Some(span)) } else { @@ -4539,16 +4532,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// Report errors if the provided parameters are too few or too many. fn check_path_parameter_count(&self, span: Span, - can_omit: bool, segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) { - let (lifetimes, types, bindings) = match segment.map(|(s, _)| &s.parameters) { - Some(&hir::AngleBracketedParameters(ref data)) => { - (&data.lifetimes[..], &data.types[..], &data.bindings[..]) - } - Some(&hir::ParenthesizedParameters(_)) => { - span_bug!(span, "parenthesized parameters cannot appear in ExprPath"); + let (lifetimes, types, infer_types, bindings) = { + match segment.map(|(s, _)| &s.parameters) { + Some(&hir::AngleBracketedParameters(ref data)) => { + (&data.lifetimes[..], &data.types[..], data.infer_types, &data.bindings[..]) + } + Some(&hir::ParenthesizedParameters(_)) => { + span_bug!(span, "parenthesized parameters cannot appear in ExprPath"); + } + None => (&[][..], &[][..], true, &[][..]) } - None => (&[][..], &[][..], &[][..]) }; let count = |n| { @@ -4597,7 +4591,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // type parameters, we force instantiate_value_path to // use inference variables instead of the provided types. *segment = None; - } else if !(can_omit && types.len() == 0) && types.len() < required_len { + } else if !infer_types && types.len() < required_len { let adjust = |len| if len > 1 { "parameters" } else { "parameter" }; let required_param_str = adjust(required_len); let actual_param_str = adjust(types.len()); From 16b5c2cfef811feebe2797bcb7e01d2b6ff12db1 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 27 Oct 2016 05:17:42 +0300 Subject: [PATCH 02/12] rustc: desugar UFCS as much as possible during HIR lowering. --- src/librustc/cfg/construct.rs | 4 +- src/librustc/hir/intravisit.rs | 51 +++-- src/librustc/hir/lowering.rs | 189 ++++++++++++------ src/librustc/hir/mod.rs | 68 ++++--- src/librustc/hir/pat_util.rs | 13 +- src/librustc/hir/print.rs | 118 ++++++----- src/librustc/infer/error_reporting.rs | 11 +- src/librustc/middle/astconv_util.rs | 24 +-- src/librustc/middle/dead.rs | 3 + src/librustc/middle/effect.rs | 2 +- src/librustc/middle/expr_use_visitor.rs | 2 +- src/librustc/middle/intrinsicck.rs | 32 +-- src/librustc/middle/liveness.rs | 16 +- src/librustc/middle/mem_categorization.rs | 4 +- src/librustc/middle/reachable.rs | 2 +- src/librustc/middle/resolve_lifetime.rs | 7 +- src/librustc/middle/stability.rs | 28 +++ src/librustc/ty/mod.rs | 11 +- src/librustc_const_eval/_match.rs | 11 +- src/librustc_const_eval/eval.rs | 46 +++-- .../calculate_svh/svh_visitor.rs | 16 +- src/librustc_lint/bad_style.rs | 2 +- src/librustc_lint/builtin.rs | 8 +- src/librustc_lint/unused.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 4 +- src/librustc_passes/consts.rs | 2 +- src/librustc_passes/hir_stats.rs | 5 +- src/librustc_passes/static_recursion.rs | 2 +- src/librustc_privacy/lib.rs | 34 ++-- src/librustc_typeck/astconv.rs | 165 ++++++--------- src/librustc_typeck/check/_match.rs | 31 ++- src/librustc_typeck/check/method/suggest.rs | 3 +- src/librustc_typeck/check/mod.rs | 144 +++++++------ src/librustc_typeck/check/regionck.rs | 2 +- src/librustc_typeck/collect.rs | 2 +- src/librustdoc/clean/mod.rs | 41 +++- src/test/compile-fail/issue-28992-empty.rs | 2 +- .../compile-fail/method-path-in-pattern.rs | 8 +- .../compile-fail/qualified-path-params.rs | 2 +- .../unspecified-self-in-trait-ref.rs | 4 +- src/test/pretty/issue-4264.pp | 2 +- 41 files changed, 637 insertions(+), 486 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index c399623462b5d..609d492a93aec 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -100,7 +100,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { 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 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { hir::ExprClosure(..) | hir::ExprLit(..) | - hir::ExprPath(..) => { + hir::ExprPath(_) => { self.straightline(expr, pred, None::.iter()) } } diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 7dd88e36dd1f5..743eed74d0cea 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -244,6 +244,9 @@ pub trait Visitor<'v> : Sized { 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); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 264a5722bcd76..056c1b906206a 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -188,13 +188,13 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { } } - 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, + 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 `::T::U::method`. @@ -326,26 +326,91 @@ impl<'a> LoweringContext<'a> { } _ => 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 `::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 ::...") + } else { + // Otherwise, the base path is an implicit `Self` type path, + // e.g. `Vec` in `Vec::new` or `::Item` in + // `::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::::IntoIter::Item::clone`: + // * base path is `std::vec::Vec` + // * "extensions" are `IntoIter`, `Item` and `clone` + // * type nodes are: + // 1. `std::vec::Vec` (created above) + // 2. `>::IntoIter` + // 3. `<>::IntoIter>::Item` + // * final path is `<<>::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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { } }) .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 @@ impl<'a> LoweringContext<'a> { }; } 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { } 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 @@ impl<'a> LoweringContext<'a> { fn expr_path(&mut self, path: hir::Path, attrs: ThinVec) -> P { 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 @@ impl<'a> LoweringContext<'a> { e: Option>, attrs: ThinVec) -> P { 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) -> hir::Expr { @@ -1902,10 +1962,11 @@ impl<'a> LoweringContext<'a> { fn pat_enum(&mut self, span: Span, path: hir::Path, subpats: hir::HirVec>) -> P { 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 @@ impl<'a> LoweringContext<'a> { }); self.expr_block(block, attrs) } + + fn ty(&mut self, span: Span, node: hir::Ty_) -> P { + P(hir::Ty { + id: self.next_id(), + node: node, + span: span, + }) + } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 6f0a3a0238084..e9e84eed3e78c 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -533,7 +533,7 @@ impl Pat { 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>, bool), + Struct(QPath, HirVec>, bool), /// A tuple struct/variant pattern `Variant(x, y, .., z)`. /// If the `..` pattern fragment is present, then `Option` denotes its position. /// 0 <= position <= subpats.len() - TupleStruct(Path, HirVec>, Option), + TupleStruct(QPath, HirVec>, Option), - /// A possibly qualified path pattern. - /// Such pattern can be resolved to a unit struct/variant or a constant. - Path(Option, 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` denotes its position. @@ -940,12 +939,8 @@ pub enum Expr_ { /// An indexing operation (`foo[2]`) ExprIndex(P, P), - /// Variable reference, possibly containing `::` and/or type - /// parameters, e.g. foo::bar::. - /// - /// Optionally "qualified", - /// e.g. ` as SomeTrait>::SomeType`. - ExprPath(Option, Path), + /// Path to a definition, possibly containing lifetime or type parameters. + ExprPath(QPath), /// A referencing operation (`&a` or `&mut a`) ExprAddrOf(Mutability, P), @@ -963,7 +958,7 @@ pub enum Expr_ { /// /// For example, `Foo {x: 1, y: 2}`, or /// `Foo {x: 1, .. base}`, where `base` is the `Option`. - ExprStruct(P, HirVec, Option>), + ExprStruct(QPath, HirVec, Option>), /// An array literal constructed from one repeated element. /// @@ -972,22 +967,30 @@ pub enum Expr_ { ExprRepeat(P, P), } -/// 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. -/// -/// as a::b::Trait>::AssociatedItem -/// ^~~~~ ~~~~~~~~~~~~~~^ -/// ty position = 3 -/// -/// >::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, - 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 ` as Clone>::clone` has `Some(Vec)` for `Self`, + /// even though they both have the same two-segment `Clone::clone` `Path`. + Resolved(Option>, P), + + /// Type-related paths, e.g. `::default` or `::Output`. + /// Will be resolved by type-checking to an associated item. + /// + /// UFCS source paths can desugar into this, with `Vec::new` turning into + /// `::new`, and `T::X::Y::method` into `<<::X>::Y>::method`, + /// the `X` and `Y` nodes being each a `TyPath(QPath::TypeRelative(..))`. + TypeRelative(P, P) +} + +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>), - /// A path (`module::module::...::Type`), optionally - /// "qualified", e.g. ` as SomeTrait>::SomeType`. + /// A path to a type definition (`module::module::...::Type`), or an + /// associated type, e.g. ` as Trait>::Type` or `::Target`. /// - /// Type parameters are stored in the Path itself - TyPath(Option, 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, TyParamBounds), /// A type like `for<'a> Foo<&'a Bar>` diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index 0deea94146361..8e39fde367ba7 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -53,9 +53,13 @@ impl EnumerateAndAdjustIterator for T { 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 { 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)) | diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 9934259c5d191..448139c37e646 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -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 @@ impl<'a> State<'a> { }; 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 @@ impl<'a> State<'a> { } 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 @@ impl<'a> State<'a> { } fn print_expr_struct(&mut self, - path: &hir::Path, + qpath: &hir::QPath, fields: &[hir::Field], wth: &Option>) -> 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 @@ impl<'a> State<'a> { 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 @@ impl<'a> State<'a> { 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 @@ impl<'a> State<'a> { 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 @@ impl<'a> State<'a> { } 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 @@ impl<'a> State<'a> { 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 @@ impl<'a> State<'a> { 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 @@ impl<'a> State<'a> { } 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 @@ impl<'a> State<'a> { } } &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 @@ impl<'a> State<'a> { 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 @@ impl<'a> State<'a> { } hir::ViewPathGlob(ref path) => { - self.print_path(path, false, 0)?; + self.print_path(path, false)?; word(&mut self.s, "::*") } @@ -2152,7 +2176,7 @@ impl<'a> State<'a> { 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))?; diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index b9b974733409f..406d345992a20 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -1440,7 +1440,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { } 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 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { }; 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)); diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs index 86422835c8cbd..5b0f241f8a878 100644 --- a/src/librustc/middle/astconv_util.rs +++ b/src/librustc/middle/astconv_util.rs @@ -14,14 +14,14 @@ * 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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } 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> { - if let ast::TyPath(None, ref path) = ast_ty.node { + pub fn ast_ty_to_prim_ty(self, ast_ty: &hir::Ty) -> Option> { + 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 { diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index f47eab013c2b2..efbec7bf13b9e 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -240,6 +240,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { 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); } diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 25fe407271bc0..2892f249c5efb 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -186,7 +186,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { 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"); diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 594ed408d8cd4..6c952825554de 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -374,7 +374,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { self.walk_adjustment(expr); match expr.node { - hir::ExprPath(..) => { } + hir::ExprPath(_) => { } hir::ExprType(ref subexpr, _) => { self.walk_expr(&subexpr) diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 80cf64865abea..c610c6f75b0ca 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -160,23 +160,27 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> { 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); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 4b1787ba593cb..eefed0a5a74ff 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { 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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.propagate_through_exprs(inputs, succ) } - hir::ExprLit(..) => { + hir::ExprLit(..) | hir::ExprPath(hir::QPath::TypeRelative(..)) => { succ } @@ -1235,7 +1235,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // 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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { 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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { 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 diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index fedf8c2ec7472..1ca078dcd2e49 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -488,7 +488,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } } - hir::ExprPath(..) => { + hir::ExprPath(_) => { self.cat_def(expr.id, expr.span, expr_ty, self.tcx().expect_def(expr.id)) } @@ -1157,7 +1157,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } } - PatKind::Path(..) | PatKind::Binding(.., None) | + PatKind::Path(_) | PatKind::Binding(.., None) | PatKind::Lit(..) | PatKind::Range(..) | PatKind::Wild => { // always ok } diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 35e0e494771ba..0329b4c4a3019 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -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) { diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 41da5562e23fa..c65fd25950dea 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -244,7 +244,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { 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 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap, 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 diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 86a89eff3a476..a044ffd9a7f85 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -486,6 +486,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { 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)) { + 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, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 7982c641ede5c..3d02ff4651f88 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2059,11 +2059,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { 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(..) | diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs index c48811cb295bd..4731cea02065b 100644 --- a/src/librustc_const_eval/_match.rs +++ b/src/librustc_const_eval/_match.rs @@ -324,6 +324,7 @@ impl Witness { 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 @@ impl Witness { } }).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) } } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index b594fe9853a43..e8c05ec1a35ae 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -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::>()?; - 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::>()?; - 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(); diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index fd0856393fc1b..ec40531101259 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -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), + 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 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has 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); diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index 4440cb41dc5f2..25ea3d65993a4 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -376,7 +376,7 @@ impl LateLintPass for NonUpperCaseGlobals { 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, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 0b2ae58852300..7be591293c91b 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -718,6 +718,12 @@ impl LateLintPass for Deprecated { &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 @@ impl LateLintPass for MutableTransmutes { 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) { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index fa452017f0cf1..d0ad682fb58a6 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -218,7 +218,7 @@ impl LintPass for PathStatements { 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"); } } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 6fa2672593587..0c796ad42bbc2 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -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) } diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 4d8520ed0440a..ff46273a997c8 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -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. diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index dafb7bc6e6099..9028821ef116d 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -218,6 +218,10 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { 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 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { 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) diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs index 5f76f865c4aca..b98cf7e602b10 100644 --- a/src/librustc_passes/static_recursion.rs +++ b/src/librustc_passes/static_recursion.rs @@ -250,7 +250,7 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> { 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)) | diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index b116408269e4d..55e11caac6d02 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -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 { - 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 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { 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 @@ impl<'b, 'a, 'tcx: 'a> Visitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b } 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 @@ impl<'b, 'a, 'tcx: 'a> Visitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b // 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 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> { } } } - 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 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { 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 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } 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 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { 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 { // 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 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { // type Alias = 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 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { 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 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a, } 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), }; diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 831426c3f06b6..7d02678679ac6 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -952,7 +952,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } } - // 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>, - 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>, + 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } 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 `::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 ::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 ::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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } } - // 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>, - 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 556d1f84fccdc..3e62b22d36f99 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -148,15 +148,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, '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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_pat_struct(&self, pat: &'gcx hir::Pat, - path: &hir::Path, + qpath: &hir::QPath, fields: &'gcx [Spanned], 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_pat_path(&self, pat: &hir::Pat, - opt_self_ty: Option>, - 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_pat_tuple_struct(&self, pat: &hir::Pat, - path: &hir::Path, + qpath: &hir::QPath, subpats: &'gcx [P], ddpos: Option, expected: Ty<'tcx>) -> Ty<'tcx> @@ -571,14 +568,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; 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(); diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 4ae15740cf2a6..6598790355e82 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -28,7 +28,6 @@ use syntax_pos::Span; use rustc::hir::print as pprust; use rustc::hir; -use rustc::hir::Expr_; use std::cell; use std::cmp::Ordering; @@ -210,7 +209,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ea84786e06b98..33b123d0a6d8f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3301,10 +3301,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_expr_struct(&self, expr: &hir::Expr, - path: &hir::Path, + qpath: &hir::QPath, fields: &'gcx [hir::Field], base_expr: &'gcx Option>) -> 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // 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>, - path: &'b hir::Path, + qpath: &'b hir::QPath, node_id: ast::NodeId, span: Span) -> (Def, Option>, &'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, diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index c613b62bf2d82..2b1bea89c5260 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -603,7 +603,7 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for RegionCtxt<'a, 'gcx, 'tcx> { 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); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 48d79a3ba4c87..ca5208b7a035a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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) | diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a19ec4e8b5edb..aff384043497e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1727,7 +1727,7 @@ impl Clean for hir::Ty { 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 @@ impl Clean for hir::Ty { } 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 @@ impl Clean for hir::Ty { }; 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 @@ impl Clean for hir::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::>().join(", "), if etc { ", ..." } else { "" } ) - }, + } PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p)) .collect::>().join(", ")), PatKind::Box(ref p) => name_from_pat(&**p), diff --git a/src/test/compile-fail/issue-28992-empty.rs b/src/test/compile-fail/issue-28992-empty.rs index d47fdda0203e8..48aabce708eab 100644 --- a/src/test/compile-fail/issue-28992-empty.rs +++ b/src/test/compile-fail/issue-28992-empty.rs @@ -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 `::C2` } diff --git a/src/test/compile-fail/method-path-in-pattern.rs b/src/test/compile-fail/method-path-in-pattern.rs index aaa89b2282967..671a518073c37 100644 --- a/src/test/compile-fail/method-path-in-pattern.rs +++ b/src/test/compile-fail/method-path-in-pattern.rs @@ -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 `::bar` } match 0u32 { - ::bar => {} //~ ERROR expected unit struct/variant or constant, found method `bar` + ::bar => {} + //~^ ERROR expected unit struct/variant or constant, found method `::bar` } match 0u32 { ::trait_bar => {} - //~^ ERROR expected unit struct/variant or constant, found method `trait_bar` + //~^ ERROR expected unit struct/variant or constant, found method `::trait_bar` } } diff --git a/src/test/compile-fail/qualified-path-params.rs b/src/test/compile-fail/qualified-path-params.rs index 82b0536a64ad4..a7bc27e174918 100644 --- a/src/test/compile-fail/qualified-path-params.rs +++ b/src/test/compile-fail/qualified-path-params.rs @@ -28,7 +28,7 @@ impl S { fn main() { match 10 { ::A::f:: => {} - //~^ ERROR expected unit struct/variant or constant, found method `Tr::A::f` + //~^ ERROR expected unit struct/variant or constant, found method `<::A>::f` 0 ... ::A::f:: => {} //~ ERROR only char and numeric types are allowed in range } } diff --git a/src/test/compile-fail/unspecified-self-in-trait-ref.rs b/src/test/compile-fail/unspecified-self-in-trait-ref.rs index 2c2f113a7790c..84bcca3fc7bd3 100644 --- a/src/test/compile-fail/unspecified-self-in-trait-ref.rs +++ b/src/test/compile-fail/unspecified-self-in-trait-ref.rs @@ -9,11 +9,11 @@ // except according to those terms. pub trait Foo { - fn foo(); + fn foo(&self); } pub trait Bar { - fn foo(); + fn foo(&self); } fn main() { diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 24b0f90d08e4d..fdb7f9c68b99d 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -40,7 +40,7 @@ (($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: From 6ebc6d8154eb80eef585603a143d1b0008b93e91 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sun, 30 Oct 2016 08:04:52 +0200 Subject: [PATCH 03/12] rustc: track hir::{TraitRef, Visibility} in the HIR map. --- src/librustc/hir/map/collector.rs | 29 ++++++++++++++++++++++------- src/librustc/hir/map/mod.rs | 30 +++++++++++++++++++++++++++--- src/librustc/hir/print.rs | 2 +- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 89217e83ca22e..64bf4bbf08039 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -124,13 +124,6 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { this.insert(struct_def.id(), NodeStructCtor(struct_def)); } } - ItemTrait(.., ref bounds, _) => { - for b in bounds.iter() { - if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b { - this.insert(t.trait_ref.ref_id, NodeItem(i)); - } - } - } ItemUse(ref view_path) => { match view_path.node { ViewPathList(_, ref paths) => { @@ -217,6 +210,14 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { }); } + fn visit_trait_ref(&mut self, tr: &'ast TraitRef) { + self.insert(tr.ref_id, NodeTraitRef(tr)); + + self.with_parent(tr.ref_id, |this| { + intravisit::walk_trait_ref(this, tr); + }); + } + fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl, b: &'ast Expr, s: Span, id: NodeId) { assert_eq!(self.parent_node, id); @@ -234,6 +235,20 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { self.insert(lifetime.id, NodeLifetime(lifetime)); } + fn visit_vis(&mut self, visibility: &'ast Visibility) { + match *visibility { + Visibility::Public | + Visibility::Crate | + Visibility::Inherited => {} + Visibility::Restricted { id, .. } => { + self.insert(id, NodeVisibility(visibility)); + self.with_parent(id, |this| { + intravisit::walk_vis(this, visibility); + }); + } + } + } + fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) { self.insert_entry(macro_def.id, NotPresent); } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index a90577b34261c..7f6c85eeaac8d 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -49,6 +49,7 @@ pub enum Node<'ast> { NodeExpr(&'ast Expr), NodeStmt(&'ast Stmt), NodeTy(&'ast Ty), + NodeTraitRef(&'ast TraitRef), NodeLocal(&'ast Pat), NodePat(&'ast Pat), NodeBlock(&'ast Block), @@ -57,7 +58,8 @@ pub enum Node<'ast> { NodeStructCtor(&'ast VariantData), NodeLifetime(&'ast Lifetime), - NodeTyParam(&'ast TyParam) + NodeTyParam(&'ast TyParam), + NodeVisibility(&'ast Visibility), } /// Represents an entry and its parent NodeID. @@ -76,12 +78,14 @@ pub enum MapEntry<'ast> { EntryExpr(NodeId, &'ast Expr), EntryStmt(NodeId, &'ast Stmt), EntryTy(NodeId, &'ast Ty), + EntryTraitRef(NodeId, &'ast TraitRef), EntryLocal(NodeId, &'ast Pat), EntryPat(NodeId, &'ast Pat), EntryBlock(NodeId, &'ast Block), EntryStructCtor(NodeId, &'ast VariantData), EntryLifetime(NodeId, &'ast Lifetime), EntryTyParam(NodeId, &'ast TyParam), + EntryVisibility(NodeId, &'ast Visibility), /// Roots for node trees. RootCrate, @@ -105,12 +109,14 @@ impl<'ast> MapEntry<'ast> { NodeExpr(n) => EntryExpr(p, n), NodeStmt(n) => EntryStmt(p, n), NodeTy(n) => EntryTy(p, n), + NodeTraitRef(n) => EntryTraitRef(p, n), NodeLocal(n) => EntryLocal(p, n), NodePat(n) => EntryPat(p, n), NodeBlock(n) => EntryBlock(p, n), NodeStructCtor(n) => EntryStructCtor(p, n), NodeLifetime(n) => EntryLifetime(p, n), NodeTyParam(n) => EntryTyParam(p, n), + NodeVisibility(n) => EntryVisibility(p, n), } } @@ -124,12 +130,14 @@ impl<'ast> MapEntry<'ast> { EntryExpr(id, _) => id, EntryStmt(id, _) => id, EntryTy(id, _) => id, + EntryTraitRef(id, _) => id, EntryLocal(id, _) => id, EntryPat(id, _) => id, EntryBlock(id, _) => id, EntryStructCtor(id, _) => id, EntryLifetime(id, _) => id, EntryTyParam(id, _) => id, + EntryVisibility(id, _) => id, NotPresent | RootCrate | @@ -147,12 +155,14 @@ impl<'ast> MapEntry<'ast> { EntryExpr(_, n) => NodeExpr(n), EntryStmt(_, n) => NodeStmt(n), EntryTy(_, n) => NodeTy(n), + EntryTraitRef(_, n) => NodeTraitRef(n), EntryLocal(_, n) => NodeLocal(n), EntryPat(_, n) => NodePat(n), EntryBlock(_, n) => NodeBlock(n), EntryStructCtor(_, n) => NodeStructCtor(n), EntryLifetime(_, n) => NodeLifetime(n), EntryTyParam(_, n) => NodeTyParam(n), + EntryVisibility(_, n) => NodeVisibility(n), _ => return None }) } @@ -266,12 +276,14 @@ impl<'ast> Map<'ast> { EntryExpr(p, _) | EntryStmt(p, _) | EntryTy(p, _) | + EntryTraitRef(p, _) | EntryLocal(p, _) | EntryPat(p, _) | EntryBlock(p, _) | EntryStructCtor(p, _) | EntryLifetime(p, _) | - EntryTyParam(p, _) => + EntryTyParam(p, _) | + EntryVisibility(p, _) => id = p, RootCrate => @@ -307,12 +319,14 @@ impl<'ast> Map<'ast> { EntryExpr(p, _) | EntryStmt(p, _) | EntryTy(p, _) | + EntryTraitRef(p, _) | EntryLocal(p, _) | EntryPat(p, _) | EntryBlock(p, _) | EntryStructCtor(p, _) | EntryLifetime(p, _) | - EntryTyParam(p, _) => + EntryTyParam(p, _) | + EntryVisibility(p, _) => id = p, RootInlinedParent(parent) => match *parent { @@ -707,11 +721,13 @@ impl<'ast> Map<'ast> { Some(NodeExpr(expr)) => expr.span, Some(NodeStmt(stmt)) => stmt.span, Some(NodeTy(ty)) => ty.span, + Some(NodeTraitRef(tr)) => tr.path.span, Some(NodeLocal(pat)) => pat.span, Some(NodePat(pat)) => pat.span, Some(NodeBlock(block)) => block.span, Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span, Some(NodeTyParam(ty_param)) => ty_param.span, + Some(NodeVisibility(&Visibility::Restricted { ref path, .. })) => path.span, _ => return None, }; Some(sp) @@ -926,9 +942,11 @@ impl<'a> NodePrinter for pprust::State<'a> { NodeExpr(a) => self.print_expr(&a), NodeStmt(a) => self.print_stmt(&a), NodeTy(a) => self.print_type(&a), + NodeTraitRef(a) => self.print_trait_ref(&a), NodePat(a) => self.print_pat(&a), NodeBlock(a) => self.print_block(&a), NodeLifetime(a) => self.print_lifetime(&a), + NodeVisibility(a) => self.print_visibility(&a), NodeTyParam(_) => bug!("cannot print TyParam"), // these cases do not carry enough information in the // ast_map to reconstruct their full structure for pretty @@ -1018,6 +1036,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { Some(NodeTy(ref ty)) => { format!("type {}{}", pprust::ty_to_string(&ty), id_str) } + Some(NodeTraitRef(ref tr)) => { + format!("trait_ref {}{}", pprust::path_to_string(&tr.path), id_str) + } Some(NodeLocal(ref pat)) => { format!("local {}{}", pprust::pat_to_string(&pat), id_str) } @@ -1037,6 +1058,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { Some(NodeTyParam(ref ty_param)) => { format!("typaram {:?}{}", ty_param, id_str) } + Some(NodeVisibility(ref vis)) => { + format!("visibility {:?}{}", vis, id_str) + } None => { format!("unknown node{}", id_str) } diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 448139c37e646..f6f40a91bf491 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -845,7 +845,7 @@ impl<'a> State<'a> { self.ann.post(self, NodeItem(item)) } - fn print_trait_ref(&mut self, t: &hir::TraitRef) -> io::Result<()> { + pub fn print_trait_ref(&mut self, t: &hir::TraitRef) -> io::Result<()> { self.print_path(&t.path, false) } From bc096549e84d1edbd051f0b42662c038dd935ff6 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 24 Nov 2016 06:11:31 +0200 Subject: [PATCH 04/12] rustc: desugar `use a::{b,c};` into `use a::b; use a::c;` in HIR. --- src/librustc/hir/intravisit.rs | 29 +-- src/librustc/hir/lowering.rs | 194 +++++++++++------- src/librustc/hir/map/collector.rs | 10 - src/librustc/hir/map/def_collector.rs | 15 +- src/librustc/hir/map/mod.rs | 12 +- src/librustc/hir/mod.rs | 46 ++--- src/librustc/hir/print.rs | 50 ++--- src/librustc/lint/context.rs | 5 - src/librustc/lint/mod.rs | 1 - src/librustc/middle/dead.rs | 5 - src/librustc/middle/reachable.rs | 2 +- src/librustc/middle/resolve_lifetime.rs | 2 +- src/librustc/middle/stability.rs | 14 -- .../calculate_svh/svh_visitor.rs | 13 +- src/librustc_lint/builtin.rs | 8 - src/librustc_lint/lib.rs | 2 +- src/librustc_lint/unused.rs | 10 +- src/librustc_metadata/encoder.rs | 4 +- src/librustc_passes/hir_stats.rs | 6 - src/librustc_typeck/check_unused.rs | 13 +- src/librustc_typeck/collect.rs | 2 +- src/librustc_typeck/variance/constraints.rs | 2 +- src/librustc_typeck/variance/terms.rs | 2 +- src/librustdoc/clean/mod.rs | 72 ++----- src/librustdoc/doctree.rs | 4 +- src/librustdoc/html/format.rs | 27 --- src/librustdoc/visit_ast.rs | 59 ++---- src/test/rustdoc/viewpath-rename.rs | 7 +- src/test/rustdoc/viewpath-self.rs | 7 +- 29 files changed, 228 insertions(+), 395 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 743eed74d0cea..3de788b8c1af1 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -250,9 +250,6 @@ pub trait Visitor<'v> : Sized { fn visit_path(&mut self, path: &'v Path, _id: NodeId) { walk_path(self, path) } - fn visit_path_list_item(&mut self, prefix: &'v Path, item: &'v PathListItem) { - walk_path_list_item(self, prefix, item) - } fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) { walk_path_segment(self, path_span, path_segment) } @@ -352,23 +349,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_id(item.id); walk_opt_name(visitor, item.span, opt_name) } - ItemUse(ref vp) => { + ItemUse(ref path, _) => { visitor.visit_id(item.id); - match vp.node { - ViewPathSimple(name, ref path) => { - visitor.visit_name(vp.span, name); - visitor.visit_path(path, item.id); - } - ViewPathGlob(ref path) => { - visitor.visit_path(path, item.id); - } - ViewPathList(ref prefix, ref list) => { - visitor.visit_path(prefix, item.id); - for item in list { - visitor.visit_path_list_item(prefix, item) - } - } - } + visitor.visit_path(path, item.id); } ItemStatic(ref typ, _, ref expr) | ItemConst(ref typ, ref expr) => { @@ -529,14 +512,6 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) { } } -pub fn walk_path_list_item<'v, V>(visitor: &mut V, _prefix: &'v Path, item: &'v PathListItem) - where V: Visitor<'v>, -{ - visitor.visit_id(item.node.id); - visitor.visit_name(item.span, item.node.name); - walk_opt_name(visitor, item.span, item.node.rename); -} - pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, path_span: Span, segment: &'v PathSegment) { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 056c1b906206a..af0448cc27755 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -55,6 +55,7 @@ use syntax::ptr::P; use syntax::codemap::{respan, Spanned}; use syntax::std_inject; use syntax::symbol::{Symbol, keywords}; +use syntax::util::small_vector::SmallVector; use syntax::visit::{self, Visitor}; use syntax_pos::Span; @@ -67,6 +68,11 @@ pub struct LoweringContext<'a> { // a definition, then we can properly create the def id. parent_def: Option, resolver: &'a mut Resolver, + + /// The items being lowered are collected here. + items: BTreeMap, + + impl_items: BTreeMap, } pub trait Resolver { @@ -98,6 +104,8 @@ pub fn lower_crate(sess: &Session, sess: sess, parent_def: None, resolver: resolver, + items: BTreeMap::new(), + impl_items: BTreeMap::new(), }.lower_crate(krate) } @@ -110,41 +118,35 @@ enum ParamMode { } impl<'a> LoweringContext<'a> { - fn lower_crate(&mut self, c: &Crate) -> hir::Crate { + fn lower_crate(mut self, c: &Crate) -> hir::Crate { struct ItemLowerer<'lcx, 'interner: 'lcx> { - items: BTreeMap, - impl_items: BTreeMap, lctx: &'lcx mut LoweringContext<'interner>, } impl<'lcx, 'interner> Visitor for ItemLowerer<'lcx, 'interner> { fn visit_item(&mut self, item: &Item) { - self.items.insert(item.id, self.lctx.lower_item(item)); + let hir_item = self.lctx.lower_item(item); + self.lctx.items.insert(item.id, hir_item); visit::walk_item(self, item); } fn visit_impl_item(&mut self, item: &ImplItem) { let id = self.lctx.lower_impl_item_ref(item).id; - self.impl_items.insert(id, self.lctx.lower_impl_item(item)); + let hir_item = self.lctx.lower_impl_item(item); + self.lctx.impl_items.insert(id, hir_item); visit::walk_impl_item(self, item); } } - let (items, impl_items) = { - let mut item_lowerer = ItemLowerer { items: BTreeMap::new(), - impl_items: BTreeMap::new(), - lctx: self }; - visit::walk_crate(&mut item_lowerer, c); - (item_lowerer.items, item_lowerer.impl_items) - }; + visit::walk_crate(&mut ItemLowerer { lctx: &mut self }, c); hir::Crate { module: self.lower_mod(&c.module), attrs: self.lower_attrs(&c.attrs), span: c.span, exported_macros: c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect(), - items: items, - impl_items: impl_items, + items: self.items, + impl_items: self.impl_items, } } @@ -183,38 +185,6 @@ impl<'a> LoweringContext<'a> { attrs.clone().into() } - fn lower_view_path(&mut self, view_path: &ViewPath) -> P { - P(Spanned { - node: match view_path.node { - ViewPathSimple(ident, ref path) => { - hir::ViewPathSimple(ident.name, - self.lower_path(path, ParamMode::Explicit)) - } - ViewPathGlob(ref path) => { - hir::ViewPathGlob(self.lower_path(path, ParamMode::Explicit)) - } - ViewPathList(ref path, ref path_list_idents) => { - hir::ViewPathList(self.lower_path(path, ParamMode::Explicit), - path_list_idents.iter() - .map(|item| self.lower_path_list_item(item)) - .collect()) - } - }, - span: view_path.span, - }) - } - - fn lower_path_list_item(&mut self, path_list_ident: &PathListItem) -> hir::PathListItem { - Spanned { - node: hir::PathListItem_ { - id: path_list_ident.node.id, - name: path_list_ident.node.name.name, - rename: path_list_ident.node.rename.map(|rename| rename.name), - }, - span: path_list_ident.span, - } - } - fn lower_arm(&mut self, arm: &Arm) -> hir::Arm { hir::Arm { attrs: self.lower_attrs(&arm.attrs), @@ -382,19 +352,32 @@ impl<'a> LoweringContext<'a> { proj_start, p.segments.len()) } - fn lower_path(&mut self, - p: &Path, - param_mode: ParamMode) - -> hir::Path { + fn lower_path_extra(&mut self, + p: &Path, + name: Option, + param_mode: ParamMode) + -> hir::Path { hir::Path { global: p.global, segments: p.segments.iter().map(|segment| { self.lower_path_segment(segment, param_mode) - }).collect(), + }).chain(name.map(|name| { + hir::PathSegment { + name: name, + parameters: hir::PathParameters::none() + } + })).collect(), span: p.span, } } + fn lower_path(&mut self, + p: &Path, + param_mode: ParamMode) + -> hir::Path { + self.lower_path_extra(p, None, param_mode) + } + fn lower_path_segment(&mut self, segment: &PathSegment, param_mode: ParamMode) @@ -661,12 +644,10 @@ impl<'a> LoweringContext<'a> { } fn lower_block(&mut self, b: &Block) -> P { - let mut stmts = Vec::new(); let mut expr = None; - if let Some((last, rest)) = b.stmts.split_last() { - stmts = rest.iter().map(|s| self.lower_stmt(s)).collect::>(); - let last = self.lower_stmt(last); + let mut stmts = b.stmts.iter().flat_map(|s| self.lower_stmt(s)).collect::>(); + if let Some(last) = stmts.pop() { if let hir::StmtExpr(e, _) = last.node { expr = Some(e); } else { @@ -683,11 +664,65 @@ impl<'a> LoweringContext<'a> { }) } - fn lower_item_kind(&mut self, i: &ItemKind) -> hir::Item_ { + fn lower_item_kind(&mut self, + name: &mut Name, + attrs: &hir::HirVec, + vis: &mut hir::Visibility, + i: &ItemKind) + -> hir::Item_ { match *i { ItemKind::ExternCrate(string) => hir::ItemExternCrate(string), ItemKind::Use(ref view_path) => { - hir::ItemUse(self.lower_view_path(view_path)) + let path = match view_path.node { + ViewPathSimple(_, ref path) => path, + ViewPathGlob(ref path) => path, + ViewPathList(ref path, ref path_list_idents) => { + for &Spanned { node: ref import, span } in path_list_idents { + // `use a::{self as x, b as y};` lowers to + // `use a as x; use a::b as y;` + let mut ident = import.name; + let suffix = if ident.name == keywords::SelfValue.name() { + if let Some(last) = path.segments.last() { + ident = last.identifier; + } + None + } else { + Some(ident.name) + }; + + let mut path = self.lower_path_extra(path, suffix, + ParamMode::Explicit); + path.span = span; + self.items.insert(import.id, hir::Item { + id: import.id, + name: import.rename.unwrap_or(ident).name, + attrs: attrs.clone(), + node: hir::ItemUse(P(path), hir::UseKind::Single), + vis: vis.clone(), + span: span, + }); + } + path + } + }; + let path = P(self.lower_path(path, ParamMode::Explicit)); + let kind = match view_path.node { + ViewPathSimple(ident, _) => { + *name = ident.name; + hir::UseKind::Single + } + ViewPathGlob(_) => { + hir::UseKind::Glob + } + ViewPathList(..) => { + // Privatize the degenerate import base, used only to check + // the stability of `use a::{};`, to avoid it showing up as + // a reexport by accident when `pub`, e.g. in documentation. + *vis = hir::Inherited; + hir::UseKind::ListStem + } + }; + hir::ItemUse(path, kind) } ItemKind::Static(ref t, m, ref e) => { hir::ItemStatic(self.lower_ty(t), @@ -835,7 +870,7 @@ impl<'a> LoweringContext<'a> { fn lower_mod(&mut self, m: &Mod) -> hir::Mod { hir::Mod { inner: m.inner, - item_ids: m.items.iter().map(|x| self.lower_item_id(x)).collect(), + item_ids: m.items.iter().flat_map(|x| self.lower_item_id(x)).collect(), } } @@ -851,21 +886,30 @@ impl<'a> LoweringContext<'a> { } } - fn lower_item_id(&mut self, i: &Item) -> hir::ItemId { - hir::ItemId { id: i.id } + fn lower_item_id(&mut self, i: &Item) -> SmallVector { + if let ItemKind::Use(ref view_path) = i.node { + if let ViewPathList(_, ref imports) = view_path.node { + return iter::once(i.id).chain(imports.iter().map(|import| import.node.id)) + .map(|id| hir::ItemId { id: id }).collect(); + } + } + SmallVector::one(hir::ItemId { id: i.id }) } pub fn lower_item(&mut self, i: &Item) -> hir::Item { + let mut name = i.ident.name; + let attrs = self.lower_attrs(&i.attrs); + let mut vis = self.lower_visibility(&i.vis); let node = self.with_parent_def(i.id, |this| { - this.lower_item_kind(&i.node) + this.lower_item_kind(&mut name, &attrs, &mut vis, &i.node) }); hir::Item { id: i.id, - name: i.ident.name, - attrs: self.lower_attrs(&i.attrs), + name: name, + attrs: attrs, node: node, - vis: self.lower_visibility(&i.vis), + vis: vis, span: i.span, } } @@ -1701,8 +1745,8 @@ impl<'a> LoweringContext<'a> { } } - fn lower_stmt(&mut self, s: &Stmt) -> hir::Stmt { - match s.node { + fn lower_stmt(&mut self, s: &Stmt) -> SmallVector { + SmallVector::one(match s.node { StmtKind::Local(ref l) => Spanned { node: hir::StmtDecl(P(Spanned { node: hir::DeclLocal(self.lower_local(l)), @@ -1710,13 +1754,17 @@ impl<'a> LoweringContext<'a> { }), s.id), span: s.span, }, - StmtKind::Item(ref it) => Spanned { - node: hir::StmtDecl(P(Spanned { - node: hir::DeclItem(self.lower_item_id(it)), + StmtKind::Item(ref it) => { + // Can only use the ID once. + let mut id = Some(s.id); + return self.lower_item_id(it).into_iter().map(|item_id| Spanned { + node: hir::StmtDecl(P(Spanned { + node: hir::DeclItem(item_id), + span: s.span, + }), id.take().unwrap_or_else(|| self.next_id())), span: s.span, - }), s.id), - span: s.span, - }, + }).collect(); + } StmtKind::Expr(ref e) => { Spanned { node: hir::StmtExpr(P(self.lower_expr(e)), s.id), @@ -1730,7 +1778,7 @@ impl<'a> LoweringContext<'a> { } } StmtKind::Mac(..) => panic!("Shouldn't exist here"), - } + }) } fn lower_capture_clause(&mut self, c: CaptureBy) -> hir::CaptureClause { diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 64bf4bbf08039..67e9b24f42d22 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -124,16 +124,6 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { this.insert(struct_def.id(), NodeStructCtor(struct_def)); } } - ItemUse(ref view_path) => { - match view_path.node { - ViewPathList(_, ref paths) => { - for path in paths { - this.insert(path.node.id, NodeItem(i)); - } - } - _ => () - } - } _ => {} } intravisit::walk_item(this, i); diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 7486d954c4802..9d1c7d41faa26 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -155,7 +155,20 @@ impl<'a> visit::Visitor for DefCollector<'a> { DefPathData::ValueNs(i.ident.name.as_str()), ItemKind::Mac(..) if i.id == DUMMY_NODE_ID => return, // Scope placeholder ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false), - ItemKind::Use(..) => DefPathData::Misc, + ItemKind::Use(ref view_path) => { + match view_path.node { + ViewPathGlob(..) => {} + + // FIXME(eddyb) Should use the real name. Which namespace? + ViewPathSimple(..) => {} + ViewPathList(_, ref imports) => { + for import in imports { + self.create_def(import.node.id, DefPathData::Misc); + } + } + } + DefPathData::Misc + } }; let def = self.create_def(i.id, def_data); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 7f6c85eeaac8d..a8986530d1d3d 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -250,16 +250,8 @@ impl<'ast> Map<'ast> { loop { match map[id.as_usize()] { EntryItem(_, item) => { - let def_id = self.local_def_id(item.id); - // NB ^~~~~~~ - // - // You would expect that `item.id == id`, but this - // is not always the case. In particular, for a - // ViewPath item like `use self::{mem, foo}`, we - // map the ids for `mem` and `foo` to the - // enclosing view path item. This seems mega super - // ultra wrong, but then who am I to judge? - // -nmatsakis + assert_eq!(id, item.id); + let def_id = self.local_def_id(id); assert!(!self.is_inlined_def_id(def_id)); return DepNode::Hir(def_id); } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index e9e84eed3e78c..da759b2d4daca 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -27,7 +27,6 @@ pub use self::Ty_::*; pub use self::TyParamBound::*; pub use self::UnOp::*; pub use self::UnsafeSource::*; -pub use self::ViewPath_::*; pub use self::Visibility::{Public, Inherited}; pub use self::PathParameters::*; @@ -1385,32 +1384,20 @@ pub struct Variant_ { pub type Variant = Spanned; -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub struct PathListItem_ { - pub name: Name, - /// renamed in list, eg `use foo::{bar as baz};` - pub rename: Option, - pub id: NodeId, -} - -pub type PathListItem = Spanned; - -pub type ViewPath = Spanned; - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum ViewPath_ { - /// `foo::bar::baz as quux` - /// - /// or just - /// - /// `foo::bar::baz` (with `as baz` implicitly on the right) - ViewPathSimple(Name, Path), +#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum UseKind { + /// One import, e.g. `use foo::bar` or `use foo::bar as baz`. + /// Also produced for each element of a list `use`, e.g. + // `use foo::{a, b}` lowers to `use foo::a; use foo::b;`. + Single, - /// `foo::bar::*` - ViewPathGlob(Path), + /// Glob import, e.g. `use foo::*`. + Glob, - /// `foo::bar::{a,b,c}` - ViewPathList(Path, HirVec), + /// Degenerate list import, e.g. `use foo::{a, b}` produces + /// an additional `use foo::{}` for performing checks such as + /// unstable feature gating. May be removed in the future. + ListStem, } /// TraitRef's appear in impls. @@ -1544,8 +1531,13 @@ pub enum Item_ { /// /// e.g. `extern crate foo` or `extern crate foo_bar as foo` ItemExternCrate(Option), - /// A `use` or `pub use` item - ItemUse(P), + + /// `use foo::bar::*;` or `use foo::bar::baz as quux;` + /// + /// or just + /// + /// `use foo::bar::baz;` (with `as baz` implicitly on the right) + ItemUse(P, UseKind), /// A `static` item ItemStatic(P, Mutability, P), diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index f6f40a91bf491..4dd08def251e9 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -669,10 +669,22 @@ impl<'a> State<'a> { self.end()?; // end inner head-block self.end()?; // end outer head-block } - hir::ItemUse(ref vp) => { + hir::ItemUse(ref path, kind) => { self.head(&visibility_qualified(&item.vis, "use"))?; - self.print_view_path(&vp)?; - word(&mut self.s, ";")?; + self.print_path(path, false)?; + + match kind { + hir::UseKind::Single => { + if path.segments.last().unwrap().name != item.name { + space(&mut self.s)?; + self.word_space("as")?; + self.print_name(item.name)?; + } + word(&mut self.s, ";")?; + } + hir::UseKind::Glob => word(&mut self.s, "::*;")?, + hir::UseKind::ListStem => word(&mut self.s, "::{};")? + } self.end()?; // end inner head-block self.end()?; // end outer head-block } @@ -2153,38 +2165,6 @@ impl<'a> State<'a> { Ok(()) } - 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)?; - - if path.segments.last().unwrap().name != name { - space(&mut self.s)?; - self.word_space("as")?; - self.print_name(name)?; - } - - Ok(()) - } - - hir::ViewPathGlob(ref path) => { - self.print_path(path, false)?; - word(&mut self.s, "::*") - } - - hir::ViewPathList(ref path, ref segments) => { - if path.segments.is_empty() { - word(&mut self.s, "{")?; - } else { - self.print_path(path, false)?; - word(&mut self.s, "::{")?; - } - self.commasep(Inconsistent, &segments[..], |s, w| s.print_name(w.node.name))?; - word(&mut self.s, "}") - } - } - } - pub fn print_mutability(&mut self, mutbl: hir::Mutability) -> io::Result<()> { match mutbl { hir::MutMutable => self.word_nbsp("mut"), diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 4a082944010b2..41c8d413486dc 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -948,11 +948,6 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { hir_visit::walk_path(self, p); } - fn visit_path_list_item(&mut self, prefix: &'tcx hir::Path, item: &'tcx hir::PathListItem) { - run_lints!(self, check_path_list_item, late_passes, item); - hir_visit::walk_path_list_item(self, prefix, item); - } - fn visit_attribute(&mut self, attr: &ast::Attribute) { check_lint_name_attribute(self, attr); run_lints!(self, check_attribute, late_passes, attr); diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 6f7102229f8d6..4e06e0abf0148 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -168,7 +168,6 @@ pub trait LateLintPass: LintPass { fn check_lifetime(&mut self, _: &LateContext, _: &hir::Lifetime) { } fn check_lifetime_def(&mut self, _: &LateContext, _: &hir::LifetimeDef) { } fn check_path(&mut self, _: &LateContext, _: &hir::Path, _: ast::NodeId) { } - fn check_path_list_item(&mut self, _: &LateContext, _: &hir::PathListItem) { } fn check_attribute(&mut self, _: &LateContext, _: &ast::Attribute) { } /// Called when entering a syntax node that can have lint attributes such diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index efbec7bf13b9e..ec064e264ab3c 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -297,11 +297,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { self.lookup_and_handle_definition(id); intravisit::walk_path(self, path); } - - fn visit_path_list_item(&mut self, path: &hir::Path, item: &hir::PathListItem) { - self.lookup_and_handle_definition(item.node.id); - intravisit::walk_path_list_item(self, path, item); - } } fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool { diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 0329b4c4a3019..91c1c63d89063 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -265,7 +265,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { // These are normal, nothing reachable about these // inherently and their children are already in the // worklist, as determined by the privacy pass - hir::ItemExternCrate(_) | hir::ItemUse(_) | + hir::ItemExternCrate(_) | hir::ItemUse(..) | hir::ItemTy(..) | hir::ItemStatic(..) | hir::ItemMod(..) | hir::ItemForeignMod(..) | hir::ItemImpl(..) | hir::ItemTrait(..) | diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index c65fd25950dea..f256d6d9b4f84 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -151,7 +151,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { intravisit::walk_item(this, item); } hir::ItemExternCrate(_) | - hir::ItemUse(_) | + hir::ItemUse(..) | hir::ItemMod(..) | hir::ItemDefaultImpl(..) | hir::ItemForeignMod(..) | diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index a044ffd9a7f85..d7a29e190a8f1 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -474,12 +474,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { intravisit::walk_path(self, path) } - fn visit_path_list_item(&mut self, prefix: &'tcx hir::Path, item: &'tcx hir::PathListItem) { - check_path_list_item(self.tcx, item, - &mut |id, sp, stab, depr| self.check(id, sp, stab, depr)); - intravisit::walk_path_list_item(self, prefix, item) - } - fn visit_pat(&mut self, pat: &'tcx hir::Pat) { check_pat(self.tcx, pat, &mut |id, sp, stab, depr| self.check(id, sp, stab, depr)); @@ -628,14 +622,6 @@ pub fn check_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -pub fn check_path_list_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - item: &hir::PathListItem, - cb: &mut FnMut(DefId, Span, - &Option<&Stability>, - &Option)) { - maybe_do_stability_check(tcx, tcx.expect_def(item.node.id).def_id(), item.span, cb); -} - pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat, cb: &mut FnMut(DefId, Span, &Option<&Stability>, diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index ec40531101259..8c6d8dffa1db5 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -189,7 +189,6 @@ enum SawAbiComponent<'a> { SawPath(bool), SawPathSegment, SawPathParameters, - SawPathListItem, SawBlock, SawPat(SawPatComponent), SawLocal, @@ -357,7 +356,7 @@ fn saw_lit(lit: &ast::Lit) -> SawExprComponent<'static> { #[derive(Hash)] enum SawItemComponent { SawItemExternCrate, - SawItemUse, + SawItemUse(UseKind), SawItemStatic(Mutability), SawItemConst, SawItemFn(Unsafety, Constness, Abi), @@ -375,7 +374,7 @@ enum SawItemComponent { fn saw_item(node: &Item_) -> SawItemComponent { match *node { ItemExternCrate(..) => SawItemExternCrate, - ItemUse(..) => SawItemUse, + ItemUse(_, kind) => SawItemUse(kind), ItemStatic(_, mutability, _) => SawItemStatic(mutability), ItemConst(..) =>SawItemConst, ItemFn(_, unsafety, constness, abi, _, _) => SawItemFn(unsafety, constness, abi), @@ -747,14 +746,6 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has visit::walk_poly_trait_ref(self, t, m) } - fn visit_path_list_item(&mut self, prefix: &'tcx Path, item: &'tcx PathListItem) { - debug!("visit_path_list_item: st={:?}", self.st); - SawPathListItem.hash(self.st); - self.hash_discriminant(&item.node); - hash_span!(self, item.span); - visit::walk_path_list_item(self, prefix, item) - } - fn visit_path_segment(&mut self, path_span: Span, path_segment: &'tcx PathSegment) { debug!("visit_path_segment: st={:?}", self.st); SawPathSegment.hash(self.st); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 7be591293c91b..d91327bc86bf8 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -704,14 +704,6 @@ impl LateLintPass for Deprecated { &mut |id, sp, stab, depr| self.lint(cx, id, sp, &stab, &depr)); } - fn check_path_list_item(&mut self, cx: &LateContext, item: &hir::PathListItem) { - stability::check_path_list_item(cx.tcx, - item, - &mut |id, sp, stab, depr| { - self.lint(cx, id, sp, &stab, &depr) - }); - } - fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) { stability::check_pat(cx.tcx, pat, diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 1a3ea5db871eb..0b92107c81708 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -111,6 +111,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { add_early_builtin!(sess, UnusedParens, + UnusedImportBraces, ); add_early_builtin_with_new!(sess, @@ -129,7 +130,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { NonCamelCaseTypes, NonSnakeCase, NonUpperCaseGlobals, - UnusedImportBraces, NonShorthandFieldPatterns, UnusedUnsafe, UnsafeCode, diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index d0ad682fb58a6..324cbd17ab36b 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -406,11 +406,11 @@ impl LintPass for UnusedImportBraces { } } -impl LateLintPass for UnusedImportBraces { - fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { - if let hir::ItemUse(ref view_path) = item.node { - if let hir::ViewPathList(_, ref items) = view_path.node { - if items.len() == 1 && items[0].node.name != keywords::SelfValue.name() { +impl EarlyLintPass for UnusedImportBraces { + fn check_item(&mut self, cx: &EarlyContext, item: &ast::Item) { + if let ast::ItemKind::Use(ref view_path) = item.node { + if let ast::ViewPathList(_, ref items) = view_path.node { + if items.len() == 1 && items[0].node.name.name != keywords::SelfValue.name() { let msg = format!("braces around {} is unnecessary", items[0].node.name); cx.span_lint(UNUSED_IMPORT_BRACES, item.span, &msg); } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 665f3de0a3ba7..8f3e8a48b1ab5 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -729,7 +729,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { EntryKind::Trait(self.lazy(&data)) } hir::ItemExternCrate(_) | - hir::ItemUse(_) => bug!("cannot encode info for item {:?}", item), + hir::ItemUse(..) => bug!("cannot encode info for item {:?}", item), }; Entry { @@ -982,7 +982,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { let def_id = self.index.tcx.map.local_def_id(item.id); match item.node { hir::ItemExternCrate(_) | - hir::ItemUse(_) => (), // ignore these + hir::ItemUse(..) => (), // ignore these _ => self.index.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)), } self.index.encode_addl_info_for_item(item); diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index 9028821ef116d..ba236ea93a4bc 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -226,12 +226,6 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { self.record("Path", Id::None, path); hir_visit::walk_path(self, path) } - fn visit_path_list_item(&mut self, - prefix: &'v hir::Path, - item: &'v hir::PathListItem) { - self.record("PathListItem", Id::Node(item.node.id), item); - hir_visit::walk_path_list_item(self, prefix, item) - } fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v hir::PathSegment) { diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index b4a10c52270e2..0034a85f8e29e 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -45,17 +45,8 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for UnusedTraitImportVisitor<'a, 'tcx> { if item.vis == hir::Public || item.span == DUMMY_SP { return; } - if let hir::ItemUse(ref path) = item.node { - match path.node { - hir::ViewPathSimple(..) | hir::ViewPathGlob(..) => { - self.check_import(item.id, path.span); - } - hir::ViewPathList(_, ref path_list) => { - for path_item in path_list { - self.check_import(path_item.node.id, path_item.span); - } - } - } + if let hir::ItemUse(ref path, _) = item.node { + self.check_import(item.id, path.span); } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index ca5208b7a035a..b83e453b2de78 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -696,7 +696,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { debug!("convert: item {} with id {}", it.name, it.id); match it.node { // These don't define types. - hir::ItemExternCrate(_) | hir::ItemUse(_) | hir::ItemMod(_) => { + hir::ItemExternCrate(_) | hir::ItemUse(..) | hir::ItemMod(_) => { } hir::ItemForeignMod(ref foreign_mod) => { for item in &foreign_mod.items { diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 8a0c1c68322d0..686d1a4a7716d 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -104,7 +104,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { } hir::ItemExternCrate(_) | - hir::ItemUse(_) | + hir::ItemUse(..) | hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) | diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index 0a3238480d908..851cfcd87231f 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -246,7 +246,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> { } hir::ItemExternCrate(_) | - hir::ItemUse(_) | + hir::ItemUse(..) | hir::ItemDefaultImpl(..) | hir::ItemImpl(..) | hir::ItemStatic(..) | diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index aff384043497e..5e1b12e80d4fb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2589,47 +2589,19 @@ impl Clean> for doctree::Import { None => false, } }); - let (mut ret, inner) = match self.node { - hir::ViewPathGlob(ref p) => { - (vec![], Import::Glob(resolve_use_source(cx, p.clean(cx), self.id))) - } - hir::ViewPathList(ref p, ref list) => { - // Attempt to inline all reexported items, but be sure - // to keep any non-inlineable reexports so they can be - // listed in the documentation. - let mut ret = vec![]; - let remaining = if !denied { - let mut remaining = vec![]; - for path in list { - match inline::try_inline(cx, path.node.id, path.node.rename) { - Some(items) => { - ret.extend(items); - } - None => { - remaining.push(path.clean(cx)); - } - } - } - remaining - } else { - list.clean(cx) - }; - if remaining.is_empty() { - return ret; - } - (ret, Import::List(resolve_use_source(cx, p.clean(cx), self.id), remaining)) - } - hir::ViewPathSimple(name, ref p) => { - if !denied { - if let Some(items) = inline::try_inline(cx, self.id, Some(name)) { - return items; - } + let path = self.path.clean(cx); + let inner = if self.glob { + Import::Glob(resolve_use_source(cx, path, self.id)) + } else { + let name = self.name; + if !denied { + if let Some(items) = inline::try_inline(cx, self.id, Some(name)) { + return items; } - (vec![], Import::Simple(name.clean(cx), - resolve_use_source(cx, p.clean(cx), self.id))) } + Import::Simple(name.clean(cx), resolve_use_source(cx, path, self.id)) }; - ret.push(Item { + vec![Item { name: None, attrs: self.attrs.clean(cx), source: self.whence.clean(cx), @@ -2638,8 +2610,7 @@ impl Clean> for doctree::Import { stability: None, deprecation: None, inner: ImportItem(inner) - }); - ret + }] } } @@ -2648,9 +2619,7 @@ pub enum Import { // use source as str; Simple(String, ImportSource), // use source::*; - Glob(ImportSource), - // use source::{a, b, c}; - List(ImportSource, Vec), + Glob(ImportSource) } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -2659,23 +2628,6 @@ pub struct ImportSource { pub did: Option, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct ViewListIdent { - pub name: String, - pub rename: Option, - pub source: Option, -} - -impl Clean for hir::PathListItem { - fn clean(&self, cx: &DocContext) -> ViewListIdent { - ViewListIdent { - name: self.node.name.clean(cx), - rename: self.node.rename.map(|r| r.clean(cx)), - source: resolve_def(cx, self.node.id) - } - } -} - impl Clean> for hir::ForeignMod { fn clean(&self, cx: &DocContext) -> Vec { let mut items = self.items.clean(cx); diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 609ae0c0e6daf..21fc135eaadae 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -254,10 +254,12 @@ pub struct ExternCrate { } pub struct Import { + pub name: Name, pub id: NodeId, pub vis: hir::Visibility, pub attrs: hir::HirVec, - pub node: hir::ViewPath_, + pub path: hir::Path, + pub glob: bool, pub whence: Span, } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index eef530081abe3..aed41916f5c53 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -969,16 +969,6 @@ impl fmt::Display for clean::Import { clean::Import::Glob(ref src) => { write!(f, "use {}::*;", *src) } - clean::Import::List(ref src, ref names) => { - write!(f, "use {}::{{", *src)?; - for (i, n) in names.iter().enumerate() { - if i > 0 { - write!(f, ", ")?; - } - write!(f, "{}", *n)?; - } - write!(f, "}};") - } } } } @@ -1000,23 +990,6 @@ impl fmt::Display for clean::ImportSource { } } -impl fmt::Display for clean::ViewListIdent { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.source { - Some(did) => { - let path = clean::Path::singleton(self.name.clone()); - resolved_path(f, did, &path, false)?; - } - _ => write!(f, "{}", self.name)?, - } - - if let Some(ref name) = self.rename { - write!(f, " as {}", name)?; - } - Ok(()) - } -} - impl fmt::Display for clean::TypeBinding { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if f.alternate() { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 8ed0567d820ac..fcf747a7c1796 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -225,42 +225,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { om } - fn visit_view_path(&mut self, path: hir::ViewPath_, - om: &mut Module, - id: ast::NodeId, - please_inline: bool) -> Option { - match path { - hir::ViewPathSimple(dst, base) => { - if self.maybe_inline_local(id, Some(dst), false, om, please_inline) { - None - } else { - Some(hir::ViewPathSimple(dst, base)) - } - } - hir::ViewPathList(p, paths) => { - let mine = paths.into_iter().filter(|path| { - !self.maybe_inline_local(path.node.id, path.node.rename, - false, om, please_inline) - }).collect::>(); - - if mine.is_empty() { - None - } else { - Some(hir::ViewPathList(p, mine)) - } - } - - hir::ViewPathGlob(base) => { - if self.maybe_inline_local(id, None, true, om, please_inline) { - None - } else { - Some(hir::ViewPathGlob(base)) - } - } - } - - } - /// Tries to resolve the target of a `pub use` statement and inlines the /// target if it is defined locally and would not be documented otherwise, /// or when it is specifically requested with `please_inline`. @@ -388,11 +352,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { whence: item.span, }) } - hir::ItemUse(ref vpath) => { - let node = vpath.node.clone(); + hir::ItemUse(_, hir::UseKind::ListStem) => {} + hir::ItemUse(ref path, kind) => { + let is_glob = kind == hir::UseKind::Glob; + // If there was a private module in the current path then don't bother inlining // anything as it will probably be stripped anyway. - let node = if item.vis == hir::Public && self.inside_public_path { + if item.vis == hir::Public && self.inside_public_path { let please_inline = item.attrs.iter().any(|item| { match item.meta_item_list() { Some(list) if item.check_name("doc") => { @@ -401,18 +367,19 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { _ => false, } }); - match self.visit_view_path(node, om, item.id, please_inline) { - None => return, - Some(p) => p + let name = if is_glob { None } else { Some(name) }; + if self.maybe_inline_local(item.id, name, is_glob, om, please_inline) { + return; } - } else { - node - }; + } + om.imports.push(Import { + name: item.name, id: item.id, vis: item.vis.clone(), attrs: item.attrs.clone(), - node: node, + path: (**path).clone(), + glob: is_glob, whence: item.span, }); } diff --git a/src/test/rustdoc/viewpath-rename.rs b/src/test/rustdoc/viewpath-rename.rs index ccc0acab7f379..4b6843d33f7ac 100644 --- a/src/test/rustdoc/viewpath-rename.rs +++ b/src/test/rustdoc/viewpath-rename.rs @@ -21,8 +21,11 @@ pub enum Maybe { // @has foo/prelude/index.html pub mod prelude { - // @has foo/prelude/index.html '//code' 'pub use io::{self as FooIo, Reader as FooReader}' + // @has foo/prelude/index.html '//code' 'pub use io as FooIo;' + // @has foo/prelude/index.html '//code' 'pub use io::Reader as FooReader;' #[doc(no_inline)] pub use io::{self as FooIo, Reader as FooReader}; - // @has foo/prelude/index.html '//code' 'pub use Maybe::{self, Just as MaybeJust, Nothing}' + // @has foo/prelude/index.html '//code' 'pub use Maybe;' + // @has foo/prelude/index.html '//code' 'pub use Maybe::Just as MaybeJust;' + // @has foo/prelude/index.html '//code' 'pub use Maybe::Nothing;' #[doc(no_inline)] pub use Maybe::{self, Just as MaybeJust, Nothing}; } diff --git a/src/test/rustdoc/viewpath-self.rs b/src/test/rustdoc/viewpath-self.rs index 65a981353f0df..000960ad972ab 100644 --- a/src/test/rustdoc/viewpath-self.rs +++ b/src/test/rustdoc/viewpath-self.rs @@ -21,8 +21,11 @@ pub enum Maybe { // @has foo/prelude/index.html pub mod prelude { - // @has foo/prelude/index.html '//code' 'pub use io::{self, Reader}' + // @has foo/prelude/index.html '//code' 'pub use io;' + // @has foo/prelude/index.html '//code' 'pub use io::Reader;' #[doc(no_inline)] pub use io::{self, Reader}; - // @has foo/prelude/index.html '//code' 'pub use Maybe::{self, Just, Nothing}' + // @has foo/prelude/index.html '//code' 'pub use Maybe;' + // @has foo/prelude/index.html '//code' 'pub use Maybe::Just;' + // @has foo/prelude/index.html '//code' 'pub use Maybe::Nothing;' #[doc(no_inline)] pub use Maybe::{self, Just, Nothing}; } From 962633cdbbe2ce87c1311edbaa0d4e0aca022b6d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 25 Nov 2016 13:21:19 +0200 Subject: [PATCH 05/12] rustc: embed path resolutions into the HIR instead of keeping DefMap. --- src/librustc/cfg/construct.rs | 27 +- src/librustc/hir/def.rs | 8 - src/librustc/hir/intravisit.rs | 22 +- src/librustc/hir/lowering.rs | 260 +++++++++--------- src/librustc/hir/map/def_collector.rs | 2 +- src/librustc/hir/map/mod.rs | 2 +- src/librustc/hir/mod.rs | 45 +-- src/librustc/hir/pat_util.rs | 245 ++++++++--------- src/librustc/hir/print.rs | 16 +- src/librustc/infer/error_reporting.rs | 3 +- src/librustc/middle/astconv_util.rs | 2 +- src/librustc/middle/dead.rs | 33 +-- src/librustc/middle/effect.rs | 4 +- src/librustc/middle/expr_use_visitor.rs | 30 +- src/librustc/middle/intrinsicck.rs | 9 +- src/librustc/middle/liveness.rs | 59 ++-- src/librustc/middle/mem_categorization.rs | 37 ++- src/librustc/middle/reachable.rs | 59 ++-- src/librustc/middle/resolve_lifetime.rs | 12 +- src/librustc/middle/stability.rs | 25 +- src/librustc/ty/context.rs | 23 +- src/librustc/ty/mod.rs | 26 +- src/librustc/ty/util.rs | 9 - .../borrowck/gather_loans/gather_moves.rs | 2 +- src/librustc_const_eval/_match.rs | 11 +- src/librustc_const_eval/check_match.rs | 50 ++-- src/librustc_const_eval/eval.rs | 74 ++--- src/librustc_const_eval/pattern.rs | 32 +-- src/librustc_driver/driver.rs | 9 +- src/librustc_driver/test.rs | 3 +- .../calculate_svh/svh_visitor.rs | 20 +- src/librustc_lint/bad_style.rs | 15 +- src/librustc_lint/builtin.rs | 37 ++- src/librustc_lint/unused.rs | 3 +- src/librustc_metadata/astencode.rs | 11 +- src/librustc_metadata/encoder.rs | 2 +- src/librustc_mir/build/mod.rs | 4 +- src/librustc_mir/hair/cx/expr.rs | 46 ++-- src/librustc_passes/consts.rs | 20 +- src/librustc_passes/loops.rs | 19 +- src/librustc_passes/static_recursion.rs | 19 +- src/librustc_privacy/lib.rs | 78 +++--- src/librustc_resolve/lib.rs | 7 +- src/librustc_save_analysis/dump_visitor.rs | 20 +- src/librustc_save_analysis/lib.rs | 48 +++- src/librustc_typeck/astconv.rs | 93 +++---- src/librustc_typeck/check/_match.rs | 18 +- src/librustc_typeck/check/callee.rs | 14 +- src/librustc_typeck/check/mod.rs | 138 ++++------ src/librustc_typeck/check/regionck.rs | 3 +- src/librustc_typeck/collect.rs | 10 +- src/librustdoc/clean/inline.rs | 19 +- src/librustdoc/clean/mod.rs | 45 +-- src/librustdoc/visit_ast.rs | 22 +- src/test/compile-fail/issue-3521.rs | 2 +- 55 files changed, 927 insertions(+), 925 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 609d492a93aec..f21d98a0fc7f9 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -10,8 +10,6 @@ use rustc_data_structures::graph; use cfg::*; -use hir::def::Def; -use hir::pat_util; use ty::{self, TyCtxt}; use syntax::ast; use syntax::ptr::P; @@ -284,7 +282,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { hir::ExprBreak(label, ref opt_expr) => { let v = self.opt_expr(opt_expr, pred); - let loop_scope = self.find_scope(expr, label.map(|l| l.node)); + let loop_scope = self.find_scope(expr, label); let b = self.add_ast_node(expr.id, &[v]); self.add_exiting_edge(expr, b, loop_scope, loop_scope.break_index); @@ -292,7 +290,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } hir::ExprAgain(label) => { - let loop_scope = self.find_scope(expr, label.map(|l| l.node)); + let loop_scope = self.find_scope(expr, label); let a = self.add_ast_node(expr.id, &[pred]); self.add_exiting_edge(expr, a, loop_scope, loop_scope.continue_index); @@ -457,7 +455,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // Visit the guard expression let guard_exit = self.expr(&guard, guard_start); - let this_has_bindings = pat_util::pat_contains_bindings_or_wild(&pat); + let this_has_bindings = pat.contains_bindings_or_wild(); // If both this pattern and the previous pattern // were free of bindings, they must consist only @@ -570,23 +568,16 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { fn find_scope(&self, expr: &hir::Expr, - label: Option) -> LoopScope { - if label.is_none() { - return *self.loop_scopes.last().unwrap(); - } - - match self.tcx.expect_def(expr.id) { - Def::Label(loop_id) => { + label: Option) -> LoopScope { + match label { + None => *self.loop_scopes.last().unwrap(), + Some(label) => { for l in &self.loop_scopes { - if l.loop_id == loop_id { + if l.loop_id == label.loop_id { return *l; } } - span_bug!(expr.span, "no loop scope for id {}", loop_id); - } - - r => { - span_bug!(expr.span, "bad entry `{:?}` in def_map for label", r); + span_bug!(expr.span, "no loop scope for id {}", label.loop_id); } } } diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index feefc43f4013e..b6fce2d6ca0be 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -83,14 +83,6 @@ impl PathResolution { PathResolution { base_def: def, depth: 0 } } - /// Get the definition, if fully resolved, otherwise panic. - pub fn full_def(&self) -> Def { - if self.depth != 0 { - bug!("path not fully resolved: {:?}", self); - } - self.base_def - } - pub fn kind_name(&self) -> &'static str { if self.depth != 0 { "associated item" diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 3de788b8c1af1..94da10d33f818 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -38,6 +38,7 @@ use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute}; use syntax::codemap::Spanned; use syntax_pos::Span; use hir::*; +use hir::def::Def; use hir::map::Map; use super::itemlikevisit::DeepVisitor; @@ -155,6 +156,9 @@ pub trait Visitor<'v> : Sized { fn visit_id(&mut self, _node_id: NodeId) { // Nothing to do. } + fn visit_def_mention(&mut self, _def: Def) { + // Nothing to do. + } fn visit_name(&mut self, _span: Span, _name: Name) { // Nothing to do. } @@ -507,6 +511,7 @@ pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath, id: Nod } pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) { + visitor.visit_def_mention(path.def); for segment in &path.segments { visitor.visit_path_segment(path.span, segment); } @@ -566,7 +571,8 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { PatKind::Ref(ref subpattern, _) => { visitor.visit_pat(subpattern) } - PatKind::Binding(_, ref pth1, ref optional_subpattern) => { + PatKind::Binding(_, def_id, ref pth1, ref optional_subpattern) => { + visitor.visit_def_mention(Def::Local(def_id)); visitor.visit_name(pth1.span, pth1.node); walk_list!(visitor, visit_pat, optional_subpattern); } @@ -907,12 +913,18 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { 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); + ExprBreak(None, ref opt_expr) => { walk_list!(visitor, visit_expr, opt_expr); } - ExprAgain(ref opt_sp_name) => { - walk_opt_sp_name(visitor, opt_sp_name); + ExprBreak(Some(label), ref opt_expr) => { + visitor.visit_def_mention(Def::Label(label.loop_id)); + visitor.visit_name(label.span, label.name); + walk_list!(visitor, visit_expr, opt_expr); + } + ExprAgain(None) => {} + ExprAgain(Some(label)) => { + visitor.visit_def_mention(Def::Label(label.loop_id)); + visitor.visit_name(label.span, label.name); } ExprRet(ref optional_expression) => { walk_list!(visitor, visit_expr, optional_expression); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index af0448cc27755..aea05357a8488 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -77,7 +77,7 @@ pub struct LoweringContext<'a> { pub trait Resolver { // Resolve a global hir path generated by the lowerer when expanding `for`, `if let`, etc. - fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) -> Def; + fn resolve_generated_global_path(&mut self, path: &mut hir::Path, is_value: bool); // Obtain the resolution for a node id fn get_resolution(&mut self, id: NodeId) -> Option; @@ -154,6 +154,15 @@ impl<'a> LoweringContext<'a> { self.sess.next_node_id() } + fn expect_full_def(&mut self, id: NodeId) -> Def { + self.resolver.get_resolution(id).map_or(Def::Err, |pr| { + if pr.depth != 0 { + bug!("path not fully resolved: {:?}", pr); + } + pr.base_def + }) + } + fn diagnostic(&self) -> &errors::Handler { self.sess.diagnostic() } @@ -181,6 +190,19 @@ impl<'a> LoweringContext<'a> { o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name)) } + fn lower_label(&mut self, id: NodeId, label: Option>) -> Option { + label.map(|sp_ident| { + hir::Label { + span: sp_ident.span, + name: sp_ident.node.name, + loop_id: match self.expect_full_def(id) { + Def::Label(loop_id) => loop_id, + _ => DUMMY_NODE_ID + } + } + }) + } + fn lower_attrs(&mut self, attrs: &Vec) -> hir::HirVec { attrs.clone().into() } @@ -286,6 +308,7 @@ impl<'a> LoweringContext<'a> { let proj_start = p.segments.len() - resolution.depth; let path = P(hir::Path { global: p.global, + def: resolution.base_def, segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| { let param_mode = match (qself_position, param_mode) { (Some(j), ParamMode::Optional) if i < j => { @@ -353,12 +376,14 @@ impl<'a> LoweringContext<'a> { } fn lower_path_extra(&mut self, + id: NodeId, p: &Path, name: Option, param_mode: ParamMode) -> hir::Path { hir::Path { global: p.global, + def: self.expect_full_def(id), segments: p.segments.iter().map(|segment| { self.lower_path_segment(segment, param_mode) }).chain(name.map(|name| { @@ -372,10 +397,11 @@ impl<'a> LoweringContext<'a> { } fn lower_path(&mut self, + id: NodeId, p: &Path, param_mode: ParamMode) -> hir::Path { - self.lower_path_extra(p, None, param_mode) + self.lower_path_extra(id, p, None, param_mode) } fn lower_path_segment(&mut self, @@ -569,7 +595,7 @@ impl<'a> LoweringContext<'a> { span}) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { id: id, - path: self.lower_path(path, ParamMode::Explicit), + path: self.lower_path(id, path, ParamMode::Explicit), ty: self.lower_ty(ty), span: span, }) @@ -599,7 +625,7 @@ impl<'a> LoweringContext<'a> { fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef { hir::TraitRef { - path: self.lower_path(&p.path, ParamMode::Explicit), + path: self.lower_path(p.ref_id, &p.path, ParamMode::Explicit), ref_id: p.ref_id, } } @@ -665,6 +691,7 @@ impl<'a> LoweringContext<'a> { } fn lower_item_kind(&mut self, + id: NodeId, name: &mut Name, attrs: &hir::HirVec, vis: &mut hir::Visibility, @@ -690,7 +717,7 @@ impl<'a> LoweringContext<'a> { Some(ident.name) }; - let mut path = self.lower_path_extra(path, suffix, + let mut path = self.lower_path_extra(import.id, path, suffix, ParamMode::Explicit); path.span = span; self.items.insert(import.id, hir::Item { @@ -705,7 +732,7 @@ impl<'a> LoweringContext<'a> { path } }; - let path = P(self.lower_path(path, ParamMode::Explicit)); + let path = P(self.lower_path(id, path, ParamMode::Explicit)); let kind = match view_path.node { ViewPathSimple(ident, _) => { *name = ident.name; @@ -901,7 +928,7 @@ impl<'a> LoweringContext<'a> { let attrs = self.lower_attrs(&i.attrs); let mut vis = self.lower_visibility(&i.vis); let node = self.with_parent_def(i.id, |this| { - this.lower_item_kind(&mut name, &attrs, &mut vis, &i.node) + this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node) }); hir::Item { @@ -1012,14 +1039,24 @@ impl<'a> LoweringContext<'a> { self.with_parent_def(p.id, |this| { match this.resolver.get_resolution(p.id).map(|d| d.base_def) { // `None` can occur in body-less function signatures - None | Some(Def::Local(..)) => { + def @ None | def @ Some(Def::Local(_)) => { + let def_id = def.map(|d| d.def_id()).unwrap_or_else(|| { + this.resolver.definitions().local_def_id(p.id) + }); hir::PatKind::Binding(this.lower_binding_mode(binding_mode), + def_id, respan(pth1.span, pth1.node.name), sub.as_ref().map(|x| this.lower_pat(x))) } - _ => { - let path = hir::Path::from_name(pth1.span, pth1.node.name); - hir::PatKind::Path(hir::QPath::Resolved(None, P(path))) + Some(def) => { + hir::PatKind::Path(hir::QPath::Resolved(None, P(hir::Path { + span: pth1.span, + global: false, + def: def, + segments: hir_vec![ + hir::PathSegment::from_name(pth1.node.name) + ], + }))) } } }) @@ -1120,8 +1157,7 @@ impl<'a> LoweringContext<'a> { let inplace_finalize = ["ops", "InPlace", "finalize"]; let make_call = |this: &mut LoweringContext, p, args| { - let path = this.std_path(e.span, p); - let path = this.expr_path(path, ThinVec::new()); + let path = this.expr_std_path(e.span, p, ThinVec::new()); P(this.expr_call(e.span, path, args)) }; @@ -1315,13 +1351,12 @@ impl<'a> LoweringContext<'a> { ast_expr: &Expr, path: &[&str], fields: &[(&str, &P)]) -> hir::Expr { - let struct_path = this.std_path(ast_expr.span, - &iter::once(&"ops").chain(path) - .map(|s| *s) - .collect::>()); + let struct_path = &iter::once(&"ops").chain(path).map(|s| *s) + .collect::>(); let hir_expr = if fields.len() == 0 { - this.expr_path(struct_path, ast_expr.attrs.clone()) + this.expr_std_path(ast_expr.span, struct_path, + ast_expr.attrs.clone()) } else { let fields = fields.into_iter().map(|&(s, e)| { let expr = P(this.lower_expr(&e)); @@ -1334,7 +1369,7 @@ impl<'a> LoweringContext<'a> { }).collect(); let attrs = ast_expr.attrs.clone(); - this.expr_struct(ast_expr.span, struct_path, fields, None, attrs) + this.expr_std_struct(ast_expr.span, struct_path, fields, None, attrs) }; this.signal_block_expr(hir_vec![], @@ -1378,10 +1413,10 @@ impl<'a> LoweringContext<'a> { 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), + hir::ExprBreak(self.lower_label(e.id, opt_ident), opt_expr.as_ref().map(|x| P(self.lower_expr(x)))) } - ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_opt_sp_ident(opt_ident)), + ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_label(e.id, opt_ident)), ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| P(self.lower_expr(x)))), ExprKind::InlineAsm(ref asm) => { let hir_asm = hir::InlineAsm { @@ -1608,10 +1643,10 @@ impl<'a> LoweringContext<'a> { // `match ::std::iter::Iterator::next(&mut iter) { ... }` let match_expr = { - let next_path = self.std_path(e.span, &["iter", "Iterator", "next"]); let iter = P(self.expr_ident(e.span, iter, iter_pat.id)); let ref_mut_iter = self.expr_mut_addr_of(e.span, iter); - let next_path = self.expr_path(next_path, ThinVec::new()); + let next_path = &["iter", "Iterator", "next"]; + let next_path = self.expr_std_path(e.span, next_path, ThinVec::new()); let next_expr = P(self.expr_call(e.span, next_path, hir_vec![ref_mut_iter])); let arms = hir_vec![pat_arm, break_arm]; @@ -1638,10 +1673,8 @@ impl<'a> LoweringContext<'a> { // `match ::std::iter::IntoIterator::into_iter() { ... }` let into_iter_expr = { - let into_iter_path = self.std_path(e.span, - &["iter", "IntoIterator", "into_iter"]); - - let into_iter = self.expr_path(into_iter_path, ThinVec::new()); + let into_iter_path = &["iter", "IntoIterator", "into_iter"]; + let into_iter = self.expr_std_path(e.span, into_iter_path, ThinVec::new()); P(self.expr_call(e.span, into_iter, hir_vec![head])) }; @@ -1684,8 +1717,8 @@ impl<'a> LoweringContext<'a> { hir::PopUnstableBlock, ThinVec::new()); - let path = self.std_path(e.span, &["ops", "Carrier", "translate"]); - let path = self.expr_path(path, ThinVec::new()); + let path = &["ops", "Carrier", "translate"]; + let path = self.expr_std_path(e.span,path, ThinVec::new()); let call = P(self.expr_call(e.span, path, hir_vec![sub_expr])); P(self.signal_block_expr(hir_vec![], @@ -1710,15 +1743,15 @@ impl<'a> LoweringContext<'a> { let err_ident = self.str_to_ident("err"); let err_local = self.pat_ident(e.span, err_ident); let from_expr = { - let path = self.std_path(e.span, &["convert", "From", "from"]); - let from = self.expr_path(path, ThinVec::new()); + let path = &["convert", "From", "from"]; + let from = self.expr_std_path(e.span, path, ThinVec::new()); let err_expr = self.expr_ident(e.span, err_ident, err_local.id); self.expr_call(e.span, from, hir_vec![err_expr]) }; let from_err_expr = { - let path = self.std_path(e.span, &["ops", "Carrier", "from_error"]); - let from_err = self.expr_path(path, ThinVec::new()); + let path = &["ops", "Carrier", "from_error"]; + let from_err = self.expr_std_path(e.span, path, ThinVec::new()); P(self.expr_call(e.span, from_err, hir_vec![from_expr])) }; @@ -1794,7 +1827,7 @@ impl<'a> LoweringContext<'a> { Visibility::Crate(_) => hir::Visibility::Crate, Visibility::Restricted { ref path, id } => { hir::Visibility::Restricted { - path: P(self.lower_path(path, ParamMode::Explicit)), + path: P(self.lower_path(id, path, ParamMode::Explicit)), id: id } } @@ -1880,14 +1913,18 @@ impl<'a> LoweringContext<'a> { } fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> hir::Expr { - 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 = { let defs = self.resolver.definitions(); Def::Local(defs.local_def_id(binding)) }; + + let expr_path = hir::ExprPath(hir::QPath::Resolved(None, P(hir::Path { + span: span, + global: false, + def: def, + segments: hir_vec![hir::PathSegment::from_name(id)], + }))); + let expr = self.expr(span, expr_path, ThinVec::new()); self.resolver.record_resolution(expr.id, def); expr @@ -1897,9 +1934,14 @@ impl<'a> LoweringContext<'a> { self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), ThinVec::new()) } - fn expr_path(&mut self, path: hir::Path, attrs: ThinVec) -> P { - let def = self.resolver.resolve_generated_global_path(&path, true); - let expr = self.expr(path.span, hir::ExprPath(hir::QPath::Resolved(None, P(path))), attrs); + fn expr_std_path(&mut self, + span: Span, + components: &[&str], + attrs: ThinVec) + -> P { + let path = self.std_path(span, components, true); + let def = path.def; + let expr = self.expr(span, hir::ExprPath(hir::QPath::Resolved(None, P(path))), attrs); self.resolver.record_resolution(expr.id, def); P(expr) } @@ -1921,15 +1963,16 @@ impl<'a> LoweringContext<'a> { P(self.expr(sp, hir::ExprTup(exprs), ThinVec::new())) } - fn expr_struct(&mut self, - sp: Span, - path: hir::Path, - fields: hir::HirVec, - e: Option>, - attrs: ThinVec) -> P { - let def = self.resolver.resolve_generated_global_path(&path, false); + fn expr_std_struct(&mut self, + span: Span, + components: &[&str], + fields: hir::HirVec, + e: Option>, + attrs: ThinVec) -> P { + let path = self.std_path(span, components, false); + let def = path.def; let qpath = hir::QPath::Resolved(None, P(path)); - let expr = self.expr(sp, hir::ExprStruct(qpath, fields, e), attrs); + let expr = self.expr(span, hir::ExprStruct(qpath, fields, e), attrs); self.resolver.record_resolution(expr.id, def); P(expr) } @@ -1988,28 +2031,28 @@ impl<'a> LoweringContext<'a> { } fn pat_ok(&mut self, span: Span, pat: P) -> P { - let path = self.std_path(span, &["result", "Result", "Ok"]); - self.pat_enum(span, path, hir_vec![pat]) + self.pat_std_enum(span, &["result", "Result", "Ok"], hir_vec![pat]) } fn pat_err(&mut self, span: Span, pat: P) -> P { - let path = self.std_path(span, &["result", "Result", "Err"]); - self.pat_enum(span, path, hir_vec![pat]) + self.pat_std_enum(span, &["result", "Result", "Err"], hir_vec![pat]) } fn pat_some(&mut self, span: Span, pat: P) -> P { - let path = self.std_path(span, &["option", "Option", "Some"]); - self.pat_enum(span, path, hir_vec![pat]) + self.pat_std_enum(span, &["option", "Option", "Some"], hir_vec![pat]) } fn pat_none(&mut self, span: Span) -> P { - let path = self.std_path(span, &["option", "Option", "None"]); - self.pat_enum(span, path, hir_vec![]) + self.pat_std_enum(span, &["option", "Option", "None"], hir_vec![]) } - fn pat_enum(&mut self, span: Span, path: hir::Path, subpats: hir::HirVec>) - -> P { - let def = self.resolver.resolve_generated_global_path(&path, true); + fn pat_std_enum(&mut self, + span: Span, + components: &[&str], + subpats: hir::HirVec>) + -> P { + let path = self.std_path(span, components, true); + let def = path.def; let qpath = hir::QPath::Resolved(None, P(path)); let pt = if subpats.is_empty() { hir::PatKind::Path(qpath) @@ -2027,25 +2070,27 @@ impl<'a> LoweringContext<'a> { fn pat_ident_binding_mode(&mut self, span: Span, name: Name, bm: hir::BindingMode) -> P { - let pat_ident = hir::PatKind::Binding(bm, - Spanned { - span: span, - node: name, - }, - None); - - let pat = self.pat(span, pat_ident); - + let id = self.next_id(); let parent_def = self.parent_def; - let def = { + let def_id = { let defs = self.resolver.definitions(); let def_path_data = DefPathData::Binding(name.as_str()); - let def_index = defs.create_def_with_parent(parent_def, pat.id, def_path_data); - Def::Local(DefId::local(def_index)) + let def_index = defs.create_def_with_parent(parent_def, id, def_path_data); + DefId::local(def_index) }; - self.resolver.record_resolution(pat.id, def); + self.resolver.record_resolution(id, Def::Local(def_id)); - pat + P(hir::Pat { + id: id, + node: hir::PatKind::Binding(bm, + def_id, + Spanned { + span: span, + node: name, + }, + None), + span: span, + }) } fn pat_wild(&mut self, span: Span) -> P { @@ -2060,64 +2105,25 @@ impl<'a> LoweringContext<'a> { }) } - fn path_ident(&mut self, span: Span, id: Name) -> hir::Path { - self.path(span, vec![id]) - } - - fn path(&mut self, span: Span, strs: Vec) -> hir::Path { - self.path_all(span, false, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new()) - } - - fn path_global(&mut self, span: Span, strs: Vec) -> hir::Path { - self.path_all(span, true, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new()) - } + /// Given suffix ["b","c","d"], returns path `::std::b::c::d` when + /// `fld.cx.use_std`, and `::core::b::c::d` otherwise. + /// The path is also resolved according to `is_value`. + fn std_path(&mut self, span: Span, components: &[&str], is_value: bool) -> hir::Path { + let idents = self.crate_root.iter().chain(components); - fn path_all(&mut self, - sp: Span, - global: bool, - mut names: Vec, - lifetimes: hir::HirVec, - types: hir::HirVec>, - bindings: hir::HirVec) - -> hir::Path { - let last_identifier = names.pop().unwrap(); - let mut segments: Vec = names.into_iter().map(|name| { - hir::PathSegment { - name: name, - parameters: hir::PathParameters::none(), - } + let segments: Vec<_> = idents.map(|name| { + hir::PathSegment::from_name(Symbol::intern(name)) }).collect(); - segments.push(hir::PathSegment { - name: last_identifier, - parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData { - lifetimes: lifetimes, - types: types, - infer_types: true, - bindings: bindings, - }), - }); - hir::Path { - span: sp, - global: global, + let mut path = hir::Path { + span: span, + global: true, + def: Def::Err, segments: segments.into(), - } - } - - fn std_path_components(&mut self, components: &[&str]) -> Vec { - let mut v = Vec::new(); - if let Some(s) = self.crate_root { - v.push(Symbol::intern(s)); - } - v.extend(components.iter().map(|s| Symbol::intern(s))); - return v; - } + }; - // Given suffix ["b","c","d"], returns path `::std::b::c::d` when - // `fld.cx.use_std`, and `::core::b::c::d` otherwise. - fn std_path(&mut self, span: Span, components: &[&str]) -> hir::Path { - let idents = self.std_path_components(components); - self.path_global(span, idents) + self.resolver.resolve_generated_global_path(&mut path, is_value); + path } fn signal_block_expr(&mut self, diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 9d1c7d41faa26..a08060e792778 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -436,7 +436,7 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> { fn visit_pat(&mut self, pat: &'ast hir::Pat) { let parent_def = self.parent_def; - if let hir::PatKind::Binding(_, name, _) = pat.node { + if let hir::PatKind::Binding(_, _, name, _) = pat.node { let def = self.create_def(pat.id, DefPathData::Binding(name.node.as_str())); self.parent_def = Some(def); } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index a8986530d1d3d..c4ed98ce6e070 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -658,7 +658,7 @@ impl<'ast> Map<'ast> { NodeVariant(v) => v.node.name, NodeLifetime(lt) => lt.name, NodeTyParam(tp) => tp.name, - NodeLocal(&Pat { node: PatKind::Binding(_,l,_), .. }) => l.node, + NodeLocal(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.node, NodeStructCtor(_) => self.name(self.get_parent(id)), _ => bug!("no name for {}", self.node_to_string(id)) } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index da759b2d4daca..1e70ebf585189 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -107,6 +107,8 @@ pub struct Path { /// A `::foo` path, is relative to the crate root rather than current /// module (like paths in an import). pub global: bool, + /// The definition that the path resolved to. + pub def: Def, /// The segments in the path: the things separated by `::`. pub segments: HirVec, } @@ -123,21 +125,6 @@ impl fmt::Display for Path { } } -impl Path { - /// Convert a span and an identifier to the corresponding - /// 1-segment path. - pub fn from_name(s: Span, name: Name) -> Path { - Path { - span: s, - global: false, - segments: hir_vec![PathSegment { - name: name, - parameters: PathParameters::none() - }], - } - } -} - /// A segment of a path: an identifier, an optional lifetime, and a set of /// types. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] @@ -153,6 +140,16 @@ pub struct PathSegment { pub parameters: PathParameters, } +impl PathSegment { + /// Convert an identifier to the corresponding segment. + pub fn from_name(name: Name) -> PathSegment { + PathSegment { + name: name, + parameters: PathParameters::none() + } + } +} + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum PathParameters { /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>` @@ -571,7 +568,8 @@ pub enum PatKind { Wild, /// A fresh binding `ref mut binding @ OPT_SUBPATTERN`. - Binding(BindingMode, Spanned, Option>), + /// The `DefId` is for the definition of the variable being bound. + Binding(BindingMode, DefId, Spanned, Option>), /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`. /// The `bool` is `true` in the presence of a `..`. @@ -944,9 +942,9 @@ pub enum Expr_ { /// A referencing operation (`&a` or `&mut a`) ExprAddrOf(Mutability, P), /// A `break`, with an optional label to break - ExprBreak(Option>, Option>), + ExprBreak(Option