rustc: store type parameter defaults outside of ty::Generics.

This commit is contained in:
Eduard-Mihai Burtescu 2017-01-25 22:01:11 +02:00
parent 1572bf104d
commit e8d01ea4c7
34 changed files with 394 additions and 385 deletions

View File

@ -525,7 +525,7 @@ impl<'a> LoweringContext<'a> {
return n;
}
assert!(!def_id.is_local());
let (n, _) = self.sess.cstore.item_generics_own_param_counts(def_id);
let n = self.sess.cstore.item_generics(def_id).regions.len();
self.type_def_lifetime_params.insert(def_id, n);
n
});

View File

@ -1197,16 +1197,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
/// as the substitutions for the default, `(T, U)`.
pub fn type_var_for_def(&self,
span: Span,
def: &ty::TypeParameterDef<'tcx>,
def: &ty::TypeParameterDef,
substs: &[Kind<'tcx>])
-> Ty<'tcx> {
let default = def.default.map(|default| {
type_variable::Default {
let default = if def.has_default {
let default = self.tcx.item_type(def.def_id);
Some(type_variable::Default {
ty: default.subst_spanned(self.tcx, substs, Some(span)),
origin_span: span,
def_id: def.default_def_id
}
});
def_id: def.def_id
})
} else {
None
};
let ty_var_id = self.type_variables

View File

@ -28,7 +28,6 @@ use hir::map as hir_map;
use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData};
use hir::svh::Svh;
use middle::lang_items;
use middle::resolve_lifetime::ObjectLifetimeDefault;
use ty::{self, Ty, TyCtxt};
use mir::Mir;
use session::Session;
@ -182,11 +181,7 @@ pub trait CrateStore<'tcx> {
-> ty::GenericPredicates<'tcx>;
fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::GenericPredicates<'tcx>;
fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::Generics<'tcx>;
fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize);
fn item_generics_object_lifetime_defaults(&self, def: DefId)
-> Vec<ObjectLifetimeDefault>;
fn item_generics(&self, def: DefId) -> ty::Generics;
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef;
fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> &'tcx ty::AdtDef;
@ -335,13 +330,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
-> ty::GenericPredicates<'tcx> { bug!("item_predicates") }
fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") }
fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::Generics<'tcx> { bug!("item_generics") }
fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize)
{ bug!("item_generics_own_param_counts") }
fn item_generics_object_lifetime_defaults(&self, def: DefId)
-> Vec<ObjectLifetimeDefault>
{ bug!("item_generics_object_lifetime_defaults") }
fn item_generics(&self, def: DefId) -> ty::Generics { bug!("item_generics") }
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { bug!("item_attrs") }
fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef
{ bug!("trait_def") }

View File

@ -995,7 +995,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
} else {
let cstore = &self.sess.cstore;
self.xcrate_object_lifetime_defaults.entry(def_id).or_insert_with(|| {
cstore.item_generics_object_lifetime_defaults(def_id)
cstore.item_generics(def_id).types.into_iter().map(|def| {
def.object_lifetime_default
}).collect()
})
};
unsubst.iter().map(|set| {

View File

@ -64,7 +64,7 @@ pub struct GlobalArenas<'tcx> {
layout: TypedArena<Layout>,
// references
generics: TypedArena<ty::Generics<'tcx>>,
generics: TypedArena<ty::Generics>,
trait_def: TypedArena<ty::TraitDef>,
adt_def: TypedArena<ty::AdtDef>,
mir: TypedArena<RefCell<Mir<'tcx>>>,
@ -467,9 +467,6 @@ pub struct GlobalCtxt<'tcx> {
// Cache for the type-contents routine. FIXME -- track deps?
pub tc_cache: RefCell<FxHashMap<Ty<'tcx>, ty::contents::TypeContents>>,
// FIXME no dep tracking, but we should be able to remove this
pub ty_param_defs: RefCell<NodeMap<ty::TypeParameterDef<'tcx>>>,
// FIXME dep tracking -- should be harmless enough
pub normalized_cache: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>,
@ -646,15 +643,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
}
pub fn type_parameter_def(self,
node_id: NodeId)
-> ty::TypeParameterDef<'tcx>
{
self.ty_param_defs.borrow().get(&node_id).unwrap().clone()
}
pub fn alloc_generics(self, generics: ty::Generics<'gcx>)
-> &'gcx ty::Generics<'gcx> {
pub fn alloc_generics(self, generics: ty::Generics) -> &'gcx ty::Generics {
self.global_arenas.generics.alloc(generics)
}
@ -785,7 +774,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
tc_cache: RefCell::new(FxHashMap()),
associated_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
associated_item_def_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
ty_param_defs: RefCell::new(NodeMap()),
normalized_cache: RefCell::new(FxHashMap()),
inhabitedness_cache: RefCell::new(FxHashMap()),
lang_items: lang_items,

View File

@ -10,7 +10,7 @@
use hir::def_id::DefId;
use infer::type_variable;
use ty::{self, BoundRegion, Region, Ty, TyCtxt};
use ty::{self, BoundRegion, DefIdTree, Region, Ty, TyCtxt};
use std::fmt;
use syntax::abi;
@ -287,8 +287,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
db.span_note(span, "a default was defined here...");
}
None => {
let item_def_id = self.parent(expected.def_id).unwrap();
db.note(&format!("a default is defined on `{}`",
self.item_path_str(expected.def_id)));
self.item_path_str(item_def_id)));
}
}
@ -301,8 +302,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
db.span_note(span, "a second default was defined here...");
}
None => {
let item_def_id = self.parent(found.def_id).unwrap();
db.note(&format!("a second default is defined on `{}`",
self.item_path_str(found.def_id)));
self.item_path_str(item_def_id)));
}
}

View File

@ -35,7 +35,7 @@ macro_rules! dep_map_ty {
dep_map_ty! { AssociatedItems: AssociatedItems(DefId) -> ty::AssociatedItem }
dep_map_ty! { Types: ItemSignature(DefId) -> Ty<'tcx> }
dep_map_ty! { Generics: ItemSignature(DefId) -> &'tcx ty::Generics<'tcx> }
dep_map_ty! { Generics: ItemSignature(DefId) -> &'tcx ty::Generics }
dep_map_ty! { Predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> }
dep_map_ty! { SuperPredicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> }
dep_map_ty! { AssociatedItemDefIds: AssociatedItemDefIds(DefId) -> Rc<Vec<DefId>> }

View File

@ -19,9 +19,10 @@ use dep_graph::{self, DepNode};
use hir::{map as hir_map, FreevarMap, TraitMap};
use middle;
use hir::def::{Def, CtorKind, ExportMap};
use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
use middle::resolve_lifetime::ObjectLifetimeDefault;
use mir::Mir;
use traits;
use ty;
@ -33,6 +34,7 @@ use util::nodemap::{NodeSet, NodeMap, FxHashMap};
use serialize::{self, Encodable, Encoder};
use std::borrow::Cow;
use std::cell::{Cell, RefCell, Ref};
use std::collections::BTreeMap;
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use std::rc::Rc;
@ -585,13 +587,13 @@ pub enum IntVarValue {
UintType(ast::UintTy),
}
#[derive(Clone, RustcEncodable, RustcDecodable)]
pub struct TypeParameterDef<'tcx> {
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
pub struct TypeParameterDef {
pub name: Name,
pub def_id: DefId,
pub index: u32,
pub default_def_id: DefId, // for use in error reporing about defaults
pub default: Option<Ty<'tcx>>,
pub has_default: bool,
pub object_lifetime_default: ObjectLifetimeDefault,
/// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
/// on generic parameter `T`, asserts data behind the parameter
@ -628,16 +630,21 @@ impl RegionParameterDef {
/// Information about the formal type/lifetime parameters associated
/// with an item or method. Analogous to hir::Generics.
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Generics<'tcx> {
pub struct Generics {
pub parent: Option<DefId>,
pub parent_regions: u32,
pub parent_types: u32,
pub regions: Vec<RegionParameterDef>,
pub types: Vec<TypeParameterDef<'tcx>>,
pub types: Vec<TypeParameterDef>,
/// Reverse map to each `TypeParameterDef`'s `index` field, from
/// `def_id.index` (`def_id.krate` is the same as the item's).
pub type_param_to_index: BTreeMap<DefIndex, u32>,
pub has_self: bool,
}
impl<'tcx> Generics<'tcx> {
impl Generics {
pub fn parent_count(&self) -> usize {
self.parent_regions as usize + self.parent_types as usize
}
@ -651,10 +658,12 @@ impl<'tcx> Generics<'tcx> {
}
pub fn region_param(&self, param: &EarlyBoundRegion) -> &RegionParameterDef {
assert_eq!(self.parent_count(), 0);
&self.regions[param.index as usize - self.has_self as usize]
}
pub fn type_param(&self, param: &ParamTy) -> &TypeParameterDef<'tcx> {
pub fn type_param(&self, param: &ParamTy) -> &TypeParameterDef {
assert_eq!(self.parent_count(), 0);
&self.types[param.idx as usize - self.has_self as usize - self.regions.len()]
}
}
@ -2319,10 +2328,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
/// Given the did of an item, returns its generics.
pub fn item_generics(self, did: DefId) -> &'gcx Generics<'gcx> {
pub fn item_generics(self, did: DefId) -> &'gcx Generics {
lookup_locally_or_in_crate_store(
"generics", did, &self.generics,
|| self.alloc_generics(self.sess.cstore.item_generics(self.global_tcx(), did)))
|| self.alloc_generics(self.sess.cstore.item_generics(did)))
}
/// Given the did of an item, returns its full set of predicates.

View File

@ -353,7 +353,7 @@ macro_rules! CopyImpls {
}
}
CopyImpls! { (), hir::Unsafety, abi::Abi, ty::RegionParameterDef }
CopyImpls! { (), hir::Unsafety, abi::Abi }
impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> (T, U) {
@ -716,40 +716,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoBorrow<'tcx> {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::TypeParameterDef {
name: self.name,
def_id: self.def_id,
index: self.index,
default: self.default.fold_with(folder),
default_def_id: self.default_def_id,
pure_wrt_drop: self.pure_wrt_drop,
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.default.visit_with(visitor)
}
}
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 {
parent: self.parent,
parent_regions: self.parent_regions,
parent_types: self.parent_types,
regions: self.regions.fold_with(folder),
types: self.types.fold_with(folder),
has_self: self.has_self,
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.regions.visit_with(visitor) || self.types.visit_with(visitor)
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::GenericPredicates {

View File

@ -184,7 +184,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
mut mk_type: FT)
-> &'tcx Substs<'tcx>
where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region,
FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx> {
FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx> {
let defs = tcx.item_generics(def_id);
let mut substs = Vec::with_capacity(defs.count());
Substs::fill_item(&mut substs, tcx, defs, &mut mk_region, &mut mk_type);
@ -198,7 +198,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
mut mk_type: FT)
-> &'tcx Substs<'tcx>
where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region,
FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx>
FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx>
{
let defs = tcx.item_generics(def_id);
let mut result = Vec::with_capacity(defs.count());
@ -209,11 +209,11 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
fn fill_item<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
defs: &ty::Generics<'tcx>,
defs: &ty::Generics,
mk_region: &mut FR,
mk_type: &mut FT)
where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region,
FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx> {
FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx> {
if let Some(def_id) = defs.parent {
let parent_defs = tcx.item_generics(def_id);
@ -223,11 +223,11 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
}
fn fill_single<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
defs: &ty::Generics<'tcx>,
defs: &ty::Generics,
mk_region: &mut FR,
mk_type: &mut FT)
where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region,
FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx> {
FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx> {
// Handle Self first, before all regions.
let mut types = defs.types.iter();
if defs.parent.is_none() && defs.has_self {
@ -301,7 +301,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
tcx.mk_substs(target_substs.iter().chain(&self[defs.own_count()..]).cloned())
}
pub fn truncate_to(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, generics: &ty::Generics<'tcx>)
pub fn truncate_to(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, generics: &ty::Generics)
-> &'tcx Substs<'tcx> {
tcx.mk_substs(self.iter().take(generics.count()).cloned())
}

View File

@ -137,11 +137,14 @@ pub fn parameterized(f: &mut fmt::Formatter,
}
if !verbose {
if generics.types.last().map_or(false, |def| def.default.is_some()) {
if generics.types.last().map_or(false, |def| def.has_default) {
if let Some(substs) = tcx.lift(&substs) {
let tps = substs.types().rev().skip(child_types);
for (def, actual) in generics.types.iter().rev().zip(tps) {
if def.default.subst(tcx, substs) != Some(actual) {
if !def.has_default {
break;
}
if tcx.item_type(def.def_id).subst(tcx, substs) != actual {
break;
}
num_supplied_defaults += 1;
@ -326,7 +329,7 @@ impl<'tcx> fmt::Display for &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>> {
}
}
impl<'tcx> fmt::Debug for ty::TypeParameterDef<'tcx> {
impl fmt::Debug for ty::TypeParameterDef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "TypeParameterDef({}, {:?}, {})",
self.name,

View File

@ -17,7 +17,6 @@ use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, ExternC
use rustc::middle::cstore::{NativeLibrary, LinkMeta, LinkagePreference, LoadedMacro};
use rustc::hir::def::{self, Def};
use rustc::middle::lang_items;
use rustc::middle::resolve_lifetime::ObjectLifetimeDefault;
use rustc::session::Session;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
@ -104,22 +103,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
self.get_crate_data(def.krate).get_super_predicates(def.index, tcx)
}
fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::Generics<'tcx>
{
fn item_generics(&self, def: DefId) -> ty::Generics {
self.dep_graph.read(DepNode::MetaData(def));
self.get_crate_data(def.krate).get_generics(def.index, tcx)
}
fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize) {
self.dep_graph.read(DepNode::MetaData(def));
self.get_crate_data(def.krate).generics_own_param_counts(def.index)
}
fn item_generics_object_lifetime_defaults(&self, def: DefId)
-> Vec<ObjectLifetimeDefault> {
self.dep_graph.read(DepNode::MetaData(def));
self.get_crate_data(def.krate).generics_object_lifetime_defaults(def.index)
self.get_crate_data(def.krate).get_generics(def.index)
}
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>

View File

@ -20,7 +20,6 @@ use rustc::middle::cstore::LinkagePreference;
use rustc::hir::def::{self, Def, CtorKind};
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::middle::lang_items;
use rustc::middle::resolve_lifetime::ObjectLifetimeDefault;
use rustc::session::Session;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::subst::Substs;
@ -601,30 +600,8 @@ impl<'a, 'tcx> CrateMetadata {
}
}
pub fn get_generics(&self,
item_id: DefIndex,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> ty::Generics<'tcx> {
let g = self.entry(item_id).generics.unwrap().decode(self);
ty::Generics {
parent: g.parent,
parent_regions: g.parent_regions,
parent_types: g.parent_types,
regions: g.regions.decode((self, tcx)).collect(),
types: g.types.decode((self, tcx)).collect(),
has_self: g.has_self,
}
}
pub fn generics_own_param_counts(&self, item_id: DefIndex) -> (usize, usize) {
let g = self.entry(item_id).generics.unwrap().decode(self);
(g.regions.len, g.types.len)
}
pub fn generics_object_lifetime_defaults(&self, item_id: DefIndex)
-> Vec<ObjectLifetimeDefault> {
pub fn get_generics(&self, item_id: DefIndex) -> ty::Generics {
self.entry(item_id).generics.unwrap().decode(self)
.object_lifetime_defaults.decode(self).collect()
}
pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {

View File

@ -423,26 +423,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
}
fn encode_generics(&mut self, def_id: DefId) -> Lazy<Generics<'tcx>> {
fn encode_generics(&mut self, def_id: DefId) -> Lazy<ty::Generics> {
let tcx = self.tcx;
let g = tcx.item_generics(def_id);
let regions = self.lazy_seq_ref(&g.regions);
let types = self.lazy_seq_ref(&g.types);
let mut object_lifetime_defaults = LazySeq::empty();
if let Some(id) = tcx.hir.as_local_node_id(def_id) {
if let Some(o) = tcx.named_region_map.object_lifetime_defaults.get(&id) {
object_lifetime_defaults = self.lazy_seq_ref(o);
}
}
self.lazy(&Generics {
parent: g.parent,
parent_regions: g.parent_regions,
parent_types: g.parent_types,
regions: regions,
types: types,
has_self: g.has_self,
object_lifetime_defaults: object_lifetime_defaults,
})
self.lazy(tcx.item_generics(def_id))
}
fn encode_predicates(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
@ -1008,6 +991,10 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
EncodeContext::encode_info_for_foreign_item,
(def_id, ni));
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
intravisit::walk_generics(self, generics);
self.index.encode_info_for_generics(generics);
}
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
intravisit::walk_ty(self, ty);
self.index.encode_info_for_ty(ty);
@ -1019,6 +1006,14 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
}
impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
for ty_param in &generics.ty_params {
let def_id = self.tcx.hir.local_def_id(ty_param.id);
let has_default = Untracked(ty_param.default.is_some());
self.record(def_id, EncodeContext::encode_info_for_ty_param, (def_id, has_default));
}
}
fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
if let hir::TyImplTrait(_) = ty.node {
let def_id = self.tcx.hir.local_def_id(ty.id);
@ -1038,6 +1033,34 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
}
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
fn encode_info_for_ty_param(&mut self,
(def_id, Untracked(has_default)): (DefId, Untracked<bool>))
-> Entry<'tcx> {
let tcx = self.tcx;
Entry {
kind: EntryKind::Type,
visibility: self.lazy(&ty::Visibility::Public),
span: self.lazy(&tcx.def_span(def_id)),
attributes: LazySeq::empty(),
children: LazySeq::empty(),
stability: None,
deprecation: None,
ty: if has_default {
Some(self.encode_item_type(def_id))
} else {
None
},
inherent_impls: LazySeq::empty(),
variances: LazySeq::empty(),
generics: None,
predicates: None,
ast: None,
mir: None,
}
}
fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
let tcx = self.tcx;
Entry {

View File

@ -16,7 +16,6 @@ use rustc::hir::def::{self, CtorKind};
use rustc::hir::def_id::{DefIndex, DefId};
use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary};
use rustc::middle::lang_items;
use rustc::middle::resolve_lifetime::ObjectLifetimeDefault;
use rustc::mir;
use rustc::ty::{self, Ty, ReprOptions};
use rustc_back::PanicStrategy;
@ -212,7 +211,7 @@ pub struct Entry<'tcx> {
pub ty: Option<Lazy<Ty<'tcx>>>,
pub inherent_impls: LazySeq<DefIndex>,
pub variances: LazySeq<ty::Variance>,
pub generics: Option<Lazy<Generics<'tcx>>>,
pub generics: Option<Lazy<ty::Generics>>,
pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>,
pub ast: Option<Lazy<astencode::Ast<'tcx>>>,
@ -246,20 +245,6 @@ pub enum EntryKind<'tcx> {
AssociatedConst(AssociatedContainer),
}
/// A copy of `ty::Generics` which allows lazy decoding of
/// `regions` and `types` (e.g. knowing the number of type
/// and lifetime parameters before `TyCtxt` is created).
#[derive(RustcEncodable, RustcDecodable)]
pub struct Generics<'tcx> {
pub parent: Option<DefId>,
pub parent_regions: u32,
pub parent_types: u32,
pub regions: LazySeq<ty::RegionParameterDef>,
pub types: LazySeq<ty::TypeParameterDef<'tcx>>,
pub has_self: bool,
pub object_lifetime_defaults: LazySeq<ObjectLifetimeDefault>,
}
#[derive(RustcEncodable, RustcDecodable)]
pub struct ModData {
pub reexports: LazySeq<def::Export>,

View File

@ -334,7 +334,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
fn generics(&mut self) -> &mut Self {
self.ev.tcx.item_generics(self.item_def_id).visit_with(self);
for def in &self.ev.tcx.item_generics(self.item_def_id).types {
if def.has_default {
self.ev.tcx.item_type(def.def_id).visit_with(self);
}
}
self
}
@ -892,7 +896,11 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
fn generics(&mut self) -> &mut Self {
self.tcx.item_generics(self.item_def_id).visit_with(self);
for def in &self.tcx.item_generics(self.item_def_id).types {
if def.has_default {
self.tcx.item_type(def.def_id).visit_with(self);
}
}
self
}

View File

@ -15,6 +15,33 @@
// use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
register_long_diagnostics! {
E0128: r##"
Type parameter defaults can only use parameters that occur before them.
Erroneous code example:
```compile_fail,E0128
struct Foo<T=U, U=()> {
field1: T,
filed2: U,
}
// error: type parameters with a default cannot use forward declared
// identifiers
```
Since type parameters are evaluated in-order, you may be able to fix this issue
by doing:
```
struct Foo<U=(), T=U> {
field1: T,
filed2: U,
}
```
Please also verify that this wasn't because of a name-clash and rename the type
parameter if so.
"##,
E0154: r##"
## Note: this error code is no longer emitted by the compiler.

View File

@ -136,6 +136,8 @@ enum ResolutionError<'a> {
AttemptToUseNonConstantValueInConstant,
/// error E0530: X bindings cannot shadow Ys
BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>),
/// error E0128: type parameters with a default cannot use forward declared identifiers
ForwardDeclaredTyParam,
}
fn resolve_error<'sess, 'a>(resolver: &'sess Resolver,
@ -322,6 +324,14 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
err.span_label(binding.span, msg);
err
}
ResolutionError::ForwardDeclaredTyParam => {
let mut err = struct_span_err!(resolver.session, span, E0128,
"type parameters with a default cannot use \
forward declared identifiers");
err.span_label(span, &format!("defaulted type parameters \
cannot be forward declared"));
err
}
}
}
@ -674,6 +684,32 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
self.label_ribs.pop();
self.ribs[ValueNS].pop();
}
fn visit_generics(&mut self, generics: &'tcx Generics) {
// For type parameter defaults, we have to ban access
// to following type parameters, as the Substs can only
// provide previous type parameters as they're built.
let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind);
default_ban_rib.bindings.extend(generics.ty_params.iter()
.skip_while(|p| p.default.is_none())
.map(|p| (Ident::with_empty_ctxt(p.ident.name), Def::Err)));
for param in &generics.ty_params {
for bound in &param.bounds {
self.visit_ty_param_bound(bound);
}
if let Some(ref ty) = param.default {
self.ribs[TypeNS].push(default_ban_rib);
self.visit_ty(ty);
default_ban_rib = self.ribs[TypeNS].pop().unwrap();
}
// Allow all following defaults to refer to this type parameter.
default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name));
}
for lt in &generics.lifetimes { self.visit_lifetime_def(lt); }
for p in &generics.where_clause.predicates { self.visit_where_predicate(p); }
}
}
pub type ErrorMessage = Option<(Span, String)>;
@ -718,6 +754,11 @@ enum RibKind<'a> {
// We passed through a `macro_rules!` statement with the given expansion
MacroDefinition(Mark),
// All bindings in this rib are type parameters that can't be used
// from the default of a type parameter because they're not declared
// before said type parameter. Also see the `visit_generics` override.
ForwardTyParamBanRibKind,
}
/// One local scope.
@ -736,13 +777,6 @@ impl<'a> Rib<'a> {
}
}
/// A definition along with the index of the rib it was found on
#[derive(Copy, Clone, Debug)]
struct LocalDef {
ribs: Option<(Namespace, usize)>,
def: Def,
}
enum LexicalScopeBinding<'a> {
Item(&'a NameBinding<'a>),
Def(Def),
@ -1428,7 +1462,7 @@ impl<'a> Resolver<'a> {
if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() {
// The ident resolves to a type parameter or local variable.
return Some(LexicalScopeBinding::Def(
self.adjust_local_def(LocalDef { ribs: Some((ns, i)), def: def }, record_used)
self.adjust_local_def(ns, i, def, record_used)
));
}
@ -2527,12 +2561,23 @@ impl<'a> Resolver<'a> {
}
// Resolve a local definition, potentially adjusting for closures.
fn adjust_local_def(&mut self, local_def: LocalDef, record_used: Option<Span>) -> Def {
let ribs = match local_def.ribs {
Some((ns, i)) => &self.ribs[ns][i + 1..],
None => &[] as &[_],
};
let mut def = local_def.def;
fn adjust_local_def(&mut self,
ns: Namespace,
rib_index: usize,
mut def: Def,
record_used: Option<Span>) -> Def {
let ribs = &self.ribs[ns][rib_index + 1..];
// An invalid forward use of a type parameter from a previous default.
if let ForwardTyParamBanRibKind = self.ribs[ns][rib_index].kind {
if let Some(span) = record_used {
resolve_error(self, span,
ResolutionError::ForwardDeclaredTyParam);
}
assert_eq!(def, Def::Err);
return Def::Err;
}
match def {
Def::Upvar(..) => {
span_bug!(record_used.unwrap_or(DUMMY_SP), "unexpected {:?} in bindings", def)
@ -2540,7 +2585,8 @@ impl<'a> Resolver<'a> {
Def::Local(def_id) => {
for rib in ribs {
match rib.kind {
NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) => {
NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) |
ForwardTyParamBanRibKind => {
// Nothing to do. Continue.
}
ClosureRibKind(function_id) => {
@ -2593,7 +2639,7 @@ impl<'a> Resolver<'a> {
for rib in ribs {
match rib.kind {
NormalRibKind | MethodRibKind(_) | ClosureRibKind(..) |
ModuleRibKind(..) | MacroDefinition(..) => {
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind => {
// Nothing to do. Continue.
}
ItemRibKind => {

View File

@ -332,7 +332,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
}
fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
generics: &ty::Generics<'tcx>,
generics: &ty::Generics,
substs: &Substs<'tcx>,
file_metadata: DIFile,
name_to_append_suffix_to: &mut String)
@ -382,9 +382,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
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> {
fn get_type_parameter_names(cx: &CrateContext, generics: &ty::Generics) -> Vec<ast::Name> {
let mut names = generics.parent.map_or(vec![], |def_id| {
get_type_parameter_names(cx, cx.tcx().item_generics(def_id))
});

View File

@ -14,6 +14,7 @@ use super::{CrateDebugContext};
use super::namespace::item_namespace;
use rustc::hir::def_id::DefId;
use rustc::ty::DefIdTree;
use llvm;
use llvm::debuginfo::{DIScope, DIBuilderRef, DIDescriptor, DIArray};
@ -74,11 +75,8 @@ pub fn DIB(cx: &CrateContext) -> DIBuilderRef {
pub fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: DefId)
-> (DIScope, Span) {
let containing_scope = item_namespace(cx, DefId {
krate: def_id.krate,
index: cx.tcx().def_key(def_id).parent
.expect("get_namespace_and_span_for_item: missing parent?")
});
let containing_scope = item_namespace(cx, cx.tcx().parent(def_id)
.expect("get_namespace_and_span_for_item: missing parent?"));
// Try to get some span information, if we have an inlined item.
let definition_span = cx.tcx().def_span(def_id);

View File

@ -42,7 +42,7 @@ use std::cell::RefCell;
use std::iter;
use syntax::{abi, ast};
use syntax::feature_gate::{GateIssue, emit_feature_err};
use syntax::symbol::{Symbol, keywords};
use syntax::symbol::Symbol;
use syntax_pos::Span;
pub trait AstConv<'gcx, 'tcx> {
@ -53,7 +53,7 @@ pub trait AstConv<'gcx, 'tcx> {
/// Returns the generic type and lifetime parameters for an item.
fn get_generics(&self, span: Span, id: DefId)
-> Result<&'tcx ty::Generics<'tcx>, ErrorReported>;
-> Result<&'tcx ty::Generics, ErrorReported>;
/// Identify the type for an item, like a type alias, fn, or struct.
fn get_item_type(&self, span: Span, id: DefId) -> Result<Ty<'tcx>, ErrorReported>;
@ -89,7 +89,7 @@ pub trait AstConv<'gcx, 'tcx> {
/// Same as ty_infer, but with a known type parameter definition.
fn ty_infer_for_def(&self,
_def: &ty::TypeParameterDef<'tcx>,
_def: &ty::TypeParameterDef,
_substs: &[Kind<'tcx>],
span: Span) -> Ty<'tcx> {
self.ty_infer(span)
@ -277,9 +277,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
}
let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
let default_needs_object_self = |p: &ty::TypeParameterDef<'tcx>| {
if let Some(ref default) = p.default {
if is_object && default.has_self_ty() {
let default_needs_object_self = |p: &ty::TypeParameterDef| {
if is_object && p.has_default {
let default = self.get_item_type(span, p.def_id).ok();
if default.has_self_ty() {
// There is no suitable inference default for a type parameter
// that references self, in an object type.
return true;
@ -327,7 +328,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
self.ty_infer(span)
};
ty_var
} else if let Some(default) = def.default {
} else if def.has_default {
// No type parameter provided, but a default exists.
// If we are converting an object type, then the
@ -346,7 +347,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
tcx.types.err
} else {
// This is a default type parameter.
default.subst_spanned(tcx, substs, Some(span))
match self.get_item_type(span, def.def_id) {
Ok(ty) => ty.subst_spanned(tcx, substs, Some(span)),
Err(ErrorReported) => tcx.types.err
}
}
} else {
// We've already errored above about the mismatch.
@ -954,19 +958,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
Err(ErrorReported) => return (tcx.types.err, Def::Err),
}
}
(&ty::TyParam(_), Def::SelfTy(Some(trait_did), None)) => {
let trait_node_id = tcx.hir.as_local_node_id(trait_did).unwrap();
match self.find_bound_for_assoc_item(trait_node_id,
keywords::SelfType.name(),
assoc_name,
span) {
Ok(bound) => bound,
Err(ErrorReported) => return (tcx.types.err, Def::Err),
}
}
(&ty::TyParam(_), Def::SelfTy(Some(param_did), None)) |
(&ty::TyParam(_), Def::TyParam(param_did)) => {
let param_node_id = tcx.hir.as_local_node_id(param_did).unwrap();
let param_name = tcx.type_parameter_def(param_node_id).name;
let param_name = ::ty_param_name(tcx, param_node_id);
match self.find_bound_for_assoc_item(param_node_id,
param_name,
assoc_name,
@ -1063,21 +1058,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
tcx.prohibit_type_params(&path.segments);
let node_id = tcx.hir.as_local_node_id(did).unwrap();
let param = tcx.ty_param_defs.borrow().get(&node_id)
.map(ty::ParamTy::for_def);
if let Some(p) = param {
p.to_ty(tcx)
} else {
// Only while computing defaults of earlier type
// parameters can a type parameter be missing its def.
struct_span_err!(tcx.sess, span, E0128,
"type parameters with a default cannot use \
forward declared identifiers")
.span_label(span, &format!("defaulted type parameters \
cannot be forward declared"))
.emit();
tcx.types.err
}
let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id));
let index = match self.get_generics(span, item_def_id) {
Ok(generics) => {
generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index]
}
Err(ErrorReported) => return tcx.types.err
};
tcx.mk_param(index, ::ty_param_name(tcx, node_id))
}
Def::SelfTy(_, Some(def_id)) => {
// Self in impl (we know the concrete type).
@ -1510,7 +1498,7 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize,
ty_param_defs: &[ty::TypeParameterDef]) {
let accepted = ty_param_defs.len();
let required = ty_param_defs.iter().take_while(|x| x.default.is_none()) .count();
let required = ty_param_defs.iter().take_while(|x| !x.has_default).count();
if supplied < required {
let expected = if required < accepted {
"expected at least"

View File

@ -386,8 +386,8 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
span: Span,
impl_m: &ty::AssociatedItem,
trait_generics: &ty::Generics<'tcx>,
impl_generics: &ty::Generics<'tcx>,
trait_generics: &ty::Generics,
impl_generics: &ty::Generics,
trait_to_skol_substs: &Substs<'tcx>,
impl_to_skol_substs: &Substs<'tcx>)
-> Result<(), ErrorReported> {

View File

@ -1360,7 +1360,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
}
fn get_generics(&self, _: Span, id: DefId)
-> Result<&'tcx ty::Generics<'tcx>, ErrorReported>
-> Result<&'tcx ty::Generics, ErrorReported>
{
Ok(self.tcx().item_generics(id))
}
@ -1390,14 +1390,17 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
node_id: ast::NodeId)
-> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
{
let def = self.tcx.type_parameter_def(node_id);
let tcx = self.tcx;
let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id));
let generics = tcx.item_generics(item_def_id);
let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index];
let r = self.parameter_environment
.caller_bounds
.iter()
.filter_map(|predicate| {
match *predicate {
ty::Predicate::Trait(ref data) => {
if data.0.self_ty().is_param(def.index) {
if data.0.self_ty().is_param(index) {
Some(data.to_poly_trait_ref())
} else {
None
@ -1426,7 +1429,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
}
fn ty_infer_for_def(&self,
ty_param_def: &ty::TypeParameterDef<'tcx>,
ty_param_def: &ty::TypeParameterDef,
substs: &[Kind<'tcx>],
span: Span) -> Ty<'tcx> {
self.type_var_for_def(span, ty_param_def, substs)
@ -4423,8 +4426,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if let Some(ast_ty) = types.get(i) {
// A provided type parameter.
self.to_ty(ast_ty)
} else if let (false, Some(default)) = (infer_types, def.default) {
} else if !infer_types && def.has_default {
// No type parameter provided, but a default exists.
let default = self.tcx.item_type(def.def_id);
default.subst_spanned(self.tcx, substs, Some(span))
} else {
// No type parameters were provided, we can infer all.
@ -4537,9 +4541,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
&generics.types
}
});
let required_len = type_defs.iter()
.take_while(|d| d.default.is_none())
.count();
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());

View File

@ -62,6 +62,7 @@ use lint;
use constrained_type_params as ctp;
use middle::lang_items::SizedTraitLangItem;
use middle::const_val::ConstVal;
use middle::resolve_lifetime as rl;
use rustc_const_eval::EvalHint::UncheckedExprHint;
use rustc_const_eval::{ConstContext, report_const_eval_err};
use rustc::ty::subst::Substs;
@ -76,6 +77,7 @@ use CrateCtxt;
use rustc_const_math::ConstInt;
use std::cell::RefCell;
use std::collections::BTreeMap;
use syntax::{abi, ast, attr};
use syntax::symbol::{Symbol, keywords};
@ -186,6 +188,16 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> {
intravisit::walk_item(self, item);
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
for param in &generics.ty_params {
if param.default.is_some() {
let def_id = self.ccx.tcx.hir.local_def_id(param.id);
type_of_def_id(self.ccx, def_id);
}
}
intravisit::walk_generics(self, generics);
}
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
if let hir::ExprClosure(..) = expr.node {
let def_id = self.ccx.tcx.hir.local_def_id(expr.id);
@ -277,11 +289,10 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
tcx.item_path_str(def_id)));
}
AstConvRequest::GetTypeParameterBounds(id) => {
let def = tcx.type_parameter_def(id);
err.note(
&format!("the cycle begins when computing the bounds \
for type parameter `{}`...",
def.name));
::ty_param_name(tcx, id)));
}
}
@ -300,11 +311,10 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
tcx.item_path_str(def_id)));
}
AstConvRequest::GetTypeParameterBounds(id) => {
let def = tcx.type_parameter_def(id);
err.note(
&format!("...which then requires computing the bounds \
for type parameter `{}`...",
def.name));
::ty_param_name(tcx, id)));
}
}
}
@ -324,11 +334,10 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
tcx.item_path_str(def_id)));
}
AstConvRequest::GetTypeParameterBounds(id) => {
let def = tcx.type_parameter_def(id);
err.note(
&format!("...which then again requires computing the bounds \
for type parameter `{}`, completing the cycle.",
def.name));
::ty_param_name(tcx, id)));
}
}
err.emit();
@ -385,7 +394,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
}
fn get_generics(&self, span: Span, id: DefId)
-> Result<&'tcx ty::Generics<'tcx>, ErrorReported>
-> Result<&'tcx ty::Generics, ErrorReported>
{
self.ccx.cycle_check(span, AstConvRequest::GetGenerics(id), || {
Ok(generics_of_def_id(self.ccx, id))
@ -531,20 +540,23 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
node_id: ast::NodeId)
-> Vec<ty::Predicate<'tcx>>
{
let def = astconv.tcx().type_parameter_def(node_id);
let tcx = astconv.tcx();
let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id));
let generics = tcx.item_generics(item_def_id);
let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index];
let mut results = self.parent.map_or(vec![], |def_id| {
let parent = astconv.tcx().item_predicates(def_id);
let parent = tcx.item_predicates(def_id);
parent.get_type_parameter_bounds(astconv, span, node_id)
});
results.extend(self.predicates.iter().filter(|predicate| {
match **predicate {
ty::Predicate::Trait(ref data) => {
data.skip_binder().self_ty().is_param(def.index)
data.skip_binder().self_ty().is_param(index)
}
ty::Predicate::TypeOutlives(ref data) => {
data.skip_binder().0.is_param(def.index)
data.skip_binder().0.is_param(index)
}
ty::Predicate::Equate(..) |
ty::Predicate::RegionOutlives(..) |
@ -568,7 +580,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
fn get_type_parameter_bounds(&self,
astconv: &AstConv<'tcx, 'tcx>,
_: Span,
span: Span,
node_id: ast::NodeId)
-> Vec<ty::Predicate<'tcx>>
{
@ -576,8 +588,15 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
// written inline like `<T:Foo>` or in a where clause like
// `where T:Foo`.
let def = astconv.tcx().type_parameter_def(node_id);
let ty = astconv.tcx().mk_param_from_def(&def);
let tcx = astconv.tcx();
let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id));
let index = match astconv.get_generics(span, item_def_id) {
Ok(generics) => {
generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index]
}
Err(ErrorReported) => return vec![]
};
let ty = tcx.mk_param(index, ::ty_param_name(tcx, node_id));
let from_ty_params =
self.ty_params
@ -594,7 +613,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
hir::WherePredicate::BoundPredicate(ref bp) => Some(bp),
_ => None
})
.filter(|bp| is_param(astconv.tcx(), &bp.bounded_ty, node_id))
.filter(|bp| is_param(tcx, &bp.bounded_ty, node_id))
.flat_map(|bp| bp.bounds.iter())
.flat_map(|b| predicates_from_bound(astconv, ty, b));
@ -625,7 +644,7 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
struct_generics: &'tcx ty::Generics<'tcx>,
struct_generics: &'tcx ty::Generics,
struct_predicates: &ty::GenericPredicates<'tcx>,
field: &hir::StructField,
ty_f: &'tcx ty::FieldDef)
@ -938,7 +957,7 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
def: &'tcx ty::AdtDef,
ty: Ty<'tcx>,
generics: &'tcx ty::Generics<'tcx>,
generics: &'tcx ty::Generics,
predicates: ty::GenericPredicates<'tcx>,
variants: &[hir::Variant]) {
// fill the field types
@ -1325,7 +1344,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item)
fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
def_id: DefId)
-> &'tcx ty::Generics<'tcx> {
-> &'tcx ty::Generics {
let tcx = ccx.tcx;
let node_id = if let Some(id) = tcx.hir.as_local_node_id(def_id) {
id
@ -1402,18 +1421,14 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
// the node id for the Self type parameter.
let param_id = item.id;
let parent = ccx.tcx.hir.get_parent(param_id);
let def = ty::TypeParameterDef {
opt_self = Some(ty::TypeParameterDef {
index: 0,
name: keywords::SelfType.name(),
def_id: tcx.hir.local_def_id(param_id),
default_def_id: tcx.hir.local_def_id(parent),
default: None,
has_default: false,
object_lifetime_default: rl::Set1::Empty,
pure_wrt_drop: false,
};
tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
opt_self = Some(def);
});
allow_defaults = true;
generics
@ -1459,11 +1474,36 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
}
}).collect::<Vec<_>>();
let object_lifetime_defaults =
tcx.named_region_map.object_lifetime_defaults.get(&node_id);
// Now create the real type parameters.
let type_start = own_start + regions.len() as u32;
let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| {
let i = type_start + i as u32;
get_or_create_type_parameter_def(ccx, i, p, allow_defaults)
if p.name == keywords::SelfType.name() {
span_bug!(p.span, "`Self` should not be the name of a regular parameter");
}
if !allow_defaults && p.default.is_some() {
if !tcx.sess.features.borrow().default_type_parameter_fallback {
tcx.sess.add_lint(
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
p.id,
p.span,
format!("defaults for type parameters are only allowed in `struct`, \
`enum`, `type`, or `trait` definitions."));
}
}
ty::TypeParameterDef {
index: type_start + i as u32,
name: p.name,
def_id: tcx.hir.local_def_id(p.id),
has_default: p.default.is_some(),
object_lifetime_default:
object_lifetime_defaults.map_or(rl::Set1::Empty, |o| o[i]),
pure_wrt_drop: p.pure_wrt_drop,
}
});
let mut types: Vec<_> = opt_self.into_iter().chain(types).collect();
@ -1476,19 +1516,25 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
index: type_start + i as u32,
name: Symbol::intern("<upvar>"),
def_id: def_id,
default_def_id: parent_def_id.unwrap(),
default: None,
has_default: false,
object_lifetime_default: rl::Set1::Empty,
pure_wrt_drop: false,
}));
});
}
let mut type_param_to_index = BTreeMap::new();
for param in &types {
type_param_to_index.insert(param.def_id.index, param.index);
}
tcx.alloc_generics(ty::Generics {
parent: parent_def_id,
parent_regions: parent_regions,
parent_types: parent_types,
regions: regions,
types: types,
type_param_to_index: type_param_to_index,
has_self: has_self || parent_has_self
})
})
@ -1576,6 +1622,9 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|def, _| ccx.tcx.mk_param_from_def(def)
))
}
NodeTyParam(&hir::TyParam { default: Some(ref ty), .. }) => {
ccx.icx(&()).to_ty(ty)
}
x => {
bug!("unexpected sort of node in type_of_def_id(): {:?}", x);
}
@ -1808,54 +1857,6 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
}
}
fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
index: u32,
param: &hir::TyParam,
allow_defaults: bool)
-> ty::TypeParameterDef<'tcx>
{
let tcx = ccx.tcx;
match tcx.ty_param_defs.borrow().get(&param.id) {
Some(d) => { return d.clone(); }
None => { }
}
let default =
param.default.as_ref().map(|def| ccx.icx(&()).to_ty(def));
let parent = tcx.hir.get_parent(param.id);
if !allow_defaults && default.is_some() {
if !tcx.sess.features.borrow().default_type_parameter_fallback {
tcx.sess.add_lint(
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
param.id,
param.span,
format!("defaults for type parameters are only allowed in `struct`, \
`enum`, `type`, or `trait` definitions."));
}
}
let def = ty::TypeParameterDef {
index: index,
name: param.name,
def_id: ccx.tcx.hir.local_def_id(param.id),
default_def_id: ccx.tcx.hir.local_def_id(parent),
default: default,
pure_wrt_drop: param.pure_wrt_drop,
};
if def.name == keywords::SelfType.name() {
span_bug!(param.span, "`Self` should not be the name of a regular parameter");
}
tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
debug!("get_or_create_type_parameter_def: def for type param: {:?}", def);
def
}
pub enum SizedByDefault { Yes, No, }
/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or

View File

@ -1701,33 +1701,6 @@ struct Foo {
```
"##,
E0128: r##"
Type parameter defaults can only use parameters that occur before them.
Erroneous code example:
```compile_fail,E0128
struct Foo<T=U, U=()> {
field1: T,
filed2: U,
}
// error: type parameters with a default cannot use forward declared
// identifiers
```
Since type parameters are evaluated in-order, you may be able to fix this issue
by doing:
```
struct Foo<U=(), T=U> {
field1: T,
filed2: U,
}
```
Please also verify that this wasn't because of a name-clash and rename the type
parameter if so.
"##,
E0131: r##"
It is not possible to define `main` with type parameters, or even with function
parameters. When `main` is present, it must take no arguments and return `()`.

View File

@ -116,6 +116,7 @@ use util::common::time;
use syntax::ast;
use syntax::abi::Abi;
use syntax::symbol::keywords;
use syntax_pos::Span;
use std::iter;
@ -193,6 +194,30 @@ fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
})
}
fn ty_param_owner(tcx: TyCtxt, id: ast::NodeId) -> ast::NodeId {
match tcx.hir.get(id) {
hir::map::NodeItem(&hir::Item { node: hir::ItemTrait(..), .. }) => id,
hir::map::NodeTyParam(_) => tcx.hir.get_parent_node(id),
_ => {
bug!("ty_param_owner: {} not a type parameter",
tcx.hir.node_to_string(id))
}
}
}
fn ty_param_name(tcx: TyCtxt, id: ast::NodeId) -> ast::Name {
match tcx.hir.get(id) {
hir::map::NodeItem(&hir::Item { node: hir::ItemTrait(..), .. }) => {
keywords::SelfType.name()
}
hir::map::NodeTyParam(tp) => tp.name,
_ => {
bug!("ty_param_name: {} not a type parameter",
tcx.hir.node_to_string(id))
}
}
}
fn check_main_fn_ty(ccx: &CrateCtxt,
main_id: ast::NodeId,
main_span: Span) {

View File

@ -279,7 +279,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
}
fn add_constraints_from_trait_ref(&mut self,
generics: &ty::Generics<'tcx>,
generics: &ty::Generics,
trait_ref: ty::TraitRef<'tcx>,
variance: VarianceTermPtr<'a>) {
debug!("add_constraints_from_trait_ref: trait_ref={:?} variance={:?}",
@ -305,7 +305,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
/// in a context with the generics defined in `generics` and
/// ambient variance `variance`
fn add_constraints_from_ty(&mut self,
generics: &ty::Generics<'tcx>,
generics: &ty::Generics,
ty: Ty<'tcx>,
variance: VarianceTermPtr<'a>) {
debug!("add_constraints_from_ty(ty={:?}, variance={:?})",
@ -433,9 +433,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
/// Adds constraints appropriate for a nominal type (enum, struct,
/// object, etc) appearing in a context with ambient variance `variance`
fn add_constraints_from_substs(&mut self,
generics: &ty::Generics<'tcx>,
generics: &ty::Generics,
def_id: DefId,
type_param_defs: &[ty::TypeParameterDef<'tcx>],
type_param_defs: &[ty::TypeParameterDef],
region_param_defs: &[ty::RegionParameterDef],
substs: &Substs<'tcx>,
variance: VarianceTermPtr<'a>) {
@ -465,7 +465,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
/// Adds constraints appropriate for a function with signature
/// `sig` appearing in a context with ambient variance `variance`
fn add_constraints_from_sig(&mut self,
generics: &ty::Generics<'tcx>,
generics: &ty::Generics,
sig: &ty::PolyFnSig<'tcx>,
variance: VarianceTermPtr<'a>) {
let contra = self.contravariant(variance);
@ -478,7 +478,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
/// Adds constraints appropriate for a region appearing in a
/// context with ambient variance `variance`
fn add_constraints_from_region(&mut self,
generics: &ty::Generics<'tcx>,
generics: &ty::Generics,
region: &'tcx ty::Region,
variance: VarianceTermPtr<'a>) {
match *region {
@ -518,7 +518,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
/// Adds constraints appropriate for a mutability-type pair
/// appearing in a context with ambient variance `variance`
fn add_constraints_from_mt(&mut self,
generics: &ty::Generics<'tcx>,
generics: &ty::Generics,
mt: &ty::TypeAndMut<'tcx>,
variance: VarianceTermPtr<'a>) {
match mt.mutbl {

View File

@ -596,14 +596,18 @@ impl Clean<TyParam> for hir::TyParam {
}
}
impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
impl<'tcx> Clean<TyParam> for ty::TypeParameterDef {
fn clean(&self, cx: &DocContext) -> TyParam {
cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx));
TyParam {
name: self.name.clean(cx),
did: self.def_id,
bounds: vec![], // these are filled in from the where-clauses
default: self.default.clean(cx),
default: if self.has_default {
Some(cx.tcx.item_type(self.def_id).clean(cx))
} else {
None
}
}
}
}
@ -965,7 +969,7 @@ 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,
&'a ty::GenericPredicates<'tcx>) {
fn clean(&self, cx: &DocContext) -> Generics {
use self::WherePredicate as WP;

View File

@ -68,6 +68,9 @@ pub trait Visitor<'ast>: Sized {
fn visit_expr_post(&mut self, _ex: &'ast Expr) { }
fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) }
fn visit_generics(&mut self, g: &'ast Generics) { walk_generics(self, g) }
fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
walk_where_predicate(self, p)
}
fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl, s: Span, _: NodeId) {
walk_fn(self, fk, fd, s)
}
@ -488,28 +491,30 @@ pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics
walk_list!(visitor, visit_attribute, &*param.attrs);
}
walk_list!(visitor, visit_lifetime_def, &generics.lifetimes);
for predicate in &generics.where_clause.predicates {
match *predicate {
WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty,
ref bounds,
ref bound_lifetimes,
..}) => {
visitor.visit_ty(bounded_ty);
walk_list!(visitor, visit_ty_param_bound, bounds);
walk_list!(visitor, visit_lifetime_def, bound_lifetimes);
}
WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
ref bounds,
..}) => {
visitor.visit_lifetime(lifetime);
walk_list!(visitor, visit_lifetime, bounds);
}
WherePredicate::EqPredicate(WhereEqPredicate{ref lhs_ty,
ref rhs_ty,
..}) => {
visitor.visit_ty(lhs_ty);
visitor.visit_ty(rhs_ty);
}
walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates);
}
pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a WherePredicate) {
match *predicate {
WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty,
ref bounds,
ref bound_lifetimes,
..}) => {
visitor.visit_ty(bounded_ty);
walk_list!(visitor, visit_ty_param_bound, bounds);
walk_list!(visitor, visit_lifetime_def, bound_lifetimes);
}
WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
ref bounds,
..}) => {
visitor.visit_lifetime(lifetime);
walk_list!(visitor, visit_lifetime, bounds);
}
WherePredicate::EqPredicate(WhereEqPredicate{ref lhs_ty,
ref rhs_ty,
..}) => {
visitor.visit_ty(lhs_ty);
visitor.visit_ty(rhs_ty);
}
}
}

View File

@ -13,6 +13,7 @@
trait Foo<X = Box<Foo>> {
//~^ ERROR unsupported cyclic reference
//~| ERROR unsupported cyclic reference
}
fn main() { }

View File

@ -10,10 +10,10 @@
struct Heap;
struct Vec<A = Heap, T>;
struct Vec<A = Heap, T>(A, T);
//~^ ERROR type parameters with a default must be trailing
struct Foo<A, B = Vec<C>, C>;
struct Foo<A, B = Vec<C>, C>(A, B, C);
//~^ ERROR type parameters with a default must be trailing
//~| ERROR type parameters with a default cannot use forward declared identifiers

View File

@ -9,7 +9,7 @@
// except according to those terms.
// Ensure that we get an error and not an ICE for this problematic case.
struct Foo<T = Option<U>, U = bool>;
struct Foo<T = Option<U>, U = bool>(T, U);
//~^ ERROR type parameters with a default cannot use forward declared identifiers
fn main() {
let x: Foo;

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub struct Foo<Bar=Bar>; //~ ERROR E0128
//~| NOTE defaulted type parameters cannot be forward declared
pub struct Foo<Bar=Bar>(Bar); //~ ERROR E0128
//~| NOTE defaulted type parameters cannot be forward declared
pub struct Baz(Foo);
fn main() {}

View File

@ -15,7 +15,7 @@ impl Tr<Self> for S {} // OK
// FIXME: `Self` cannot be used in bounds because it depends on bounds itself.
impl<T: Tr<Self>> Tr<T> for S {} //~ ERROR `Self` type is used before it's determined
impl<T = Self> Tr<T> for S {} //~ ERROR `Self` type is used before it's determined
impl<T = Self> Tr<T> for S {}
impl Tr for S where Self: Copy {} //~ ERROR `Self` type is used before it's determined
impl Tr for S where S<Self>: Copy {} //~ ERROR `Self` type is used before it's determined
impl Tr for S where Self::Assoc: Copy {} //~ ERROR `Self` type is used before it's determined