rustc: split Generics of a method from its parent Generics.

This commit is contained in:
Eduard Burtescu 2016-08-10 20:39:09 +03:00
parent c1cfd58cbd
commit 3e74e5bffe
25 changed files with 291 additions and 265 deletions

View File

@ -82,7 +82,6 @@ use hir::def::Def;
use hir::def_id::DefId; use hir::def_id::DefId;
use infer::{self, TypeOrigin}; use infer::{self, TypeOrigin};
use middle::region; use middle::region;
use ty::subst;
use ty::{self, TyCtxt, TypeFoldable}; use ty::{self, TyCtxt, TypeFoldable};
use ty::{Region, ReFree}; use ty::{Region, ReFree};
use ty::error::TypeError; use ty::error::TypeError;
@ -1369,7 +1368,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
let generics = self.tcx.lookup_generics(did); let generics = self.tcx.lookup_generics(did);
let expected = let expected =
generics.regions.len(subst::TypeSpace) as u32; generics.regions.len() as u32;
let lifetimes = let lifetimes =
path.segments.last().unwrap().parameters.lifetimes(); path.segments.last().unwrap().parameters.lifetimes();
let mut insert = Vec::new(); let mut insert = Vec::new();

View File

@ -271,14 +271,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
let def = self.tcx.lookup_trait_def(trait_ref.def_id); let def = self.tcx.lookup_trait_def(trait_ref.def_id);
let trait_str = def.trait_ref.to_string(); let trait_str = def.trait_ref.to_string();
if let Some(ref istring) = item.value_str() { if let Some(ref istring) = item.value_str() {
let mut generic_map = def.generics.types.iter_enumerated() let generic_map = def.generics.types.iter().map(|param| {
.map(|(param, i, gen)| { (param.name.as_str().to_string(),
(gen.name.as_str().to_string(), trait_ref.substs.type_for_def(param).to_string())
trait_ref.substs.types.get(param, i) }).collect::<FnvHashMap<String, String>>();
.to_string())
}).collect::<FnvHashMap<String, String>>();
generic_map.insert("Self".to_string(),
trait_ref.self_ty().to_string());
let parser = Parser::new(&istring); let parser = Parser::new(&istring);
let mut errored = false; let mut errored = false;
let err: String = parser.filter_map(|p| { let err: String = parser.filter_map(|p| {

View File

@ -20,7 +20,6 @@
use super::elaborate_predicates; use super::elaborate_predicates;
use hir::def_id::DefId; use hir::def_id::DefId;
use ty::subst;
use traits; use traits;
use ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
use std::rc::Rc; use std::rc::Rc;
@ -266,7 +265,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
} }
// We can't monomorphize things like `fn foo<A>(...)`. // We can't monomorphize things like `fn foo<A>(...)`.
if !method.generics.types.is_empty_in(subst::FnSpace) { if !method.generics.types.is_empty() {
return Some(MethodViolationCode::Generic); return Some(MethodViolationCode::Generic);
} }

View File

@ -757,33 +757,14 @@ impl RegionParameterDef {
/// with an item or method. Analogous to hir::Generics. /// with an item or method. Analogous to hir::Generics.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Generics<'tcx> { pub struct Generics<'tcx> {
pub types: VecPerParamSpace<TypeParameterDef<'tcx>>, pub parent: Option<DefId>,
pub regions: VecPerParamSpace<RegionParameterDef>, pub parent_regions: u32,
pub parent_types: u32,
pub regions: Vec<RegionParameterDef>,
pub types: Vec<TypeParameterDef<'tcx>>,
pub has_self: bool, pub has_self: bool,
} }
impl<'tcx> Generics<'tcx> {
pub fn empty() -> Generics<'tcx> {
Generics {
types: VecPerParamSpace::empty(),
regions: VecPerParamSpace::empty(),
has_self: false,
}
}
pub fn is_empty(&self) -> bool {
self.types.is_empty() && self.regions.is_empty()
}
pub fn has_type_params(&self, space: subst::ParamSpace) -> bool {
!self.types.is_empty_in(space)
}
pub fn has_region_params(&self, space: subst::ParamSpace) -> bool {
!self.regions.is_empty_in(space)
}
}
/// Bounds on generics. /// Bounds on generics.
#[derive(Clone)] #[derive(Clone)]
pub struct GenericPredicates<'tcx> { pub struct GenericPredicates<'tcx> {

View File

@ -832,20 +832,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef {
} }
} }
impl<'tcx> TypeFoldable<'tcx> for ty::Generics<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::Generics {
types: self.types.fold_with(folder),
regions: self.regions.fold_with(folder),
has_self: self.has_self
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.types.visit_with(visitor) || self.regions.visit_with(visitor)
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> { impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::GenericPredicates { ty::GenericPredicates {

View File

@ -89,42 +89,55 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
where FR: FnMut(&ty::RegionParameterDef, &Substs<'tcx>) -> ty::Region, where FR: FnMut(&ty::RegionParameterDef, &Substs<'tcx>) -> ty::Region,
FT: FnMut(&ty::TypeParameterDef<'tcx>, &Substs<'tcx>) -> Ty<'tcx> { FT: FnMut(&ty::TypeParameterDef<'tcx>, &Substs<'tcx>) -> Ty<'tcx> {
let defs = tcx.lookup_generics(def_id); let defs = tcx.lookup_generics(def_id);
let num_regions = defs.parent_regions as usize + defs.regions.len();
let num_types = defs.parent_types as usize + defs.types.len();
let mut substs = Substs { let mut substs = Substs {
types: VecPerParamSpace {
type_limit: 0,
content: Vec::with_capacity(defs.types.content.len())
},
regions: VecPerParamSpace { regions: VecPerParamSpace {
type_limit: 0, type_limit: 0,
content: Vec::with_capacity(defs.regions.content.len()) content: Vec::with_capacity(num_regions)
},
types: VecPerParamSpace {
type_limit: 0,
content: Vec::with_capacity(num_types)
} }
}; };
for &space in &ParamSpace::all() { substs.fill_item(tcx, defs, &mut mk_region, &mut mk_type);
for def in defs.regions.get_slice(space) {
assert_eq!(def.space, space);
let region = mk_region(def, &substs); Substs::new(tcx, substs.types, substs.regions)
substs.regions.content.push(region); }
if space == TypeSpace { fn fill_item<FR, FT>(&mut self,
substs.regions.type_limit += 1; tcx: TyCtxt<'a, 'gcx, 'tcx>,
} defs: &ty::Generics<'tcx>,
} mk_region: &mut FR,
mk_type: &mut FT)
where FR: FnMut(&ty::RegionParameterDef, &Substs<'tcx>) -> ty::Region,
FT: FnMut(&ty::TypeParameterDef<'tcx>, &Substs<'tcx>) -> Ty<'tcx> {
if let Some(def_id) = defs.parent {
let parent_defs = tcx.lookup_generics(def_id);
self.fill_item(tcx, parent_defs, mk_region, mk_type);
}
for def in defs.types.get_slice(space) { for def in &defs.regions {
assert_eq!(def.space, space); let region = mk_region(def, self);
self.regions.content.push(region);
let ty = mk_type(def, &substs); if def.space == TypeSpace {
substs.types.content.push(ty); self.regions.type_limit += 1;
assert_eq!(self.regions.content.len(), self.regions.type_limit);
if space == TypeSpace {
substs.types.type_limit += 1;
}
} }
} }
Substs::new(tcx, substs.types, substs.regions) for def in &defs.types {
let ty = mk_type(def, self);
self.types.content.push(ty);
if def.space == TypeSpace {
self.types.type_limit += 1;
assert_eq!(self.types.content.len(), self.types.type_limit);
}
}
} }
pub fn is_noop(&self) -> bool { pub fn is_noop(&self) -> bool {
@ -149,16 +162,14 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
target_substs: &Substs<'tcx>) target_substs: &Substs<'tcx>)
-> &'tcx Substs<'tcx> { -> &'tcx Substs<'tcx> {
let defs = tcx.lookup_generics(source_ancestor); let defs = tcx.lookup_generics(source_ancestor);
assert_eq!(self.types.len(TypeSpace), defs.types.len(TypeSpace)); assert_eq!(self.types.len(TypeSpace), defs.types.len());
assert_eq!(target_substs.types.len(FnSpace), 0); assert_eq!(target_substs.types.len(FnSpace), 0);
assert_eq!(defs.types.len(FnSpace), 0); assert_eq!(self.regions.len(TypeSpace), defs.regions.len());
assert_eq!(self.regions.len(TypeSpace), defs.regions.len(TypeSpace));
assert_eq!(target_substs.regions.len(FnSpace), 0); assert_eq!(target_substs.regions.len(FnSpace), 0);
assert_eq!(defs.regions.len(FnSpace), 0);
let Substs { mut types, mut regions } = target_substs.clone(); let Substs { mut types, mut regions } = target_substs.clone();
types.content.extend(&self.types.as_full_slice()[defs.types.content.len()..]); types.content.extend(&self.types.as_full_slice()[defs.types.len()..]);
regions.content.extend(&self.regions.as_full_slice()[defs.regions.content.len()..]); regions.content.extend(&self.regions.as_full_slice()[defs.regions.len()..]);
Substs::new(tcx, types, regions) Substs::new(tcx, types, regions)
} }
} }
@ -597,8 +608,8 @@ impl<'a, 'gcx, 'tcx> ty::TraitRef<'tcx> {
-> ty::TraitRef<'tcx> { -> ty::TraitRef<'tcx> {
let Substs { mut types, mut regions } = substs.clone(); let Substs { mut types, mut regions } = substs.clone();
let defs = tcx.lookup_generics(trait_id); let defs = tcx.lookup_generics(trait_id);
types.content.truncate(defs.types.type_limit); types.content.truncate(defs.types.len());
regions.content.truncate(defs.regions.type_limit); regions.content.truncate(defs.regions.len());
ty::TraitRef { ty::TraitRef {
def_id: trait_id, def_id: trait_id,

View File

@ -73,13 +73,15 @@ pub fn parameterized(f: &mut fmt::Formatter,
let mut has_self = false; let mut has_self = false;
let (fn_trait_kind, item_name) = ty::tls::with(|tcx| { let (fn_trait_kind, item_name) = ty::tls::with(|tcx| {
verbose = tcx.sess.verbose(); verbose = tcx.sess.verbose();
let generics = tcx.lookup_generics(did); let mut generics = tcx.lookup_generics(did);
if let Some(def_id) = generics.parent {
generics = tcx.lookup_generics(def_id);
}
if !verbose { if !verbose {
let ty_params = generics.types.get_slice(subst::TypeSpace); if generics.types.last().map_or(false, |def| def.default.is_some()) {
if ty_params.last().map_or(false, |def| def.default.is_some()) {
if let Some(substs) = tcx.lift(&substs) { if let Some(substs) = tcx.lift(&substs) {
let tps = substs.types.get_slice(subst::TypeSpace); let tps = substs.types.get_slice(subst::TypeSpace);
for (def, actual) in ty_params.iter().zip(tps).rev() { for (def, actual) in generics.types.iter().zip(tps).rev() {
if def.default.subst(tcx, substs) != Some(actual) { if def.default.subst(tcx, substs) != Some(actual) {
break; break;
} }

View File

@ -620,9 +620,9 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
if let Some(impl_item) = impl_item_opt { if let Some(impl_item) = impl_item_opt {
if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
encode_attributes(rbml_w, &impl_item.attrs); encode_attributes(rbml_w, &impl_item.attrs);
let scheme = ecx.tcx.lookup_item_type(m.def_id); let generics = ecx.tcx.lookup_generics(m.def_id);
let any_types = !scheme.generics.types.is_empty(); let types = generics.parent_types as usize + generics.types.len();
let needs_inline = any_types || is_default_impl || let needs_inline = types > 0 || is_default_impl ||
attr::requests_inline(&impl_item.attrs); attr::requests_inline(&impl_item.attrs);
if needs_inline || sig.constness == hir::Constness::Const { if needs_inline || sig.constness == hir::Constness::Const {
encode_inlined_item(ecx, encode_inlined_item(ecx,

View File

@ -149,9 +149,29 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
} }
pub fn parse_generics(&mut self) -> &'tcx ty::Generics<'tcx> { pub fn parse_generics(&mut self) -> &'tcx ty::Generics<'tcx> {
let regions = self.parse_vec_per_param_space(|this| this.parse_region_param_def()); let parent = self.parse_opt(|this| this.parse_def());
let types = self.parse_vec_per_param_space(|this| this.parse_type_param_def()); let parent_regions = self.parse_u32();
assert_eq!(self.next(), '|');
let parent_types = self.parse_u32();
let mut regions = vec![];
assert_eq!(self.next(), '[');
while self.peek() != ']' {
regions.push(self.parse_region_param_def());
}
assert_eq!(self.next(), ']');
let mut types = vec![];
assert_eq!(self.next(), '[');
while self.peek() != ']' {
types.push(self.parse_type_param_def());
}
assert_eq!(self.next(), ']');
self.tcx.alloc_generics(ty::Generics { self.tcx.alloc_generics(ty::Generics {
parent: parent,
parent_regions: parent_regions,
parent_types: parent_types,
regions: regions, regions: regions,
types: types, types: types,
has_self: self.next() == 'S' has_self: self.next() == 'S'

View File

@ -274,10 +274,21 @@ pub fn enc_substs<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
pub fn enc_generics<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>, pub fn enc_generics<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
generics: &ty::Generics<'tcx>) { generics: &ty::Generics<'tcx>) {
enc_vec_per_param_space(w, cx, &generics.regions, enc_opt(w, generics.parent, |w, def_id| {
|w, cx, r| enc_region_param_def(w, cx, r)); write!(w, "{}|", (cx.ds)(cx.tcx, def_id));
enc_vec_per_param_space(w, cx, &generics.types, });
|w, cx, ty| enc_type_param_def(w, cx, ty)); write!(w, "{}|{}[",
generics.parent_regions,
generics.parent_types);
for r in &generics.regions {
enc_region_param_def(w, cx, r)
}
write!(w, "][");
for t in &generics.types {
enc_type_param_def(w, cx, t);
}
write!(w, "]");
if generics.has_self { if generics.has_self {
write!(w, "S"); write!(w, "S");

View File

@ -2470,8 +2470,8 @@ pub fn filter_reachable_ids(tcx: TyCtxt, reachable: NodeSet) -> NodeSet {
hir_map::NodeImplItem(&hir::ImplItem { hir_map::NodeImplItem(&hir::ImplItem {
node: hir::ImplItemKind::Method(..), .. }) => { node: hir::ImplItemKind::Method(..), .. }) => {
let def_id = tcx.map.local_def_id(id); let def_id = tcx.map.local_def_id(id);
let scheme = tcx.lookup_item_type(def_id); let generics = tcx.lookup_generics(def_id);
scheme.generics.types.is_empty() generics.parent_types == 0 && generics.types.is_empty()
} }
_ => false _ => false

View File

@ -195,7 +195,7 @@ use rustc::hir::map as hir_map;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::middle::lang_items::{ExchangeFreeFnLangItem, ExchangeMallocFnLangItem}; use rustc::middle::lang_items::{ExchangeFreeFnLangItem, ExchangeMallocFnLangItem};
use rustc::traits; use rustc::traits;
use rustc::ty::subst::{self, Substs, Subst}; use rustc::ty::subst::{Substs, Subst};
use rustc::ty::{self, TypeFoldable, TyCtxt}; use rustc::ty::{self, TypeFoldable, TyCtxt};
use rustc::ty::adjustment::CustomCoerceUnsized; use rustc::ty::adjustment::CustomCoerceUnsized;
use rustc::mir::repr as mir; use rustc::mir::repr as mir;
@ -1219,17 +1219,16 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id_to_string(tcx, impl_def_id)); def_id_to_string(tcx, impl_def_id));
if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) { if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) {
let default_impls = tcx.provided_trait_methods(trait_ref.def_id);
let callee_substs = tcx.erase_regions(&trait_ref.substs); let callee_substs = tcx.erase_regions(&trait_ref.substs);
let overridden_methods: FnvHashSet<_> = items.iter() let overridden_methods: FnvHashSet<_> = items.iter()
.map(|item| item.name) .map(|item| item.name)
.collect(); .collect();
for default_impl in default_impls { for method in tcx.provided_trait_methods(trait_ref.def_id) {
if overridden_methods.contains(&default_impl.name) { if overridden_methods.contains(&method.name) {
continue; continue;
} }
if default_impl.generics.has_type_params(subst::FnSpace) { if !method.generics.types.is_empty() {
continue; continue;
} }
@ -1242,7 +1241,7 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
callee_substs, callee_substs,
impl_def_id, impl_def_id,
impl_substs, impl_substs,
default_impl.name); method.name);
assert!(mth.is_provided); assert!(mth.is_provided);
@ -1251,10 +1250,10 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
continue; continue;
} }
if can_have_local_instance(tcx, default_impl.def_id) { if can_have_local_instance(tcx, method.def_id) {
let empty_substs = tcx.erase_regions(&mth.substs); let empty_substs = tcx.erase_regions(&mth.substs);
let item = create_fn_trans_item(tcx, let item = create_fn_trans_item(tcx,
default_impl.def_id, method.def_id,
callee_substs, callee_substs,
empty_substs); empty_substs);
output.push(item); output.push(item);

View File

@ -381,10 +381,11 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
// Again, only create type information if full debuginfo is enabled // Again, only create type information if full debuginfo is enabled
let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo { let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo {
generics.types.as_full_slice().iter().enumerate().map(|(i, param)| { let names = get_type_parameter_names(cx, generics);
let actual_type = cx.tcx().normalize_associated_type(&actual_types[i]); actual_types.iter().zip(names).map(|(ty, name)| {
let actual_type = cx.tcx().normalize_associated_type(ty);
let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
let name = CString::new(param.name.as_str().as_bytes()).unwrap(); let name = CString::new(name.as_str().as_bytes()).unwrap();
unsafe { unsafe {
llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
DIB(cx), DIB(cx),
@ -403,6 +404,16 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
return create_DIArray(DIB(cx), &template_params[..]); return create_DIArray(DIB(cx), &template_params[..]);
} }
fn get_type_parameter_names<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
generics: &ty::Generics<'tcx>)
-> Vec<ast::Name> {
let mut names = generics.parent.map_or(vec![], |def_id| {
get_type_parameter_names(cx, cx.tcx().lookup_generics(def_id))
});
names.extend(generics.types.iter().map(|param| param.name));
names
}
fn get_containing_scope_and_span<'ccx, 'tcx>(cx: &CrateContext<'ccx, 'tcx>, fn get_containing_scope_and_span<'ccx, 'tcx>(cx: &CrateContext<'ccx, 'tcx>,
instance: Instance<'tcx>) instance: Instance<'tcx>)
-> (DIScope, Span) { -> (DIScope, Span) {

View File

@ -429,7 +429,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
bug!("ErrorReported returned, but no errors reports?") bug!("ErrorReported returned, but no errors reports?")
} }
}; };
let expected_num_region_params = decl_generics.regions.len(TypeSpace); let expected_num_region_params = decl_generics.regions.len();
let supplied_num_region_params = lifetimes.len(); let supplied_num_region_params = lifetimes.len();
let regions = if expected_num_region_params == supplied_num_region_params { let regions = if expected_num_region_params == supplied_num_region_params {
lifetimes.iter().map(|l| ast_region_to_region(tcx, l)).collect() lifetimes.iter().map(|l| ast_region_to_region(tcx, l)).collect()
@ -454,8 +454,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
// Check the number of type parameters supplied by the user. // Check the number of type parameters supplied by the user.
if let Some(num_provided) = num_types_provided { if let Some(num_provided) = num_types_provided {
let ty_param_defs = decl_generics.types.get_slice(TypeSpace); let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..];
let ty_param_defs = &ty_param_defs[self_ty.is_some() as usize..];
check_type_argument_count(tcx, span, num_provided, ty_param_defs); check_type_argument_count(tcx, span, num_provided, ty_param_defs);
} }

View File

@ -13,7 +13,7 @@ use rustc::infer::{self, InferOk, TypeOrigin};
use rustc::ty; use rustc::ty;
use rustc::traits::{self, Reveal}; use rustc::traits::{self, Reveal};
use rustc::ty::error::ExpectedFound; use rustc::ty::error::ExpectedFound;
use rustc::ty::subst::{self, Subst, Substs}; use rustc::ty::subst::{Subst, Substs};
use rustc::hir::map::Node; use rustc::hir::map::Node;
use rustc::hir::{ImplItemKind, TraitItem_}; use rustc::hir::{ImplItemKind, TraitItem_};
@ -95,8 +95,8 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
} }
} }
let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace); let num_impl_m_type_params = impl_m.generics.types.len();
let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace); let num_trait_m_type_params = trait_m.generics.types.len();
if num_impl_m_type_params != num_trait_m_type_params { if num_impl_m_type_params != num_trait_m_type_params {
span_err!(tcx.sess, impl_m_span, E0049, span_err!(tcx.sess, impl_m_span, E0049,
"method `{}` has {} type parameter{} \ "method `{}` has {} type parameter{} \
@ -389,8 +389,8 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-> bool -> bool
{ {
let trait_params = trait_generics.regions.get_slice(subst::FnSpace); let trait_params = &trait_generics.regions[..];
let impl_params = impl_generics.regions.get_slice(subst::FnSpace); let impl_params = &impl_generics.regions[..];
debug!("check_region_bounds_on_impl_method: \ debug!("check_region_bounds_on_impl_method: \
trait_generics={:?} \ trait_generics={:?} \

View File

@ -49,7 +49,7 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
variadic: false, variadic: false,
}), }),
})); }));
let i_n_tps = i_ty.generics.types.len(subst::FnSpace); let i_n_tps = i_ty.generics.types.len();
if i_n_tps != n_tps { if i_n_tps != n_tps {
struct_span_err!(tcx.sess, it.span, E0094, struct_span_err!(tcx.sess, it.span, E0094,
"intrinsic has wrong number of type \ "intrinsic has wrong number of type \
@ -321,7 +321,7 @@ pub fn check_platform_intrinsic_type(ccx: &CrateCtxt,
let tcx = ccx.tcx; let tcx = ccx.tcx;
let i_ty = tcx.lookup_item_type(tcx.map.local_def_id(it.id)); let i_ty = tcx.lookup_item_type(tcx.map.local_def_id(it.id));
let i_n_tps = i_ty.generics.types.len(subst::FnSpace); let i_n_tps = i_ty.generics.types.len();
let name = it.name.as_str(); let name = it.name.as_str();
let (n_tps, inputs, output) = match &*name { let (n_tps, inputs, output) = match &*name {

View File

@ -308,7 +308,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
// variables. // variables.
let num_supplied_types = supplied_method_types.len(); let num_supplied_types = supplied_method_types.len();
let method = pick.item.as_opt_method().unwrap(); let method = pick.item.as_opt_method().unwrap();
let num_method_types = method.generics.types.len(subst::FnSpace); let num_method_types = method.generics.types.len();
if num_supplied_types > 0 && num_supplied_types != num_method_types { if num_supplied_types > 0 && num_supplied_types != num_method_types {
if num_method_types == 0 { if num_method_types == 0 {

View File

@ -183,15 +183,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let trait_def = self.tcx.lookup_trait_def(trait_def_id); let trait_def = self.tcx.lookup_trait_def(trait_def_id);
if let Some(ref input_types) = opt_input_types { if let Some(ref input_types) = opt_input_types {
assert_eq!(trait_def.generics.types.len(subst::TypeSpace) - 1, input_types.len()); assert_eq!(trait_def.generics.types.len() - 1, input_types.len());
} }
assert_eq!(trait_def.generics.types.len(subst::FnSpace), 0);
assert!(trait_def.generics.regions.is_empty()); assert!(trait_def.generics.regions.is_empty());
// Construct a trait-reference `self_ty : Trait<input_tys>` // Construct a trait-reference `self_ty : Trait<input_tys>`
let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| { let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| {
self.region_var_for_def(span, def) self.region_var_for_def(span, def)
}, |def, substs| { }, |def, substs| {
assert_eq!(def.space, subst::TypeSpace);
if def.index == 0 { if def.index == 0 {
self_ty self_ty
} else if let Some(ref input_types) = opt_input_types { } else if let Some(ref input_types) = opt_input_types {
@ -221,8 +221,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let tcx = self.tcx; let tcx = self.tcx;
let method_item = self.trait_item(trait_def_id, m_name).unwrap(); let method_item = self.trait_item(trait_def_id, m_name).unwrap();
let method_ty = method_item.as_opt_method().unwrap(); let method_ty = method_item.as_opt_method().unwrap();
assert_eq!(method_ty.generics.types.len(subst::FnSpace), 0); assert_eq!(method_ty.generics.types.len(), 0);
assert_eq!(method_ty.generics.regions.len(subst::FnSpace), 0); assert_eq!(method_ty.generics.regions.len(), 0);
debug!("lookup_in_trait_adjusted: method_item={:?} method_ty={:?}", debug!("lookup_in_trait_adjusted: method_item={:?} method_ty={:?}",
method_item, method_ty); method_item, method_ty);

View File

@ -518,9 +518,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
trait_ref, trait_ref,
trait_ref.substs, trait_ref.substs,
m); m);
assert_eq!(m.generics.types.len(subst::TypeSpace), assert_eq!(m.generics.parent_types as usize,
trait_ref.substs.types.len(subst::TypeSpace)); trait_ref.substs.types.len(subst::TypeSpace));
assert_eq!(m.generics.regions.len(subst::TypeSpace), assert_eq!(m.generics.parent_regions as usize,
trait_ref.substs.regions.len(subst::TypeSpace)); trait_ref.substs.regions.len(subst::TypeSpace));
} }
@ -1232,8 +1232,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
let xform_self_ty = method.fty.sig.input(0); let xform_self_ty = method.fty.sig.input(0);
let xform_self_ty = self.erase_late_bound_regions(&xform_self_ty); let xform_self_ty = self.erase_late_bound_regions(&xform_self_ty);
if method.generics.types.is_empty_in(subst::FnSpace) && if method.generics.types.is_empty() && method.generics.regions.is_empty() {
method.generics.regions.is_empty_in(subst::FnSpace) {
xform_self_ty.subst(self.tcx, substs) xform_self_ty.subst(self.tcx, substs)
} else { } else {
let substs = Substs::for_item(self.tcx, method.def_id, |def, _| { let substs = Substs::for_item(self.tcx, method.def_id, |def, _| {
@ -1260,17 +1259,13 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
impl_def_id: DefId) impl_def_id: DefId)
-> (Ty<'tcx>, &'tcx Substs<'tcx>) -> (Ty<'tcx>, &'tcx Substs<'tcx>)
{ {
let impl_pty = self.tcx.lookup_item_type(impl_def_id); let impl_ty = self.tcx.lookup_item_type(impl_def_id).ty;
let type_vars = let substs = Substs::for_item(self.tcx, impl_def_id,
impl_pty.generics.types.map( |_, _| ty::ReErased,
|_| self.next_ty_var()); |_, _| self.next_ty_var());
let region_placeholders = (impl_ty, substs)
impl_pty.generics.regions.map(
|_| ty::ReErased); // see erase_late_bound_regions() for an expl of why 'erased
(impl_pty.ty, Substs::new(self.tcx, type_vars, region_placeholders))
} }
/// Replace late-bound-regions bound by `value` with `'static` using /// Replace late-bound-regions bound by `value` with `'static` using

View File

@ -881,8 +881,7 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
// `{Self}` is allowed // `{Self}` is allowed
Position::ArgumentNamed(s) if s == "Self" => (), Position::ArgumentNamed(s) if s == "Self" => (),
// So is `{A}` if A is a type parameter // So is `{A}` if A is a type parameter
Position::ArgumentNamed(s) => match types.as_full_slice() Position::ArgumentNamed(s) => match types.iter().find(|t| {
.iter().find(|t| {
t.name.as_str() == s t.name.as_str() == s
}) { }) {
Some(_) => (), Some(_) => (),
@ -1693,7 +1692,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let mut ty = self.tcx.lookup_item_type(did).ty; let mut ty = self.tcx.lookup_item_type(did).ty;
if ty.is_fn() { if ty.is_fn() {
// Tuple variants have fn type even in type namespace, extract true variant type from it // Tuple variants have fn type even in type namespace, extract true variant type from it
ty = self.tcx.no_late_bound_regions(&type_scheme.ty.fn_ret()).unwrap(); ty = self.tcx.no_late_bound_regions(&ty.fn_ret()).unwrap();
} }
let type_predicates = self.tcx.lookup_predicates(did); let type_predicates = self.tcx.lookup_predicates(did);
let substs = AstConv::ast_path_substs_for_ty(self, self, let substs = AstConv::ast_path_substs_for_ty(self, self,
@ -3222,13 +3221,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
self.set_tainted_by_errors(); self.set_tainted_by_errors();
return None; return None;
} }
Def::Variant(..) | Def::Struct(..) => { Def::Variant(type_did, _) | Def::Struct(type_did) => {
Some(self.tcx.expect_variant_def(def)) Some((type_did, self.tcx.expect_variant_def(def)))
} }
Def::TyAlias(did) | Def::AssociatedTy(_, did) => { Def::TyAlias(did) => {
if let Some(&ty::TyStruct(adt, _)) = self.tcx.opt_lookup_item_type(did) if let Some(&ty::TyStruct(adt, _)) = self.tcx.opt_lookup_item_type(did)
.map(|scheme| &scheme.ty.sty) { .map(|scheme| &scheme.ty.sty) {
Some(adt.struct_variant()) Some((did, adt.struct_variant()))
} else { } else {
None None
} }
@ -3236,14 +3235,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
_ => None _ => None
}; };
if let Some(variant) = variant { if let Some((def_id, variant)) = variant {
if variant.kind == ty::VariantKind::Tuple && if variant.kind == ty::VariantKind::Tuple &&
!self.tcx.sess.features.borrow().relaxed_adts { !self.tcx.sess.features.borrow().relaxed_adts {
emit_feature_err(&self.tcx.sess.parse_sess.span_diagnostic, emit_feature_err(&self.tcx.sess.parse_sess.span_diagnostic,
"relaxed_adts", span, GateIssue::Language, "relaxed_adts", span, GateIssue::Language,
"tuple structs and variants in struct patterns are unstable"); "tuple structs and variants in struct patterns are unstable");
} }
let ty = self.instantiate_type_path(def.def_id(), path, node_id); let ty = self.instantiate_type_path(def_id, path, node_id);
Some((variant, ty)) Some((variant, ty))
} else { } else {
struct_span_err!(self.tcx.sess, path.span, E0071, struct_span_err!(self.tcx.sess, path.span, E0071,
@ -4122,25 +4121,29 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let mut fn_segment = None; let mut fn_segment = None;
match def { match def {
// Case 1 and 1b. Reference to a *type* or *enum variant*. // Case 1 and 1b. Reference to a *type* or *enum variant*.
Def::SelfTy(..) | Def::Struct(def_id) |
Def::Struct(..) | Def::Variant(_, def_id) |
Def::Variant(..) | Def::Enum(def_id) |
Def::Enum(..) | Def::TyAlias(def_id) |
Def::TyAlias(..) | Def::AssociatedTy(_, def_id) |
Def::AssociatedTy(..) | Def::Trait(def_id) => {
Def::Trait(..) |
Def::PrimTy(..) |
Def::TyParam(..) => {
// Everything but the final segment should have no // Everything but the final segment should have no
// parameters at all. // parameters at all.
type_segment = segments.last(); let mut generics = self.tcx.lookup_generics(def_id);
if let Some(def_id) = generics.parent {
// Variant and struct constructors use the
// generics of their parent type definition.
generics = self.tcx.lookup_generics(def_id);
}
type_segment = Some((segments.last().unwrap(), generics));
} }
// Case 2. Reference to a top-level value. // Case 2. Reference to a top-level value.
Def::Fn(..) | Def::Fn(def_id) |
Def::Const(..) | Def::Const(def_id) |
Def::Static(..) => { Def::Static(def_id, _) => {
fn_segment = segments.last(); fn_segment = Some((segments.last().unwrap(),
self.tcx.lookup_generics(def_id)));
} }
// Case 3. Reference to a method or associated const. // Case 3. Reference to a method or associated const.
@ -4154,14 +4157,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
ty::ImplContainer(_) => {} ty::ImplContainer(_) => {}
} }
let generics = self.tcx.lookup_generics(def_id);
if segments.len() >= 2 { if segments.len() >= 2 {
type_segment = Some(&segments[segments.len() - 2]); let parent_generics = self.tcx.lookup_generics(generics.parent.unwrap());
type_segment = Some((&segments[segments.len() - 2], parent_generics));
} else { } else {
// `<T>::assoc` will end up here, and so can `T::assoc`. // `<T>::assoc` will end up here, and so can `T::assoc`.
let self_ty = opt_self_ty.expect("UFCS sugared assoc missing Self"); let self_ty = opt_self_ty.expect("UFCS sugared assoc missing Self");
ufcs_associated = Some((container, self_ty)); ufcs_associated = Some((container, self_ty));
} }
fn_segment = segments.last(); fn_segment = Some((segments.last().unwrap(), generics));
} }
// Other cases. Various nonsense that really shouldn't show up // Other cases. Various nonsense that really shouldn't show up
@ -4169,6 +4174,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// elsewhere. (I hope) // elsewhere. (I hope)
Def::Mod(..) | Def::Mod(..) |
Def::ForeignMod(..) | Def::ForeignMod(..) |
Def::PrimTy(..) |
Def::SelfTy(..) |
Def::TyParam(..) |
Def::Local(..) | Def::Local(..) |
Def::Label(..) | Def::Label(..) |
Def::Upvar(..) | Def::Upvar(..) |
@ -4213,12 +4221,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// a problem. // a problem.
self.check_path_parameter_count(subst::TypeSpace, self.check_path_parameter_count(subst::TypeSpace,
span, span,
scheme.generics,
!require_type_space, !require_type_space,
&mut type_segment); &mut type_segment);
self.check_path_parameter_count(subst::FnSpace, self.check_path_parameter_count(subst::FnSpace,
span, span,
scheme.generics,
true, true,
&mut fn_segment); &mut fn_segment);
@ -4228,7 +4234,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
subst::TypeSpace => type_segment, subst::TypeSpace => type_segment,
subst::FnSpace => fn_segment subst::FnSpace => fn_segment
}; };
let lifetimes = match segment.map(|s| &s.parameters) { let lifetimes = match segment.map(|(s, _)| &s.parameters) {
Some(&hir::AngleBracketedParameters(ref data)) => &data.lifetimes[..], Some(&hir::AngleBracketedParameters(ref data)) => &data.lifetimes[..],
Some(&hir::ParenthesizedParameters(_)) => bug!(), Some(&hir::ParenthesizedParameters(_)) => bug!(),
None => &[] None => &[]
@ -4242,25 +4248,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}, |def, substs| { }, |def, substs| {
let mut i = def.index as usize; let mut i = def.index as usize;
let segment = match def.space { let segment = match def.space {
subst::TypeSpace => type_segment, subst::TypeSpace => {
// Handle Self first, so we can adjust the index to match the AST.
match (type_segment, fn_segment) {
(Some((_, generics)), _) | (_, Some((_, generics))) => {
if generics.has_self {
if i == 0 {
return opt_self_ty.unwrap_or_else(|| {
self.type_var_for_def(span, def, substs)
});
}
i -= 1;
}
}
_ => {}
}
type_segment
}
subst::FnSpace => fn_segment subst::FnSpace => fn_segment
}; };
let types = match segment.map(|s| &s.parameters) { let types = match segment.map(|(s, _)| &s.parameters) {
Some(&hir::AngleBracketedParameters(ref data)) => &data.types[..], Some(&hir::AngleBracketedParameters(ref data)) => &data.types[..],
Some(&hir::ParenthesizedParameters(_)) => bug!(), Some(&hir::ParenthesizedParameters(_)) => bug!(),
None => &[] None => &[]
}; };
// Handle Self first, so we can adjust the index to match the AST.
if scheme.generics.has_self && def.space == subst::TypeSpace {
if i == 0 {
return opt_self_ty.unwrap_or_else(|| {
self.type_var_for_def(span, def, substs)
});
}
i -= 1;
}
let can_omit = def.space != subst::TypeSpace || !require_type_space; let can_omit = def.space != subst::TypeSpace || !require_type_space;
let default = if can_omit && types.len() == 0 { let default = if can_omit && types.len() == 0 {
def.default def.default
@ -4306,9 +4318,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// with the substituted impl type. // with the substituted impl type.
let impl_scheme = self.tcx.lookup_item_type(impl_def_id); let impl_scheme = self.tcx.lookup_item_type(impl_def_id);
assert_eq!(substs.types.len(subst::TypeSpace), assert_eq!(substs.types.len(subst::TypeSpace),
impl_scheme.generics.types.len(subst::TypeSpace)); impl_scheme.generics.types.len());
assert_eq!(substs.regions.len(subst::TypeSpace), assert_eq!(substs.regions.len(subst::TypeSpace),
impl_scheme.generics.regions.len(subst::TypeSpace)); impl_scheme.generics.regions.len());
let impl_ty = self.instantiate_type_scheme(span, &substs, &impl_scheme.ty); let impl_ty = self.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
match self.sub_types(false, TypeOrigin::Misc(span), self_ty, impl_ty) { match self.sub_types(false, TypeOrigin::Misc(span), self_ty, impl_ty) {
@ -4339,10 +4351,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
fn check_path_parameter_count(&self, fn check_path_parameter_count(&self,
space: subst::ParamSpace, space: subst::ParamSpace,
span: Span, span: Span,
generics: &ty::Generics<'tcx>,
can_omit: bool, can_omit: bool,
segment: &mut Option<&hir::PathSegment>) { segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) {
let (lifetimes, types, bindings) = match segment.map(|s| &s.parameters) { let (lifetimes, types, bindings) = match segment.map(|(s, _)| &s.parameters) {
Some(&hir::AngleBracketedParameters(ref data)) => { Some(&hir::AngleBracketedParameters(ref data)) => {
(&data.lifetimes[..], &data.types[..], &data.bindings[..]) (&data.lifetimes[..], &data.types[..], &data.bindings[..])
} }
@ -4357,7 +4368,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}; };
// Check provided lifetime parameters. // Check provided lifetime parameters.
let lifetime_defs = generics.regions.get_slice(space); let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions);
if lifetimes.len() > lifetime_defs.len() { if lifetimes.len() > lifetime_defs.len() {
let span = lifetimes[lifetime_defs.len()].span; let span = lifetimes[lifetime_defs.len()].span;
span_err!(self.tcx.sess, span, E0088, span_err!(self.tcx.sess, span, E0088,
@ -4374,12 +4385,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
// Check provided type parameters. // Check provided type parameters.
let type_defs = generics.types.get_slice(space); let type_defs = segment.map_or(&[][..], |(_, generics)| {
let type_defs = if space == subst::TypeSpace { if space == subst::TypeSpace {
&type_defs[generics.has_self as usize..] &generics.types[generics.has_self as usize..]
} else { } else {
type_defs &generics.types
}; }
});
let required_len = type_defs.iter() let required_len = type_defs.iter()
.take_while(|d| d.default.is_none()) .take_while(|d| d.default.is_none())
.count(); .count();

View File

@ -523,10 +523,10 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
} }
fn reject_shadowing_type_parameters(tcx: TyCtxt, span: Span, generics: &ty::Generics) { fn reject_shadowing_type_parameters(tcx: TyCtxt, span: Span, generics: &ty::Generics) {
let impl_params = generics.types.get_slice(subst::TypeSpace).iter() let parent = tcx.lookup_generics(generics.parent.unwrap());
.map(|tp| tp.name).collect::<HashSet<_>>(); let impl_params: HashSet<_> = parent.types.iter().map(|tp| tp.name).collect();
for method_param in generics.types.get_slice(subst::FnSpace) { for method_param in &generics.types {
if impl_params.contains(&method_param.name) { if impl_params.contains(&method_param.name) {
error_194(tcx, span, method_param.name); error_194(tcx, span, method_param.name);
} }

View File

@ -65,7 +65,7 @@ use middle::lang_items::SizedTraitLangItem;
use middle::const_val::ConstVal; use middle::const_val::ConstVal;
use rustc_const_eval::EvalHint::UncheckedExprHint; use rustc_const_eval::EvalHint::UncheckedExprHint;
use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err}; use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err};
use rustc::ty::subst::{Substs, FnSpace, ParamSpace, TypeSpace, VecPerParamSpace}; use rustc::ty::subst::{Substs, FnSpace, ParamSpace, TypeSpace};
use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}; use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme}; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme};
use rustc::ty::{VariantKind}; use rustc::ty::{VariantKind};
@ -793,9 +793,11 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
} }
if let hir::ImplItemKind::Const(ref ty, _) = impl_item.node { if let hir::ImplItemKind::Const(ref ty, _) = impl_item.node {
let const_def_id = ccx.tcx.map.local_def_id(impl_item.id);
let ty_generics = generics_of_def_id(ccx, const_def_id);
let ty = ccx.icx(&ty_predicates) let ty = ccx.icx(&ty_predicates)
.to_ty(&ExplicitRscope, &ty); .to_ty(&ExplicitRscope, &ty);
tcx.register_item_type(ccx.tcx.map.local_def_id(impl_item.id), tcx.register_item_type(const_def_id,
TypeScheme { TypeScheme {
generics: ty_generics, generics: ty_generics,
ty: ty, ty: ty,
@ -858,11 +860,13 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
// Convert all the associated constants. // Convert all the associated constants.
for trait_item in trait_items { for trait_item in trait_items {
if let hir::ConstTraitItem(ref ty, ref default) = trait_item.node { if let hir::ConstTraitItem(ref ty, ref default) = trait_item.node {
let const_def_id = ccx.tcx.map.local_def_id(trait_item.id);
let ty_generics = generics_of_def_id(ccx, const_def_id);
let ty = ccx.icx(&trait_predicates) let ty = ccx.icx(&trait_predicates)
.to_ty(&ExplicitRscope, ty); .to_ty(&ExplicitRscope, ty);
tcx.register_item_type(ccx.tcx.map.local_def_id(trait_item.id), tcx.register_item_type(const_def_id,
TypeScheme { TypeScheme {
generics: trait_def.generics, generics: ty_generics,
ty: ty, ty: ty,
}); });
convert_associated_const(ccx, convert_associated_const(ccx,
@ -957,7 +961,7 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
predicates: ty::GenericPredicates<'tcx>) { predicates: ty::GenericPredicates<'tcx>) {
let tcx = ccx.tcx; let tcx = ccx.tcx;
let def_id = tcx.map.local_def_id(ctor_id); let def_id = tcx.map.local_def_id(ctor_id);
tcx.generics.borrow_mut().insert(def_id, scheme.generics); generics_of_def_id(ccx, def_id);
let ctor_ty = match variant.kind { let ctor_ty = match variant.kind {
VariantKind::Unit | VariantKind::Struct => scheme.ty, VariantKind::Unit | VariantKind::Struct => scheme.ty,
VariantKind::Tuple => { VariantKind::Tuple => {
@ -1389,24 +1393,35 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
use rustc::hir::map::*; use rustc::hir::map::*;
use rustc::hir::*; use rustc::hir::*;
let node = tcx.map.get(node_id);
let parent_def_id = match node {
NodeImplItem(_) |
NodeTraitItem(_) |
NodeVariant(_) |
NodeStructCtor(_) => {
let parent_id = tcx.map.get_parent(node_id);
Some(tcx.map.local_def_id(parent_id))
}
_ => None
};
let mut opt_self = None; let mut opt_self = None;
let mut base_def_id = None;
let mut allow_defaults = false; let mut allow_defaults = false;
let no_generics = hir::Generics::empty(); let no_generics = hir::Generics::empty();
let (space, ast_generics) = match tcx.map.get(node_id) { let (space, ast_generics) = match node {
NodeImplItem(&ImplItem { node: ImplItemKind::Method(ref sig, _), .. }) | NodeTraitItem(item) => {
NodeTraitItem(&TraitItem { node: MethodTraitItem(ref sig, _), .. }) => { match item.node {
let parent_id = tcx.map.get_parent(node_id); MethodTraitItem(ref sig, _) => (FnSpace, &sig.generics),
base_def_id = Some(tcx.map.local_def_id(parent_id)); _ => (FnSpace, &no_generics)
(FnSpace, &sig.generics) }
} }
NodeImplItem(_) | NodeImplItem(item) => {
NodeTraitItem(_) => { match item.node {
let parent_id = tcx.map.get_parent(node_id); ImplItemKind::Method(ref sig, _) => (FnSpace, &sig.generics),
base_def_id = Some(tcx.map.local_def_id(parent_id)); _ => (FnSpace, &no_generics)
(FnSpace, &no_generics) }
} }
NodeItem(item) => { NodeItem(item) => {
@ -1457,9 +1472,16 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
_ => (TypeSpace, &no_generics) _ => (TypeSpace, &no_generics)
}; };
let empty_generics = ty::Generics::empty(); let has_self = opt_self.is_some();
let base_generics = base_def_id.map_or(&empty_generics, |def_id| { let mut parent_has_self = false;
generics_of_def_id(ccx, def_id) let (parent_regions, parent_types) = parent_def_id.map_or((0, 0), |def_id| {
let generics = generics_of_def_id(ccx, def_id);
assert_eq!(generics.parent, None);
assert_eq!(generics.parent_regions, 0);
assert_eq!(generics.parent_types, 0);
assert_eq!(has_self, false);
parent_has_self = generics.has_self;
(generics.regions.len(), generics.types.len())
}); });
let early_lifetimes = early_bound_lifetimes_from_generics(ccx, ast_generics); let early_lifetimes = early_bound_lifetimes_from_generics(ccx, ast_generics);
@ -1477,32 +1499,15 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
// Now create the real type parameters. // Now create the real type parameters.
let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| { let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| {
let i = opt_self.is_some() as u32 + i as u32; let i = has_self as u32 + i as u32;
get_or_create_type_parameter_def(ccx, ast_generics, space, i, p, allow_defaults) get_or_create_type_parameter_def(ccx, ast_generics, space, i, p, allow_defaults)
}).collect(); });
let types: Vec<_> = opt_self.into_iter().chain(types).collect();
let has_self = base_generics.has_self || opt_self.is_some();
let (regions, types) = match space {
TypeSpace => {
assert_eq!(base_generics.regions.as_full_slice().len(), 0);
assert_eq!(base_generics.types.as_full_slice().len(), 0);
(VecPerParamSpace::new(regions, vec![]),
VecPerParamSpace::new(opt_self.into_iter().chain(types).collect(), vec![]))
}
FnSpace => {
assert_eq!(base_generics.regions.len(FnSpace), 0);
assert_eq!(base_generics.types.len(FnSpace), 0);
(VecPerParamSpace::new(base_generics.regions.get_slice(TypeSpace).to_vec(),
regions),
VecPerParamSpace::new(base_generics.types.get_slice(TypeSpace).to_vec(),
types))
}
};
// Debugging aid. // Debugging aid.
if tcx.has_attr(def_id, "rustc_object_lifetime_default") { if tcx.has_attr(def_id, "rustc_object_lifetime_default") {
let object_lifetime_default_reprs: String = let object_lifetime_default_reprs: String =
types.as_full_slice().iter().map(|t| { types.iter().map(|t| {
match t.object_lifetime_default { match t.object_lifetime_default {
ty::ObjectLifetimeDefault::Specific(r) => r.to_string(), ty::ObjectLifetimeDefault::Specific(r) => r.to_string(),
d => format!("{:?}", d), d => format!("{:?}", d),
@ -1512,9 +1517,12 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
} }
tcx.alloc_generics(ty::Generics { tcx.alloc_generics(ty::Generics {
parent: parent_def_id,
parent_regions: parent_regions as u32,
parent_types: parent_types as u32,
regions: regions, regions: regions,
types: types, types: types,
has_self: has_self has_self: has_self || parent_has_self
}) })
}) })
} }
@ -2148,7 +2156,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
&mut input_parameters); &mut input_parameters);
let ty_generics = generics_of_def_id(ccx, impl_def_id); let ty_generics = generics_of_def_id(ccx, impl_def_id);
for (ty_param, param) in ty_generics.types.as_full_slice().iter().zip(&generics.ty_params) { for (ty_param, param) in ty_generics.types.iter().zip(&generics.ty_params) {
let param_ty = ty::ParamTy::for_def(ty_param); let param_ty = ty::ParamTy::for_def(ty_param);
if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) { if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) {
report_unused_parameter(ccx, param.span, "type", &param_ty.to_string()); report_unused_parameter(ccx, param.span, "type", &param_ty.to_string());

View File

@ -301,8 +301,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
self.add_constraints_from_substs( self.add_constraints_from_substs(
generics, generics,
trait_ref.def_id, trait_ref.def_id,
trait_def.generics.types.as_full_slice(), &trait_def.generics.types,
trait_def.generics.regions.as_full_slice(), &trait_def.generics.regions,
trait_ref.substs, trait_ref.substs,
variance); variance);
} }
@ -359,16 +359,11 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
// README.md for a discussion on dep-graph management. // README.md for a discussion on dep-graph management.
self.tcx().dep_graph.read(ItemVariances::to_dep_node(&def.did)); self.tcx().dep_graph.read(ItemVariances::to_dep_node(&def.did));
// All type parameters on enums and structs should be
// in the TypeSpace.
assert!(item_type.generics.types.is_empty_in(subst::FnSpace));
assert!(item_type.generics.regions.is_empty_in(subst::FnSpace));
self.add_constraints_from_substs( self.add_constraints_from_substs(
generics, generics,
def.did, def.did,
item_type.generics.types.as_full_slice(), &item_type.generics.types,
item_type.generics.regions.as_full_slice(), &item_type.generics.regions,
substs, substs,
variance); variance);
} }
@ -385,8 +380,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
self.add_constraints_from_substs( self.add_constraints_from_substs(
generics, generics,
trait_ref.def_id, trait_ref.def_id,
trait_def.generics.types.as_full_slice(), &trait_def.generics.types,
trait_def.generics.regions.as_full_slice(), &trait_def.generics.regions,
trait_ref.substs, trait_ref.substs,
variance); variance);
} }
@ -406,7 +401,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
} }
ty::TyParam(ref data) => { ty::TyParam(ref data) => {
let def_id = generics.types.get(data.space, data.idx as usize).def_id; assert_eq!(data.space, subst::TypeSpace);
assert_eq!(generics.parent, None);
let def_id = generics.types[data.idx as usize].def_id;
let node_id = self.tcx().map.as_local_node_id(def_id).unwrap(); let node_id = self.tcx().map.as_local_node_id(def_id).unwrap();
match self.terms_cx.inferred_map.get(&node_id) { match self.terms_cx.inferred_map.get(&node_id) {
Some(&index) => { Some(&index) => {
@ -493,8 +490,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
variance: VarianceTermPtr<'a>) { variance: VarianceTermPtr<'a>) {
match region { match region {
ty::ReEarlyBound(ref data) => { ty::ReEarlyBound(ref data) => {
let def_id = assert_eq!(data.space, subst::TypeSpace);
generics.regions.get(data.space, data.index as usize).def_id; assert_eq!(generics.parent, None);
let def_id = generics.regions[data.index as usize].def_id;
let node_id = self.tcx().map.as_local_node_id(def_id).unwrap(); let node_id = self.tcx().map.as_local_node_id(def_id).unwrap();
if self.is_to_be_inferred(node_id) { if self.is_to_be_inferred(node_id) {
let index = self.inferred_index(node_id); let index = self.inferred_index(node_id);

View File

@ -21,7 +21,6 @@ use rustc::hir::def::Def;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::hir::print as pprust; use rustc::hir::print as pprust;
use rustc::ty::{self, TyCtxt}; use rustc::ty::{self, TyCtxt};
use rustc::ty::subst;
use rustc_const_eval::lookup_const_by_id; use rustc_const_eval::lookup_const_by_id;
@ -161,7 +160,7 @@ pub fn build_external_trait<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tc
let def = tcx.lookup_trait_def(did); let def = tcx.lookup_trait_def(did);
let trait_items = tcx.trait_items(did).clean(cx); let trait_items = tcx.trait_items(did).clean(cx);
let predicates = tcx.lookup_predicates(did); let predicates = tcx.lookup_predicates(did);
let generics = (def.generics, &predicates, subst::TypeSpace).clean(cx); let generics = (def.generics, &predicates).clean(cx);
let generics = filter_non_trait_generics(did, generics); let generics = filter_non_trait_generics(did, generics);
let (generics, supertrait_bounds) = separate_supertrait_bounds(generics); let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
clean::Trait { clean::Trait {
@ -189,7 +188,7 @@ fn build_external_function<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx
let predicates = tcx.lookup_predicates(did); let predicates = tcx.lookup_predicates(did);
clean::Function { clean::Function {
decl: decl, decl: decl,
generics: (t.generics, &predicates, subst::FnSpace).clean(cx), generics: (t.generics, &predicates).clean(cx),
unsafety: style, unsafety: style,
constness: constness, constness: constness,
abi: abi, abi: abi,
@ -209,7 +208,7 @@ fn build_struct<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
&[..] if variant.kind == ty::VariantKind::Tuple => doctree::Tuple, &[..] if variant.kind == ty::VariantKind::Tuple => doctree::Tuple,
_ => doctree::Plain, _ => doctree::Plain,
}, },
generics: (t.generics, &predicates, subst::TypeSpace).clean(cx), generics: (t.generics, &predicates).clean(cx),
fields: variant.fields.clean(cx), fields: variant.fields.clean(cx),
fields_stripped: false, fields_stripped: false,
} }
@ -222,7 +221,7 @@ fn build_type<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
match t.ty.sty { match t.ty.sty {
ty::TyEnum(edef, _) if !tcx.sess.cstore.is_typedef(did) => { ty::TyEnum(edef, _) if !tcx.sess.cstore.is_typedef(did) => {
return clean::EnumItem(clean::Enum { return clean::EnumItem(clean::Enum {
generics: (t.generics, &predicates, subst::TypeSpace).clean(cx), generics: (t.generics, &predicates).clean(cx),
variants_stripped: false, variants_stripped: false,
variants: edef.variants.clean(cx), variants: edef.variants.clean(cx),
}) })
@ -232,7 +231,7 @@ fn build_type<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
clean::TypedefItem(clean::Typedef { clean::TypedefItem(clean::Typedef {
type_: t.ty.clean(cx), type_: t.ty.clean(cx),
generics: (t.generics, &predicates, subst::TypeSpace).clean(cx), generics: (t.generics, &predicates).clean(cx),
}, false) }, false)
} }
@ -393,9 +392,11 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext,
// because an associated type won't have generics on the LHS // because an associated type won't have generics on the LHS
let typedef = clean::Typedef { let typedef = clean::Typedef {
type_: assoc_ty.ty.unwrap().clean(cx), type_: assoc_ty.ty.unwrap().clean(cx),
generics: (&ty::Generics::empty(), generics: clean::Generics {
&ty::GenericPredicates::empty(), lifetimes: vec![],
subst::TypeSpace).clean(cx) type_params: vec![],
where_predicates: vec![]
}
}; };
Some(clean::Item { Some(clean::Item {
name: Some(assoc_ty.name.clean(cx)), name: Some(assoc_ty.name.clean(cx)),
@ -434,7 +435,7 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext,
provided_trait_methods: provided, provided_trait_methods: provided,
trait_: trait_, trait_: trait_,
for_: for_, for_: for_,
generics: (ty.generics, &predicates, subst::TypeSpace).clean(cx), generics: (ty.generics, &predicates).clean(cx),
items: trait_items, items: trait_items,
polarity: polarity.map(|p| { p.clean(cx) }), polarity: polarity.map(|p| { p.clean(cx) }),
}), }),

View File

@ -973,17 +973,16 @@ impl Clean<Generics> for hir::Generics {
} }
impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>, impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
&'a ty::GenericPredicates<'tcx>, &'a ty::GenericPredicates<'tcx>) {
subst::ParamSpace) {
fn clean(&self, cx: &DocContext) -> Generics { fn clean(&self, cx: &DocContext) -> Generics {
use self::WherePredicate as WP; use self::WherePredicate as WP;
let (gens, preds, space) = *self; let (gens, preds) = *self;
// Bounds in the type_params and lifetimes fields are repeated in the // Bounds in the type_params and lifetimes fields are repeated in the
// predicates field (see rustc_typeck::collect::ty_generics), so remove // predicates field (see rustc_typeck::collect::ty_generics), so remove
// them. // them.
let stripped_typarams = gens.types.get_slice(space).iter().filter_map(|tp| { let stripped_typarams = gens.types.iter().filter_map(|tp| {
if tp.name == keywords::SelfType.name() { if tp.name == keywords::SelfType.name() {
assert_eq!(tp.index, 0); assert_eq!(tp.index, 0);
None None
@ -991,7 +990,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
Some(tp.clean(cx)) Some(tp.clean(cx))
} }
}).collect::<Vec<_>>(); }).collect::<Vec<_>>();
let stripped_lifetimes = gens.regions.get_slice(space).iter().map(|rp| { let stripped_lifetimes = gens.regions.iter().map(|rp| {
let mut srp = rp.clone(); let mut srp = rp.clone();
srp.bounds = Vec::new(); srp.bounds = Vec::new();
srp.clean(cx) srp.clean(cx)
@ -1359,8 +1358,7 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
predicates: self.predicates.predicates[method_start..].to_vec() predicates: self.predicates.predicates[method_start..].to_vec()
}; };
let generics = (self.generics, &method_predicates, let generics = (self.generics, &method_predicates).clean(cx);
subst::FnSpace).clean(cx);
let mut decl = (self.def_id, &self.fty.sig).clean(cx); let mut decl = (self.def_id, &self.fty.sig).clean(cx);
match self.explicit_self { match self.explicit_self {
ty::ExplicitSelfCategory::ByValue => { ty::ExplicitSelfCategory::ByValue => {
@ -2929,7 +2927,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedType<'tcx> {
// applied to this associated type in question. // applied to this associated type in question.
let def = cx.tcx().lookup_trait_def(did); let def = cx.tcx().lookup_trait_def(did);
let predicates = cx.tcx().lookup_predicates(did); let predicates = cx.tcx().lookup_predicates(did);
let generics = (def.generics, &predicates, subst::TypeSpace).clean(cx); let generics = (def.generics, &predicates).clean(cx);
generics.where_predicates.iter().filter_map(|pred| { generics.where_predicates.iter().filter_map(|pred| {
let (name, self_type, trait_, bounds) = match *pred { let (name, self_type, trait_, bounds) = match *pred {
WherePredicate::BoundPredicate { WherePredicate::BoundPredicate {