if item_lowered {
let item_lifetimes = match self.lctx.items.get(&item.id).unwrap().node {
- hir::Item_::ItemImpl(_, _, _, ref generics, ..)
- | hir::Item_::ItemTrait(_, _, ref generics, ..) => {
+ hir::Item_::ItemImpl(_, _, _, ref generics, .. ) |
+ hir::Item_::ItemTrait(_, _, ref generics, .. ) => {
generics.lifetimes().cloned().collect::<Vec<_>>()
}
_ => Vec::new(),
for lt_def in generics.lifetimes() {
let (lt_name, region) = Region::early(&self.tcx.hir, &mut index, <_def);
if let hir::LifetimeName::Underscore = lt_name {
- // Pick the elided lifetime "definition" if one exists and use it to make an
- // elision scope.
+ // Pick the elided lifetime "definition" if one exists and use it to make
+ // an elision scope.
elision = Some(region);
} else {
lifetimes.insert(lt_name, region);
let name = param.name.to_string();
let ty = trait_ref.substs.type_for_def(param);
let ty_str = ty.to_string();
- flags.push((name.clone(),
- Some(ty_str.clone())));
+ flags.push((name.clone(), Some(ty_str.clone())));
}
if let Some(true) = self_ty.ty_to_def_id().map(|def_id| def_id.is_local()) {
use fmt_macros::{Parser, Piece, Position};
use hir::def_id::DefId;
-use ty::{self, TyCtxt};
+use ty::{self, TyCtxt, GenericParamDef};
use util::common::ErrorReported;
use util::nodemap::FxHashMap;
let name = tcx.item_name(trait_def_id);
let generics = tcx.generics_of(trait_def_id);
let parser = Parser::new(&self.0);
- let mut types = generics.types();
let mut result = Ok(());
for token in parser {
match token {
// `{ThisTraitsName}` is allowed
Position::ArgumentNamed(s) if s == name => (),
// So is `{A}` if A is a type parameter
- Position::ArgumentNamed(s) => match types.find(|t| {
- t.name == s
+ Position::ArgumentNamed(s) => match generics.params.iter().find(|param| {
+ if let GenericParamDef::Type(ty) = param {
+ ty.name == s
+ } else {
+ false
+ }
}) {
Some(_) => (),
None => {
let trait_str = tcx.item_path_str(trait_ref.def_id);
let generics = tcx.generics_of(trait_ref.def_id);
let generic_map = generics.types().map(|param| {
- (param.name.to_string(),
- trait_ref.substs.type_for_def(param).to_string())
+ (param.name.to_string(), trait_ref.substs.type_for_def(param).to_string())
}).collect::<FxHashMap<String, String>>();
let parser = Parser::new(&self.0);
}
}
+#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
+pub enum Kind {
+ Lifetime,
+ Type,
+}
+
+impl Kind {
+ pub fn iter<'a>() -> impl Iterator<Item = &'a Kind> {
+ [Kind::Lifetime, Kind::Type].into_iter()
+ }
+}
+
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum GenericParamDef {
Lifetime(RegionParamDef),
self.parent_count + self.params.len()
}
+ pub fn param_counts(&self) -> FxHashMap<Kind, usize> {
+ let mut param_counts: FxHashMap<_, _> = FxHashMap();
+ Kind::iter().for_each(|kind| {
+ param_counts.insert(*kind, 0);
+ });
+
+ for param in self.params.iter() {
+ let key = match param {
+ GenericParamDef::Type(_) => Kind::Type,
+ GenericParamDef::Lifetime(_) => Kind::Lifetime,
+ };
+ *param_counts.get_mut(&key).unwrap() += 1;
+ }
+
+ param_counts
+ }
+
pub fn lifetimes(&self) -> impl DoubleEndedIterator<Item = &RegionParamDef> {
self.params.iter().filter_map(|p| {
if let GenericParamDef::Lifetime(lt) = p {
use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
use ty::{TyClosure, TyGenerator, TyGeneratorWitness, TyForeign, TyProjection, TyAnon};
use ty::{TyDynamic, TyInt, TyUint, TyInfer};
-use ty::{self, Ty, TyCtxt, TypeFoldable};
-use util::nodemap::FxHashSet;
+use ty::{self, Ty, TyCtxt, TypeFoldable, Kind};
+use util::nodemap::{FxHashSet, FxHashMap};
use std::cell::Cell;
use std::fmt;
let verbose = self.is_verbose;
let mut num_supplied_defaults = 0;
let mut has_self = false;
- let mut num_regions = 0;
- let mut num_types = 0;
+ let mut param_counts = FxHashMap();
+ Kind::iter().for_each(|kind| {
+ param_counts.insert(*kind, 0);
+ });
let mut is_value_path = false;
let fn_trait_kind = ty::tls::with(|tcx| {
// Unfortunately, some kinds of items (e.g., closures) don't have
}
}
let mut generics = tcx.generics_of(item_def_id);
+ let child_param_counts = generics.param_counts();
let mut path_def_id = did;
has_self = generics.has_self;
if let Some(def_id) = generics.parent {
// Methods.
assert!(is_value_path);
- child_types = generics.types().count();
+ child_types = child_param_counts[&Kind::Type];
generics = tcx.generics_of(def_id);
- num_regions = generics.lifetimes().count();
- num_types = generics.types().count();
+ param_counts = generics.param_counts();
if has_self {
print!(f, self, write("<"), print_display(substs.type_at(0)), write(" as "))?;
assert_eq!(has_self, false);
} else {
// Types and traits.
- num_regions = generics.lifetimes().count();
- num_types = generics.types().count();
+ param_counts = child_param_counts;
}
}
Ok(())
};
- print_regions(f, "<", 0, num_regions)?;
+ print_regions(f, "<", 0, param_counts[&Kind::Lifetime])?;
- let tps = substs.types().take(num_types - num_supplied_defaults)
- .skip(has_self as usize);
+ let tps = substs.types()
+ .take(param_counts[&Kind::Type] - num_supplied_defaults)
+ .skip(has_self as usize);
for ty in tps {
start_or_continue(f, "<", ", ")?;
write!(f, "::{}", item_name)?;
}
- print_regions(f, "::<", num_regions, usize::MAX)?;
+ print_regions(f, "::<", param_counts[&Kind::Lifetime], usize::MAX)?;
// FIXME: consider being smart with defaults here too
- for ty in substs.types().skip(num_types) {
+ for ty in substs.types().skip(param_counts[&Kind::Type]) {
start_or_continue(f, "::<", ", ")?;
ty.print_display(f, self)?;
}
use rustc::hir::TransFnAttrFlags;
use rustc::hir::def_id::{DefId, CrateNum};
use rustc::ty::subst::Substs;
+use rustc::ty::{Kind, GenericParamDef};
use abi::Abi;
use common::CodegenCx;
// Again, only create type information if full debuginfo is enabled
let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo {
- let names = get_type_parameter_names(cx, generics);
+ let names = get_parameter_names(cx, generics);
+ let names = names.iter().flat_map(|(kind, param)| {
+ if kind == &Kind::Type {
+ Some(param)
+ } else {
+ None
+ }
+ });
substs.types().zip(names).map(|(ty, name)| {
let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
return create_DIArray(DIB(cx), &template_params[..]);
}
- fn get_type_parameter_names(cx: &CodegenCx, generics: &ty::Generics) -> Vec<InternedString> {
+ fn get_parameter_names(cx: &CodegenCx,
+ generics: &ty::Generics)
+ -> Vec<(Kind, InternedString)> {
let mut names = generics.parent.map_or(vec![], |def_id| {
- get_type_parameter_names(cx, cx.tcx.generics_of(def_id))
+ get_parameter_names(cx, cx.tcx.generics_of(def_id))
});
- names.extend(generics.types().map(|param| param.name));
+ names.extend(generics.params.iter().map(|param| {
+ match param {
+ GenericParamDef::Lifetime(lt) => (Kind::Lifetime, lt.name.as_str()),
+ GenericParamDef::Type(ty) => (Kind::Type, ty.name),
+ }
+ }));
names
}
use rustc::mir::interpret::{GlobalId};
use rustc::ty::subst::{Kind, Subst, Substs};
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
-use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate};
+use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate, GenericParamDef};
use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc::ty::fold::TypeFoldable;
use rustc::ty::maps::Providers;
} else {
for item in &m.items {
let generics = tcx.generics_of(tcx.hir.local_def_id(item.id));
- if generics.types().count() != 0 {
+ let param_counts = generics.param_counts();
+ if generics.params.len() - param_counts[&ty::Kind::Lifetime] != 0 {
let mut err = struct_span_err!(tcx.sess, item.span, E0044,
"foreign items may not have type parameters");
err.span_label(item.span, "can't have type parameters");
// Skip over the lifetimes in the same segment.
if let Some((_, generics)) = segment {
- i -= generics.lifetimes().count();
+ i -= generics.param_counts()[&ty::Kind::Lifetime];
}
if let Some(ast_ty) = types.get(i) {
format!("{} type parameter{}", n, if n == 1 { "" } else { "s" })
};
- // Check provided type parameters.
- let type_defs = segment.map_or(vec![], |(_, generics)| {
- if generics.parent.is_none() {
- generics.types().skip(generics.has_self as usize).collect()
- } else {
- generics.types().collect()
- }
- });
- let required_len = type_defs.iter().take_while(|d| !d.has_default).count();
- if types.len() > type_defs.len() {
- let span = types[type_defs.len()].span;
- let expected_text = count_type_params(type_defs.len());
+ // Check provided parameters.
+ let (ty_non_def_req_len, ty_req_len, lt_req_len) =
+ segment.map_or((0, 0, 0), |(_, generics)| {
+ let params_count = generics.param_counts();
+
+ let offset_type_params = generics.parent.is_none() && generics.has_self;
+ let type_params = params_count[&ty::Kind::Type] - offset_type_params as usize;
+ let type_params_barring_defaults =
+ type_params - generics.params.iter().filter(|param| {
+ if let GenericParamDef::Type(ty) = param {
+ ty.has_default
+ } else {
+ false
+ }
+ }).count();
+
+ (type_params_barring_defaults, type_params, params_count[&ty::Kind::Lifetime])
+ });
+
+ if types.len() > ty_req_len {
+ let span = types[ty_req_len].span;
+ let expected_text = count_type_params(ty_req_len);
let actual_text = count_type_params(types.len());
struct_span_err!(self.tcx.sess, span, E0087,
"too many type parameters provided: \
// type parameters, we force instantiate_value_path to
// use inference variables instead of the provided types.
*segment = None;
- } else if types.len() < required_len && !infer_types && !supress_mismatch_error {
- let expected_text = count_type_params(required_len);
+ } else if types.len() < ty_non_def_req_len && !infer_types && !supress_mismatch_error {
+ let expected_text = count_type_params(ty_non_def_req_len);
let actual_text = count_type_params(types.len());
struct_span_err!(self.tcx.sess, span, E0089,
"too few type parameters provided: \
AstConv::prohibit_projection(self, bindings[0].span);
}
- // Check provided lifetime parameters.
- let lifetime_defs = segment.map_or(vec![], |(_, generics)| generics.lifetimes().collect());
- let required_len = lifetime_defs.len();
-
// Prohibit explicit lifetime arguments if late bound lifetime parameters are present.
let has_late_bound_lifetime_defs =
segment.map_or(None, |(_, generics)| generics.has_late_bound_regions);
let primary_msg = "cannot specify lifetime arguments explicitly \
if late bound lifetime parameters are present";
let note_msg = "the late bound lifetime parameter is introduced here";
- if !is_method_call && (lifetimes.len() > required_len ||
- lifetimes.len() < required_len && !infer_lifetimes) {
+ if !is_method_call && (lifetimes.len() > lt_req_len ||
+ lifetimes.len() < lt_req_len && !infer_lifetimes) {
let mut err = self.tcx.sess.struct_span_err(lifetimes[0].span, primary_msg);
err.span_note(span_late, note_msg);
err.emit();
return;
}
- if lifetimes.len() > required_len {
- let span = lifetimes[required_len].span;
- let expected_text = count_lifetime_params(required_len);
+ if lifetimes.len() > lt_req_len {
+ let span = lifetimes[lt_req_len].span;
+ let expected_text = count_lifetime_params(lt_req_len);
let actual_text = count_lifetime_params(lifetimes.len());
struct_span_err!(self.tcx.sess, span, E0088,
"too many lifetime parameters provided: \
expected_text, actual_text)
.span_label(span, format!("expected {}", expected_text))
.emit();
- } else if lifetimes.len() < required_len && !infer_lifetimes {
- let expected_text = count_lifetime_params(required_len);
+ } else if lifetimes.len() < lt_req_len && !infer_lifetimes {
+ let expected_text = count_lifetime_params(lt_req_len);
let actual_text = count_lifetime_params(lifetimes.len());
struct_span_err!(self.tcx.sess, span, E0090,
"too few lifetime parameters provided: \
span: Span,
segment: &mut Option<(&hir::PathSegment, &ty::Generics)>)
-> bool {
- use hir::SyntheticTyParamKind::*;
-
let segment = segment.map(|(path_segment, generics)| {
let explicit = !path_segment.infer_types;
- let impl_trait = generics.types().any(|ty_param| {
- match ty_param.synthetic {
- Some(ImplTrait) => true,
- _ => false,
- }
- });
+ let impl_trait = generics.params.iter().any(|param| {
+ if let ty::GenericParamDef::Type(ty) = param {
+ if let Some(hir::SyntheticTyParamKind::ImplTrait) = ty.synthetic {
+ return true;
+ }
+ }
+ false
+ });
if explicit && impl_trait {
let mut err = struct_span_err! {
if generics.ty_params().next().is_none() { return; }
let mut tps_used = vec![false; generics.ty_params().count()];
- let lifetime_count = generics.lifetimes().count();
+ let mut param_counts = FxHashMap();
+ param_counts.insert(ty::Kind::Type, 0);
+ param_counts.insert(ty::Kind::Lifetime, 0);
+
+ for param in generics.params.iter() {
+ let key = match param {
+ hir::GenericParamDef::Type(_) => ty::Kind::Type,
+ hir::GenericParamDef::Lifetime(_) => ty::Kind::Lifetime,
+ };
+ *param_counts.get_mut(&key).unwrap() += 1;
+ }
for leaf_ty in ty.walk() {
- if let ty::TyParam(ty::ParamTy {idx, ..}) = leaf_ty.sty {
+ if let ty::TyParam(ty::ParamTy {idx, .. }) = leaf_ty.sty {
debug!("Found use of ty param num {}", idx);
- tps_used[idx as usize - lifetime_count] = true;
+ tps_used[idx as usize - param_counts[&ty::Kind::Lifetime]] = true;
} else if let ty::TyError = leaf_ty.sty {
// If there already another error, do not emit an error for not using a type Parameter
assert!(tcx.sess.err_count() > 0);
use check::{Inherited, FnCtxt};
use constrained_type_params::{identify_constrained_type_params, Parameter};
+use ty::GenericParamDef;
+
use hir::def_id::DefId;
use rustc::traits::{self, ObligationCauseCode};
use rustc::ty::{self, Lift, Ty, TyCtxt};
fcx.register_wf_obligation(ty, span, code.clone());
}
ty::AssociatedKind::Method => {
- reject_shadowing_type_parameters(fcx.tcx, item.def_id);
+ reject_shadowing_parameters(fcx.tcx, item.def_id);
let sig = fcx.tcx.fn_sig(item.def_id);
let sig = fcx.normalize_associated_types_in(span, &sig);
check_fn_or_method(tcx, fcx, span, sig,
err.emit();
}
-fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
+fn reject_shadowing_parameters(tcx: TyCtxt, def_id: DefId) {
let generics = tcx.generics_of(def_id);
let parent = tcx.generics_of(generics.parent.unwrap());
- let impl_params: FxHashMap<_, _> = parent.types()
- .map(|tp| (tp.name, tp.def_id))
- .collect();
-
- for method_param in generics.types() {
- if impl_params.contains_key(&method_param.name) {
+ let impl_params: FxHashMap<_, _> =
+ parent.params.iter()
+ .flat_map(|param| {
+ match param {
+ GenericParamDef::Lifetime(_) => None,
+ GenericParamDef::Type(ty) => Some((ty.name, ty.def_id)),
+ }
+ })
+ .collect();
+
+ for method_param in generics.params.iter() {
+ // Shadowing is currently permitted with lifetimes.
+ if let GenericParamDef::Lifetime(_) = method_param {
+ continue;
+ }
+ let (name, def_id) = match method_param {
+ GenericParamDef::Lifetime(_) => continue,
+ GenericParamDef::Type(ty) => (ty.name, ty.def_id),
+ };
+ if impl_params.contains_key(&name) {
// Tighten up the span to focus on only the shadowing type
- let type_span = tcx.def_span(method_param.def_id);
+ let type_span = tcx.def_span(def_id);
// The expectation here is that the original trait declaration is
// local so it should be okay to just unwrap everything.
- let trait_def_id = impl_params[&method_param.name];
+ let trait_def_id = impl_params[&name];
let trait_decl_span = tcx.def_span(trait_def_id);
- error_194(tcx, type_span, trait_decl_span, &method_param.name.as_str()[..]);
+ error_194(tcx, type_span, trait_decl_span, &name[..]);
}
}
}
}
fn generics_to_path_params(&self, generics: ty::Generics) -> hir::PathParameters {
- let lifetimes = HirVec::from_vec(
- generics.lifetimes()
- .map(|p| {
- let name = if p.name == "" {
- hir::LifetimeName::Static
- } else {
- hir::LifetimeName::Name(p.name.as_symbol())
- };
+ let mut lifetimes = vec![];
+ let mut types = vec![];
+
+ for param in generics.params.iter() {
+ match param {
+ ty::GenericParamDef::Lifetime(lt) => {
+ let name = if lt.name == "" {
+ hir::LifetimeName::Static
+ } else {
+ hir::LifetimeName::Name(lt.name.as_symbol())
+ };
- hir::Lifetime {
- id: ast::DUMMY_NODE_ID,
- span: DUMMY_SP,
- name,
- }
- })
- .collect(),
- );
- let types = HirVec::from_vec(
- generics.types()
- .into_iter()
- .map(|p| P(self.ty_param_to_ty(p.clone())))
- .collect(),
- );
+ lifetimes.push(hir::Lifetime {
+ id: ast::DUMMY_NODE_ID,
+ span: DUMMY_SP,
+ name,
+ });
+ }
+ ty::GenericParamDef::Type(ty) => {
+ types.push(P(self.ty_param_to_ty(ty.clone())));
+ }
+ }
+ }
hir::PathParameters {
- lifetimes: lifetimes,
- types: types,
+ lifetimes: HirVec::from_vec(lifetimes),
+ types: HirVec::from_vec(types),
bindings: HirVec::new(),
parenthesized: false,
}
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::hir::def_id::DefIndexAddressSpace;
use rustc::ty::subst::Substs;
-use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
+use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind, Kind};
use rustc::middle::stability;
use rustc::util::nodemap::{FxHashMap, FxHashSet};
use rustc_typeck::hir_ty_to_ty;
let mut ty_substs = FxHashMap();
let mut lt_substs = FxHashMap();
provided_params.with_parameters(|provided_params| {
- for (i, ty_param) in generics.ty_params().enumerate() {
- let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
- if let Some(ty) = provided_params.types.get(i).cloned() {
- ty_substs.insert(ty_param_def, ty.into_inner().clean(cx));
- } else if let Some(default) = ty_param.default.clone() {
- ty_substs.insert(ty_param_def, default.into_inner().clean(cx));
- }
- }
-
- for (i, lt_param) in generics.lifetimes().enumerate() {
- if let Some(lt) = provided_params.lifetimes.get(i).cloned() {
- if !lt.is_elided() {
- let lt_def_id = cx.tcx.hir.local_def_id(lt_param.lifetime.id);
- lt_substs.insert(lt_def_id, lt.clean(cx));
+ let mut indices = FxHashMap();
+ for param in generics.params.iter() {
+ match param {
+ GenericParamDef::Type(ty_param) => {
+ let i = indices.entry(Kind::Type).or_insert(0);
+ let ty_param_def =
+ Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
+ if let Some(ty) = provided_params.types.get(*i).cloned() {
+ ty_substs.insert(ty_param_def, ty.into_inner().clean(cx));
+ } else if let Some(default) = ty_param.default.clone() {
+ ty_substs.insert(ty_param_def,
+ default.into_inner().clean(cx));
+ }
+ *i += 1;
+ }
+ GenericParamDef::Lifetime(lt_param) => {
+ let i = indices.entry(Kind::Type).or_insert(0);
+ if let Some(lt) = provided_params.lifetimes.get(*i).cloned() {
+ if !lt.is_elided() {
+ let lt_def_id =
+ cx.tcx.hir.local_def_id(lt_param.lifetime.id);
+ lt_substs.insert(lt_def_id, lt.clean(cx));
+ }
+ }
+ *i += 1;
}
}
}