From 494859e8dde5080534e94aba6d98affb921552f8 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 8 Feb 2018 08:58:13 +0000 Subject: [PATCH] Consolidate PathParameters and AngleBracketedParameterData --- src/librustc/hir/intravisit.rs | 4 +- src/librustc/hir/lowering.rs | 59 ++++++------- src/librustc/hir/mod.rs | 40 +++++++-- src/librustc/hir/print.rs | 44 ++++++---- src/librustc/ich/impls_hir.rs | 8 +- src/librustc/middle/resolve_lifetime.rs | 18 ++-- src/librustc/ty/mod.rs | 95 +++++++++++++++++++++ src/librustc_driver/pretty.rs | 2 +- src/librustc_save_analysis/dump_visitor.rs | 4 +- src/librustc_typeck/astconv.rs | 42 ++++----- src/librustc_typeck/check/method/confirm.rs | 5 +- src/librustc_typeck/check/mod.rs | 14 +-- src/librustc_typeck/collect.rs | 7 ++ src/libsyntax/ast.rs | 34 +++++++- src/libsyntax/ext/build.rs | 33 +++---- src/libsyntax/fold.rs | 22 ++++- src/libsyntax/parse/parser.rs | 20 +++-- src/libsyntax/print/pprust.rs | 29 +++---- src/libsyntax/visit.rs | 4 +- src/libsyntax_ext/deriving/clone.rs | 3 +- src/libsyntax_ext/deriving/cmp/eq.rs | 4 +- src/libsyntax_ext/deriving/generic/mod.rs | 17 ++-- src/libsyntax_ext/deriving/generic/ty.rs | 26 ++++-- src/libsyntax_ext/env.rs | 5 +- 24 files changed, 364 insertions(+), 175 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 12ccb329e06..79b433e3cb2 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -650,8 +650,8 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V, _path_span: Span, path_parameters: &'v PathParameters) { - walk_list!(visitor, visit_lifetime, &path_parameters.lifetimes); - walk_list!(visitor, visit_ty, &path_parameters.types); + walk_list!(visitor, visit_lifetime, path_parameters.lifetimes()); + walk_list!(visitor, visit_ty, path_parameters.types()); walk_list!(visitor, visit_assoc_type_binding, &path_parameters.bindings); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index dd12edb7302..8e66ce3fd18 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -46,6 +46,7 @@ use hir::map::{DefKey, DefPathData, Definitions}; use hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX}; use hir::def::{Def, PathResolution, PerNS}; +use hir::GenericPathParam; use lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES}; use middle::cstore::CrateStore; use rustc_data_structures::indexed_vec::IndexVec; @@ -1037,6 +1038,20 @@ fn lower_ty_binding(&mut self, b: &TypeBinding, itctx: ImplTraitContext) -> hir: } } + fn lower_param(&mut self, + p: &GenericAngleBracketedParam, + itctx: ImplTraitContext) + -> GenericPathParam { + match p { + GenericAngleBracketedParam::Lifetime(lt) => { + GenericPathParam::Lifetime(self.lower_lifetime(<)) + } + GenericAngleBracketedParam::Type(ty) => { + GenericPathParam::Type(self.lower_ty(&ty, itctx)) + } + } + } + fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P { let kind = match t.node { TyKind::Infer => hir::TyInfer, @@ -1552,7 +1567,7 @@ fn lower_qpath( assert!(!def_id.is_local()); let item_generics = self.cstore.item_generics_cloned_untracked(def_id, self.sess); - let n = item_generics.own_counts().lifetimes; + let n = item_generics.own_counts().lifetimes(); self.type_def_lifetime_params.insert(def_id, n); n }); @@ -1671,7 +1686,7 @@ fn lower_path_segment( ) -> hir::PathSegment { let (mut parameters, infer_types) = if let Some(ref parameters) = segment.parameters { let msg = "parenthesized parameters may only be used with a trait"; - match **parameters { + match **path_params { PathParameters::AngleBracketed(ref data) => { self.lower_angle_bracketed_parameter_data(data, param_mode, itctx) } @@ -1699,12 +1714,14 @@ fn lower_path_segment( }; if !parameters.parenthesized && parameters.lifetimes.is_empty() { - parameters.lifetimes = self.elided_path_lifetimes(path_span, expected_lifetimes); + path_params.parameters = (0..expected_lifetimes).map(|_| { + GenericPathParam::Lifetime(self.elided_lifetime(path_span)) + }).chain(path_params.parameters.into_iter()).collect(); } hir::PathSegment::new( self.lower_ident(segment.ident), - parameters, + path_params, infer_types, ) } @@ -1715,24 +1732,13 @@ fn lower_angle_bracketed_parameter_data( param_mode: ParamMode, itctx: ImplTraitContext, ) -> (hir::PathParameters, bool) { - let &AngleBracketedParameterData { - ref lifetimes, - ref types, - ref bindings, - .. - } = data; - ( - hir::PathParameters { - lifetimes: self.lower_lifetimes(lifetimes), - types: types.iter().map(|ty| self.lower_ty(ty, itctx)).collect(), - bindings: bindings - .iter() - .map(|b| self.lower_ty_binding(b, itctx)) - .collect(), - parenthesized: false, - }, - types.is_empty() && param_mode == ParamMode::Optional, - ) + let &AngleBracketedParameterData { ref parameters, ref bindings, .. } = data; + (hir::PathParameters { + parameters: parameters.iter().map(|p| self.lower_param(p, itctx)).collect(), + bindings: bindings.iter().map(|b| self.lower_ty_binding(b, itctx)).collect(), + parenthesized: false, + }, + types.is_empty() && param_mode == ParamMode::Optional) } fn lower_parenthesized_parameter_data( @@ -1769,8 +1775,7 @@ fn lower_parenthesized_parameter_data( ( hir::PathParameters { - lifetimes: hir::HirVec::new(), - types: hir_vec![mk_tup(this, inputs, span)], + parameters: hir_vec![GenericPathParam::Type(mk_tup(this, inputs, span))], bindings: hir_vec![ hir::TypeBinding { id: this.next_id().node_id, @@ -1971,7 +1976,7 @@ fn lower_lifetime_def(&mut self, l: &LifetimeDef) -> hir::LifetimeDef { let def = hir::LifetimeDef { lifetime: self.lower_lifetime(&l.lifetime), - bounds: self.lower_lifetimes(&l.bounds), + bounds: l.bounds.iter().map(|l| self.lower_lifetime(l)).collect(), pure_wrt_drop: attr::contains_name(&l.attrs, "may_dangle"), in_band: false, }; @@ -1981,10 +1986,6 @@ fn lower_lifetime_def(&mut self, l: &LifetimeDef) -> hir::LifetimeDef { def } - fn lower_lifetimes(&mut self, lts: &Vec) -> hir::HirVec { - lts.iter().map(|l| self.lower_lifetime(l)).collect() - } - fn lower_generic_params( &mut self, params: &Vec, diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 833090c3ee0..e69b824e779 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -372,12 +372,16 @@ pub fn with_parameters(&self, f: F) -> R } } +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum GenericPathParam { + Lifetime(Lifetime), + Type(P), +} + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct PathParameters { - /// The lifetime parameters for this path segment. - pub lifetimes: HirVec, - /// The type parameters for this path segment, if present. - pub types: HirVec>, + /// The generic parameters for this path segment. + pub parameters: HirVec, /// Bindings (equality constraints) on associated types, if present. /// E.g., `Foo`. pub bindings: HirVec, @@ -390,21 +394,19 @@ pub struct PathParameters { impl PathParameters { pub fn none() -> Self { Self { - lifetimes: HirVec::new(), - types: HirVec::new(), + parameters: HirVec::new(), bindings: HirVec::new(), parenthesized: false, } } pub fn is_empty(&self) -> bool { - self.lifetimes.is_empty() && self.types.is_empty() && - self.bindings.is_empty() && !self.parenthesized + self.parameters.is_empty() && self.bindings.is_empty() && !self.parenthesized } pub fn inputs(&self) -> &[P] { if self.parenthesized { - if let Some(ref ty) = self.types.get(0) { + if let Some(ref ty) = self.types().get(0) { if let TyTup(ref tys) = ty.node { return tys; } @@ -412,6 +414,26 @@ pub fn inputs(&self) -> &[P] { } bug!("PathParameters::inputs: not a `Fn(T) -> U`"); } + + pub fn lifetimes(&self) -> Vec<&Lifetime> { + self.parameters.iter().filter_map(|p| { + if let GenericPathParam::Lifetime(lt) = p { + Some(lt) + } else { + None + } + }).collect() + } + + pub fn types(&self) -> Vec<&P> { + self.parameters.iter().filter_map(|p| { + if let GenericPathParam::Type(ty) = p { + Some(ty) + } else { + None + } + }).collect() + } } /// The AST represents all type param bounds as types. diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 1beef3f715e..9e3c103b978 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -25,6 +25,7 @@ use hir; use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier, RangeEnd}; +use hir::GenericPathParam; use std::cell::Cell; use std::io::{self, Write, Read}; @@ -1269,8 +1270,7 @@ fn print_expr_method_call(&mut self, self.print_name(segment.name)?; segment.with_parameters(|parameters| { - if !parameters.lifetimes.is_empty() || - !parameters.types.is_empty() || + if !parameters.parameters.is_empty() || !parameters.bindings.is_empty() { self.print_path_parameters(¶meters, segment.infer_types, true) @@ -1707,18 +1707,18 @@ pub fn print_qpath(&mut self, } fn print_path_parameters(&mut self, - parameters: &hir::PathParameters, + path_params: &hir::PathParameters, infer_types: bool, colons_before_params: bool) -> io::Result<()> { - if parameters.parenthesized { + if path_params.parenthesized { self.s.word("(")?; - self.commasep(Inconsistent, parameters.inputs(), |s, ty| s.print_type(&ty))?; + self.commasep(Inconsistent, path_params.inputs(), |s, ty| s.print_type(&ty))?; self.s.word(")")?; self.space_if_not_bol()?; self.word_space("->")?; - self.print_type(¶meters.bindings[0].ty)?; + self.print_type(&path_params.bindings[0].ty)?; } else { let start = if colons_before_params { "::<" } else { "<" }; let empty = Cell::new(true); @@ -1731,17 +1731,27 @@ fn print_path_parameters(&mut self, } }; - if !parameters.lifetimes.iter().all(|lt| lt.is_elided()) { - for lifetime in ¶meters.lifetimes { - start_or_comma(self)?; - self.print_lifetime(lifetime)?; + let elide_lifetimes = path_params.parameters.iter().all(|p| { + if let GenericPathParam::Lifetime(lt) = p { + if !lt.is_elided() { + return false; + } } - } - - if !parameters.types.is_empty() { - start_or_comma(self)?; - self.commasep(Inconsistent, ¶meters.types, |s, ty| s.print_type(&ty))?; - } + true + }); + + self.commasep(Inconsistent, &path_params.parameters, |s, p| { + match p { + GenericPathParam::Lifetime(lt) => { + if !elide_lifetimes { + s.print_lifetime(lt) + } else { + Ok(()) + } + } + GenericPathParam::Type(ty) => s.print_type(ty), + } + })?; // FIXME(eddyb) This would leak into error messages, e.g.: // "non-exhaustive patterns: `Some::<..>(_)` not covered". @@ -1750,7 +1760,7 @@ fn print_path_parameters(&mut self, self.s.word("..")?; } - for binding in parameters.bindings.iter() { + for binding in path_params.bindings.iter() { start_or_comma(self)?; self.print_name(binding.name)?; self.s.space()?; diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index ed259b28545..54e6989d55a 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -180,9 +180,13 @@ fn hash_stable(&self, parameters }); +impl_stable_hash_for!(enum hir::GenericPathParam { + Lifetime(lt), + Type(ty) +}); + impl_stable_hash_for!(struct hir::PathParameters { - lifetimes, - types, + parameters, bindings, parenthesized }); diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index f251a3d5f38..477c4c213ce 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -155,7 +155,7 @@ fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region { } } - fn subst(self, params: &[hir::Lifetime], map: &NamedRegionMap) -> Option { + fn subst(self, params: Vec<&hir::Lifetime>, map: &NamedRegionMap) -> Option { if let Region::EarlyBound(index, _, _) = self { params .get(index as usize) @@ -820,7 +820,7 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { if lifetime_ref.is_elided() { - self.resolve_elided_lifetimes(slice::from_ref(lifetime_ref), false); + self.resolve_elided_lifetimes(vec![lifetime_ref], false); return; } if lifetime_ref.is_static() { @@ -1613,10 +1613,10 @@ fn visit_segment_parameters( return; } - if params.lifetimes.iter().all(|l| l.is_elided()) { - self.resolve_elided_lifetimes(¶ms.lifetimes, true); + if params.lifetimes().iter().all(|l| l.is_elided()) { + self.resolve_elided_lifetimes(params.lifetimes(), true); } else { - for l in ¶ms.lifetimes { + for l in ¶ms.lifetimes() { self.visit_lifetime(l); } } @@ -1688,13 +1688,13 @@ fn visit_segment_parameters( } else { Some(Region::Static) }, - Set1::One(r) => r.subst(¶ms.lifetimes, map), + Set1::One(r) => r.subst(params.lifetimes(), map), Set1::Many => None, }) .collect() }); - for (i, ty) in params.types.iter().enumerate() { + for (i, ty) in params.types().iter().enumerate() { if let Some(<) = object_lifetime_defaults.get(i) { let scope = Scope::ObjectLifetimeDefault { lifetime: lt, @@ -1981,7 +1981,9 @@ fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) { } } - fn resolve_elided_lifetimes(&mut self, lifetime_refs: &'tcx [hir::Lifetime], deprecated: bool) { + fn resolve_elided_lifetimes(&mut self, + lifetime_refs: Vec<&'tcx hir::Lifetime>, + deprecated: bool) { if lifetime_refs.is_empty() { return; } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4f5f0c9d740..d09be8e5c45 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -885,6 +885,73 @@ pub struct GenericParamCount { pub types: usize, } +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] +pub enum GenericParameterDef { + Lifetime(RegionParameterDef), + Type(TypeParameterDef), +} + +impl GenericParameterDef { + pub fn index(&self) -> u32 { + match self { + GenericParameterDef::Lifetime(lt) => lt.index, + GenericParameterDef::Type(ty) => ty.index, + } + } +} + +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] +pub enum KindIndex { + Lifetime, + Type, +} + +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] +pub struct KindIndexed { + pub lt: L, + pub ty: T, +} + +impl KindIndexed { + pub fn get(&self, idx: KindIndex) -> &T { + match idx { + KindIndex::Lifetime => &self.lt, + KindIndex::Type => &self.ty, + } + } + + pub fn iter(&self) -> KindIndexIterator { + KindIndexIterator { + index: self, + next: Some(KindIndex::Lifetime), + } + } +} + +#[derive(Clone, Debug)] +pub struct KindIndexIterator<'a, T: 'a> { + pub index: &'a KindIndexed, + pub next: Option, +} + +impl<'a, T> Iterator for KindIndexIterator<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option { + match self.next { + Some(KindIndex::Lifetime) => { + self.next = Some(KindIndex::Type); + Some(&self.index.lt) + } + Some(KindIndex::Type) => { + self.next = None; + Some(&self.index.ty) + }, + None => None, + } + } +} + /// Information about the formal type/lifetime parameters associated /// with an item or method. Analogous to hir::Generics. /// @@ -942,6 +1009,34 @@ pub fn requires_monomorphization(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { } } + pub fn lifetimes(&self) -> Vec<&RegionParameterDef> { + self.parameters.iter().filter_map(|p| { + if let GenericParameterDef::Lifetime(lt) = p { + Some(lt) + } else { + None + } + }).collect() + } + + pub fn types(&self) -> Vec<&TypeParameterDef> { + self.parameters.iter().filter_map(|p| { + if let GenericParameterDef::Type(ty) = p { + Some(ty) + } else { + None + } + }).collect() + } + + pub fn parent_lifetimes(&self) -> u32 { + *self.parent_parameters.get(KindIndex::Lifetime) + } + + pub fn parent_types(&self) -> u32 { + *self.parent_parameters.get(KindIndex::Type) + } + pub fn region_param(&'tcx self, param: &EarlyBoundRegion, tcx: TyCtxt<'a, 'gcx, 'tcx>) diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index f1ad14237ee..71ecc893806 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -680,7 +680,7 @@ fn involves_impl_trait(ty: &ast::Ty) -> bool { match seg.parameters.as_ref().map(|p| &**p) { None => false, Some(&ast::PathParameters::AngleBracketed(ref data)) => - any_involves_impl_trait(data.types.iter()) || + any_involves_impl_trait(data.types().into_iter()) || any_involves_impl_trait(data.bindings.iter().map(|b| &b.ty)), Some(&ast::PathParameters::Parenthesized(ref data)) => any_involves_impl_trait(data.inputs.iter()) || diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 279ee403cc6..81a3617f0aa 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -822,7 +822,7 @@ fn process_path(&mut self, id: NodeId, path: &'l ast::Path) { for seg in &path.segments { if let Some(ref params) = seg.parameters { match **params { - ast::PathParameters::AngleBracketed(ref data) => for t in &data.types { + ast::PathParameters::AngleBracketed(ref data) => for t in data.types() { self.visit_ty(t); }, ast::PathParameters::Parenthesized(ref data) => { @@ -907,7 +907,7 @@ fn process_method_call( // Explicit types in the turbo-fish. if let Some(ref params) = seg.parameters { if let ast::PathParameters::AngleBracketed(ref data) = **params { - for t in &data.types { + for t in data.types() { self.visit_ty(t); } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 18911b47ed1..005d088c478 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -214,8 +214,8 @@ fn create_substs_for_ast_path(&self, // region with the current anon region binding (in other words, // whatever & would get replaced with). let decl_generics = tcx.generics_of(def_id); - let ty_provided = parameters.types.len(); - let lt_provided = parameters.lifetimes.len(); + let ty_provided = parameters.types().len(); + let lt_provided = parameters.lifetimes().len(); let mut lt_accepted = 0; let mut ty_params = ParamRange { required: 0, accepted: 0 }; @@ -269,7 +269,7 @@ fn create_substs_for_ast_path(&self, match param.kind { GenericParamDefKind::Lifetime => { let i = param.index as usize - own_self; - if let Some(lifetime) = parameters.lifetimes.get(i) { + if let Some(lifetime) = parameters.lifetimes().get(i) { self.ast_region_to_region(lifetime, Some(param)).into() } else { tcx.types.re_static.into() @@ -286,7 +286,7 @@ fn create_substs_for_ast_path(&self, let i = i - (lt_accepted + own_self); if i < ty_provided { // A provided type parameter. - self.ast_ty_to_ty(¶meters.types[i]).into() + self.ast_ty_to_ty(¶meters.types()[i]).into() } else if infer_types { // No type parameters were provided, we can infer all. if !default_needs_object_self(param) { @@ -970,23 +970,27 @@ fn qpath_to_ty(&self, pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) { for segment in segments { - segment.with_parameters(|parameters| { - for typ in ¶meters.types { - struct_span_err!(self.tcx().sess, typ.span, E0109, - "type parameters are not allowed on this type") - .span_label(typ.span, "type parameter not allowed") - .emit(); - break; - } - for lifetime in ¶meters.lifetimes { - struct_span_err!(self.tcx().sess, lifetime.span, E0110, - "lifetime parameters are not allowed on this type") - .span_label(lifetime.span, - "lifetime parameter not allowed on this type") - .emit(); + segment.with_parameters(|params| { + for p in ¶ms.parameters { + let (mut span_err, span, kind) = match p { + hir::GenericPathParam::Lifetime(lt) => { + (struct_span_err!(self.tcx().sess, lt.span, E0110, + "lifetime parameters are not allowed on this type"), + lt.span, + "lifetime") + } + hir::GenericPathParam::Type(ty) => { + (struct_span_err!(self.tcx().sess, ty.span, E0109, + "type parameters are not allowed on this type"), + ty.span, + "type") + } + }; + span_err.span_label(span, format!("{} parameter not allowed", kind)) + .emit(); break; } - for binding in ¶meters.bindings { + for binding in ¶ms.bindings { self.prohibit_projection(binding.span); break; } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index f3a3c30fe5a..33102757925 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -331,7 +331,7 @@ fn instantiate_method_substs( match param.kind { GenericParamDefKind::Lifetime => { if let Some(lifetime) = provided.as_ref().and_then(|p| { - p.lifetimes.get(i - parent_substs.len()) + p.lifetimes().get(i - parent_substs.len()) }) { return AstConv::ast_region_to_region( self.fcx, lifetime, Some(param)).into(); @@ -339,7 +339,7 @@ fn instantiate_method_substs( } GenericParamDefKind::Type {..} => { if let Some(ast_ty) = provided.as_ref().and_then(|p| { - p.types.get(i - parent_substs.len() - own_counts.lifetimes) + p.types().get(i - parent_substs.len() - own_counts.lifetimes) }) { return self.to_ty(ast_ty).into(); } @@ -347,6 +347,7 @@ fn instantiate_method_substs( } self.var_for_def(self.span, param) } + self.type_var_for_def(self.span, def, cur_substs) }) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b70b61d1915..0f1b739cddf 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4833,8 +4833,8 @@ pub fn instantiate_value_path(&self, match param.kind { GenericParamDefKind::Lifetime => { - let lifetimes = segment.map_or(&[][..], |(s, _)| { - s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..]) + let lifetimes = segment.map_or(vec![], |(s, _)| { + s.parameters.as_ref().map_or(vec![], |p| p.lifetimes()) }); if let Some(lifetime) = lifetimes.get(i) { @@ -4844,8 +4844,8 @@ pub fn instantiate_value_path(&self, } } GenericParamDefKind::Type {..} => { - let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| { - (s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types) + let (types, infer_types) = segment.map_or((vec![], true), |(s, _)| { + (s.parameters.as_ref().map_or(vec![], |p| |p| p.types()), s.infer_types) }); // Skip over the lifetimes in the same segment. @@ -4961,10 +4961,10 @@ fn check_path_parameter_count(&self, is_method_call: bool, supress_mismatch_error: bool) { let (lifetimes, types, infer_types, bindings) = segment.map_or( - (&[][..], &[][..], true, &[][..]), + (vec![], vec![], true, &[][..]), |(s, _)| s.parameters.as_ref().map_or( - (&[][..], &[][..], s.infer_types, &[][..]), - |p| (&p.lifetimes[..], &p.types[..], + (vec![], vec![], s.infer_types, &[][..]), + |p| (p.lifetimes(), p.types(), s.infer_types, &p.bindings[..]))); let infer_lifetimes = lifetimes.len() == 0; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 58e804fc13f..6e323e5913a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -973,6 +973,13 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .map(|param| (param.def_id, param.index)) .collect(); + let parent_parameters = ty::KindIndexed { lt: parent_regions, ty: parent_types }; + let lifetimes: Vec = + regions.into_iter().map(|lt| ty::GenericParameterDef::Lifetime(lt)).collect(); + let types: Vec = + types.into_iter().map(|ty| ty::GenericParameterDef::Type(ty)).collect(); + let parameters = lifetimes.into_iter().chain(types.into_iter()).collect(); + tcx.alloc_generics(ty::Generics { parent: parent_def_id, parent_count, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 76fa463a631..1af4743cfe4 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -167,21 +167,47 @@ pub fn span(&self) -> Span { } } +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum GenericAngleBracketedParam { + Lifetime(Lifetime), + Type(P), +} + /// A path like `Foo<'a, T>` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Default)] pub struct AngleBracketedParameterData { /// Overall span pub span: Span, - /// The lifetime parameters for this path segment. - pub lifetimes: Vec, - /// The type parameters for this path segment, if present. - pub types: Vec>, + /// The parameters for this path segment. + pub parameters: Vec, /// Bindings (equality constraints) on associated types, if present. /// /// E.g., `Foo`. pub bindings: Vec, } +impl AngleBracketedParameterData { + pub fn lifetimes(&self) -> Vec<&Lifetime> { + self.parameters.iter().filter_map(|p| { + if let GenericAngleBracketedParam::Lifetime(lt) = p { + Some(lt) + } else { + None + } + }).collect() + } + + pub fn types(&self) -> Vec<&P> { + self.parameters.iter().filter_map(|p| { + if let GenericAngleBracketedParam::Type(ty) = p { + Some(ty) + } else { + None + } + }).collect() + } +} + impl Into>> for AngleBracketedParameterData { fn into(self) -> Option> { Some(P(PathParameters::AngleBracketed(self))) diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 4a6f06dcc17..02112517827 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -30,10 +30,9 @@ pub trait AstBuilder { fn path_global(&self, span: Span, strs: Vec ) -> ast::Path; fn path_all(&self, sp: Span, global: bool, - idents: Vec , - lifetimes: Vec, - types: Vec>, - bindings: Vec ) + idents: Vec, + parameters: Vec, + bindings: Vec) -> ast::Path; fn qpath(&self, self_type: P, @@ -43,8 +42,7 @@ fn qpath(&self, self_type: P, fn qpath_all(&self, self_type: P, trait_path: ast::Path, ident: ast::Ident, - lifetimes: Vec, - types: Vec>, + parameters: Vec, bindings: Vec) -> (ast::QSelf, ast::Path); @@ -304,20 +302,19 @@ fn item_use_glob(&self, sp: Span, impl<'a> AstBuilder for ExtCtxt<'a> { fn path(&self, span: Span, strs: Vec ) -> ast::Path { - self.path_all(span, false, strs, Vec::new(), Vec::new(), Vec::new()) + self.path_all(span, false, strs, Vec::new(), Vec::new()) } fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path { self.path(span, vec![id]) } fn path_global(&self, span: Span, strs: Vec ) -> ast::Path { - self.path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new()) + self.path_all(span, true, strs, Vec::new(), Vec::new()) } fn path_all(&self, span: Span, global: bool, mut idents: Vec , - lifetimes: Vec, - types: Vec>, + parameters: Vec, bindings: Vec ) -> ast::Path { let last_ident = idents.pop().unwrap(); @@ -326,8 +323,8 @@ fn path_all(&self, segments.extend(idents.into_iter().map(|ident| { ast::PathSegment::from_ident(ident.with_span_pos(span)) })); - let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() { - ast::AngleBracketedParameterData { lifetimes, types, bindings, span }.into() + let parameters = if !parameters.is_empty() !bindings.is_empty() { + ast::AngleBracketedParameterData { parameters, bindings, span }.into() } else { None }; @@ -349,7 +346,7 @@ fn qpath(&self, trait_path: ast::Path, ident: ast::Ident) -> (ast::QSelf, ast::Path) { - self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![]) + self.qpath_all(self_type, trait_path, ident, vec![], vec![]) } /// Constructs a qualified path. @@ -359,13 +356,12 @@ fn qpath_all(&self, self_type: P, trait_path: ast::Path, ident: ast::Ident, - lifetimes: Vec, - types: Vec>, + parameters: Vec, bindings: Vec) -> (ast::QSelf, ast::Path) { let mut path = trait_path; - let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() { - ast::AngleBracketedParameterData { lifetimes, types, bindings, span: ident.span }.into() + let parameters = if !parameters.is_empty() || !bindings.is_empty() { + ast::AngleBracketedParameterData { parameters, bindings, span: ident.span }.into() } else { None }; @@ -428,8 +424,7 @@ fn ty_option(&self, ty: P) -> P { self.path_all(DUMMY_SP, true, self.std_path(&["option", "Option"]), - Vec::new(), - vec![ ty ], + vec![ ast::GenericAngleBracketedParam::Type(ty) ], Vec::new())) } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 8544ef330dc..b935425cdd4 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -132,6 +132,10 @@ fn fold_exprs(&mut self, es: Vec>) -> Vec> { noop_fold_exprs(es, self) } + fn fold_param(&mut self, p: GenericAngleBracketedParam) -> GenericAngleBracketedParam { + noop_fold_param(p, self) + } + fn fold_ty(&mut self, t: P) -> P { noop_fold_ty(t, self) } @@ -353,6 +357,19 @@ pub fn noop_fold_ty_binding(b: TypeBinding, fld: &mut T) -> TypeBindi } } +pub fn noop_fold_param(p: GenericAngleBracketedParam, + fld: &mut T) + -> GenericAngleBracketedParam { + match p { + GenericAngleBracketedParam::Lifetime(lt) => { + GenericAngleBracketedParam::Lifetime(noop_fold_lifetime(lt, fld)) + } + GenericAngleBracketedParam::Type(ty) => { + GenericAngleBracketedParam::Type(noop_fold_ty(ty, fld)) + } + } +} + pub fn noop_fold_ty(t: P, fld: &mut T) -> P { t.map(|Ty {id, node, span}| Ty { id: fld.new_id(id), @@ -469,9 +486,8 @@ pub fn noop_fold_angle_bracketed_parameter_data(data: AngleBracketedP fld: &mut T) -> AngleBracketedParameterData { - let AngleBracketedParameterData { lifetimes, types, bindings, span } = data; - AngleBracketedParameterData { lifetimes: lifetimes.move_map(|l| noop_fold_lifetime(l, fld)), - types: types.move_map(|ty| fld.fold_ty(ty)), + let AngleBracketedParameterData { parameters, bindings, span } = data; + AngleBracketedParameterData { parameters: parameters.move_map(|p| fld.fold_param(p)), bindings: bindings.move_map(|b| fld.fold_ty_binding(b)), span: fld.new_span(span) } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1735951da2f..c205e937611 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -22,6 +22,7 @@ use ast::{Field, FnDecl}; use ast::{ForeignItem, ForeignItemKind, FunctionRetTy}; use ast::GenericParam; +use ast::GenericAngleBracketedParam; use ast::{Ident, ImplItem, IsAuto, Item, ItemKind}; use ast::{Label, Lifetime, LifetimeDef, Lit, LitKind}; use ast::Local; @@ -1971,10 +1972,10 @@ fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool) let parameters = if self.eat_lt() { // `<'a, T, A = U>` - let (lifetimes, types, bindings) = self.parse_generic_args()?; + let (parameters, bindings) = self.parse_generic_args()?; self.expect_gt()?; let span = lo.to(self.prev_span); - AngleBracketedParameterData { lifetimes, types, bindings, span }.into() + AngleBracketedParameterData { parameters, bindings, span }.into() } else { // `(T, U) -> R` self.bump(); // `(` @@ -4936,16 +4937,16 @@ fn parse_generics(&mut self) -> PResult<'a, ast::Generics> { /// Parses (possibly empty) list of lifetime and type arguments and associated type bindings, /// possibly including trailing comma. - fn parse_generic_args(&mut self) -> PResult<'a, (Vec, Vec>, Vec)> { - let mut lifetimes = Vec::new(); - let mut types = Vec::new(); + fn parse_generic_args(&mut self) + -> PResult<'a, (Vec, Vec)> { + let mut parameters = Vec::new(); let mut bindings = Vec::new(); let mut seen_type = false; let mut seen_binding = false; loop { if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) { // Parse lifetime argument. - lifetimes.push(self.expect_lifetime()); + parameters.push(GenericAngleBracketedParam::Lifetime(self.expect_lifetime())); if seen_type || seen_binding { self.span_err(self.prev_span, "lifetime parameters must be declared prior to type parameters"); @@ -4965,11 +4966,12 @@ fn parse_generic_args(&mut self) -> PResult<'a, (Vec, Vec>, Vec< seen_binding = true; } else if self.check_type() { // Parse type argument. - types.push(self.parse_ty()?); + let ty_param = self.parse_ty()?; if seen_binding { - self.span_err(types[types.len() - 1].span, + self.span_err(ty_param.span, "type parameters must be declared prior to associated type bindings"); } + parameters.push(GenericAngleBracketedParam::Type(ty_param)); seen_type = true; } else { break @@ -4979,7 +4981,7 @@ fn parse_generic_args(&mut self) -> PResult<'a, (Vec, Vec>, Vec< break } } - Ok((lifetimes, types, bindings)) + Ok((parameters, bindings)) } /// Parses an optional `where` clause and places it in `generics`. diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 87edfd69e2b..dc204e3d0ef 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -13,7 +13,7 @@ use rustc_target::spec::abi::{self, Abi}; use ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax}; use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; -use ast::{Attribute, MacDelimiter}; +use ast::{Attribute, MacDelimiter, GenericAngleBracketedParam}; use util::parser::{self, AssocOp, Fixity}; use attr; use codemap::{self, CodeMap}; @@ -1017,6 +1017,13 @@ pub fn print_opt_lifetime(&mut self, Ok(()) } + pub fn print_param(&mut self, param: &GenericAngleBracketedParam) -> io::Result<()> { + match param { + GenericAngleBracketedParam::Lifetime(lt) => self.print_lifetime(lt), + GenericAngleBracketedParam::Type(ty) => self.print_type(ty), + } + } + pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> { self.maybe_print_comment(ty.span.lo())?; self.ibox(0)?; @@ -2474,25 +2481,9 @@ fn print_path_parameters(&mut self, ast::PathParameters::AngleBracketed(ref data) => { self.s.word("<")?; - let mut comma = false; - for lifetime in &data.lifetimes { - if comma { - self.word_space(",")? - } - self.print_lifetime(lifetime)?; - comma = true; - } + self.commasep(Inconsistent, &data.parameters, |s, p| s.print_param(p))?; - if !data.types.is_empty() { - if comma { - self.word_space(",")? - } - self.commasep( - Inconsistent, - &data.types, - |s, ty| s.print_type(ty))?; - comma = true; - } + let mut comma = data.parameters.len() != 0; for binding in data.bindings.iter() { if comma { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index adda39c62ed..a4b9e3d7d45 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -387,8 +387,8 @@ pub fn walk_path_parameters<'a, V>(visitor: &mut V, { match *path_parameters { PathParameters::AngleBracketed(ref data) => { - walk_list!(visitor, visit_ty, &data.types); - walk_list!(visitor, visit_lifetime, &data.lifetimes); + walk_list!(visitor, visit_lifetime, data.lifetimes()); + walk_list!(visitor, visit_ty, data.types()); walk_list!(visitor, visit_assoc_type_binding, &data.bindings); } PathParameters::Parenthesized(ref data) => { diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index dec24d13c9b..3a83922bc90 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -13,6 +13,7 @@ use deriving::generic::ty::*; use syntax::ast::{self, Expr, Generics, ItemKind, MetaItem, VariantData}; +use syntax::ast::GenericAngleBracketedParam; use syntax::attr; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; @@ -123,7 +124,7 @@ fn assert_ty_bounds(cx: &mut ExtCtxt, stmts: &mut Vec, let span = span.with_ctxt(cx.backtrace()); let assert_path = cx.path_all(span, true, cx.std_path(&["clone", helper_name]), - vec![], vec![ty], vec![]); + vec![GenericAngleBracketedParam::Type(ty)], vec![]); stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path))); } fn process_variant(cx: &mut ExtCtxt, stmts: &mut Vec, variant: &VariantData) { diff --git a/src/libsyntax_ext/deriving/cmp/eq.rs b/src/libsyntax_ext/deriving/cmp/eq.rs index 237c8654edf..61b7e5b482d 100644 --- a/src/libsyntax_ext/deriving/cmp/eq.rs +++ b/src/libsyntax_ext/deriving/cmp/eq.rs @@ -12,7 +12,7 @@ use deriving::generic::*; use deriving::generic::ty::*; -use syntax::ast::{self, Expr, MetaItem}; +use syntax::ast::{self, Expr, MetaItem, GenericAngleBracketedParam}; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; use syntax::ptr::P; @@ -62,7 +62,7 @@ fn assert_ty_bounds(cx: &mut ExtCtxt, stmts: &mut Vec, let span = span.with_ctxt(cx.backtrace()); let assert_path = cx.path_all(span, true, cx.std_path(&["cmp", helper_name]), - vec![], vec![ty], vec![]); + vec![GenericAngleBracketedParam::Type(ty)], vec![]); stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path))); } fn process_variant(cx: &mut ExtCtxt, stmts: &mut Vec, variant: &ast::VariantData) { diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 80f65957c39..7ab0acda408 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -192,10 +192,8 @@ use std::vec; use rustc_target::spec::abi::Abi; -use syntax::ast::{ - self, BinOpKind, EnumDef, Expr, GenericParam, Generics, Ident, PatKind, VariantData -}; - +use syntax::ast::{self, BinOpKind, EnumDef, Expr, GenericParam, Generics, Ident, PatKind}; +use syntax::ast::{VariantData, GenericAngleBracketedParam}; use syntax::attr; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; @@ -667,7 +665,7 @@ fn create_derived_impl(&self, let trait_ref = cx.trait_ref(trait_path); // Create the type parameters on the `self` path. - let self_ty_params = generics.params + let self_ty_params: Vec> = generics.params .iter() .filter_map(|param| match *param { GenericParam::Type(ref ty_param) @@ -684,12 +682,17 @@ fn create_derived_impl(&self, }) .collect(); + let self_params = self_lifetimes.into_iter() + .map(|lt| GenericAngleBracketedParam::Lifetime(lt)) + .chain(self_ty_params.into_iter().map(|ty| + GenericAngleBracketedParam::Type(ty))) + .collect(); + // Create the type of `self`. let self_type = cx.ty_path(cx.path_all(self.span, false, vec![type_ident], - self_lifetimes, - self_ty_params, + self_params, Vec::new())); let attr = cx.attribute(self.span, diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs index 25a29694488..6387f2d8d98 100644 --- a/src/libsyntax_ext/deriving/generic/ty.rs +++ b/src/libsyntax_ext/deriving/generic/ty.rs @@ -15,7 +15,7 @@ pub use self::Ty::*; use syntax::ast; -use syntax::ast::{Expr, GenericParam, Generics, Ident, SelfKind}; +use syntax::ast::{Expr, GenericParam, Generics, Ident, SelfKind, GenericAngleBracketedParam}; use syntax::ext::base::ExtCtxt; use syntax::ext::build::AstBuilder; use syntax::codemap::{respan, DUMMY_SP}; @@ -86,15 +86,20 @@ pub fn to_path(&self, -> ast::Path { let mut idents = self.path.iter().map(|s| cx.ident_of(*s)).collect(); let lt = mk_lifetimes(cx, span, &self.lifetime); - let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect(); + let tys: Vec> = + self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect(); + let params = lt.into_iter() + .map(|lt| GenericAngleBracketedParam::Lifetime(lt)) + .chain(tys.into_iter().map(|ty| GenericAngleBracketedParam::Type(ty))) + .collect(); match self.kind { - PathKind::Global => cx.path_all(span, true, idents, lt, tys, Vec::new()), - PathKind::Local => cx.path_all(span, false, idents, lt, tys, Vec::new()), + PathKind::Global => cx.path_all(span, true, idents, params, Vec::new()), + PathKind::Local => cx.path_all(span, false, idents, params, Vec::new()), PathKind::Std => { let def_site = DUMMY_SP.apply_mark(cx.current_expansion.mark); idents.insert(0, Ident::new(keywords::DollarCrate.name(), def_site)); - cx.path_all(span, false, idents, lt, tys, Vec::new()) + cx.path_all(span, false, idents, params, Vec::new()) } } @@ -184,7 +189,7 @@ pub fn to_path(&self, -> ast::Path { match *self { Self_ => { - let self_params = self_generics.params + let ty_params: Vec> = self_generics.params .iter() .filter_map(|param| match *param { GenericParam::Type(ref ty_param) => Some(cx.ty_ident(span, ty_param.ident)), @@ -200,11 +205,16 @@ pub fn to_path(&self, }) .collect(); + let params = lifetimes.into_iter() + .map(|lt| GenericAngleBracketedParam::Lifetime(lt)) + .chain(ty_params.into_iter().map(|ty| + GenericAngleBracketedParam::Type(ty))) + .collect(); + cx.path_all(span, false, vec![self_ty], - lifetimes, - self_params, + params, Vec::new()) } Literal(ref p) => p.to_path(cx, span, self_ty, self_generics), diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs index 4e1af108ab4..c904cfcfdbf 100644 --- a/src/libsyntax_ext/env.rs +++ b/src/libsyntax_ext/env.rs @@ -13,7 +13,7 @@ // interface. // -use syntax::ast::{self, Ident}; +use syntax::ast::{self, Ident, GenericAngleBracketedParam}; use syntax::ext::base::*; use syntax::ext::base; use syntax::ext::build::AstBuilder; @@ -39,8 +39,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, cx.expr_path(cx.path_all(sp, true, cx.std_path(&["option", "Option", "None"]), - Vec::new(), - vec![cx.ty_rptr(sp, + vec![GenericAngleBracketedParam::Type(cx.ty_rptr(sp, cx.ty_ident(sp, Ident::from_str("str")), Some(lt), ast::Mutability::Immutable)], -- GitLab