mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
rustc: store type parameter defaults outside of ty::Generics.
This commit is contained in:
parent
1572bf104d
commit
e8d01ea4c7
@ -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
|
||||
});
|
||||
|
@ -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
|
||||
|
@ -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") }
|
||||
|
@ -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| {
|
||||
|
@ -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,
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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>> }
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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>
|
||||
|
@ -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> {
|
||||
|
@ -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 {
|
||||
|
@ -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>,
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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 ¶m.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 => {
|
||||
|
@ -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))
|
||||
});
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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> {
|
||||
|
@ -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());
|
||||
|
@ -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(¶m.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
|
||||
|
@ -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 `()`.
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
trait Foo<X = Box<Foo>> {
|
||||
//~^ ERROR unsupported cyclic reference
|
||||
//~| ERROR unsupported cyclic reference
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user