rustc: store type parameter defaults outside of ty::Generics.
This commit is contained in:
parent
1572bf104d
commit
e8d01ea4c7
34 changed files with 394 additions and 385 deletions
|
@ -525,7 +525,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
assert!(!def_id.is_local());
|
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);
|
self.type_def_lifetime_params.insert(def_id, n);
|
||||||
n
|
n
|
||||||
});
|
});
|
||||||
|
|
|
@ -1197,16 +1197,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
/// as the substitutions for the default, `(T, U)`.
|
/// as the substitutions for the default, `(T, U)`.
|
||||||
pub fn type_var_for_def(&self,
|
pub fn type_var_for_def(&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
def: &ty::TypeParameterDef<'tcx>,
|
def: &ty::TypeParameterDef,
|
||||||
substs: &[Kind<'tcx>])
|
substs: &[Kind<'tcx>])
|
||||||
-> Ty<'tcx> {
|
-> Ty<'tcx> {
|
||||||
let default = def.default.map(|default| {
|
let default = if def.has_default {
|
||||||
type_variable::Default {
|
let default = self.tcx.item_type(def.def_id);
|
||||||
|
Some(type_variable::Default {
|
||||||
ty: default.subst_spanned(self.tcx, substs, Some(span)),
|
ty: default.subst_spanned(self.tcx, substs, Some(span)),
|
||||||
origin_span: span,
|
origin_span: span,
|
||||||
def_id: def.default_def_id
|
def_id: def.def_id
|
||||||
}
|
})
|
||||||
});
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
let ty_var_id = self.type_variables
|
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::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData};
|
||||||
use hir::svh::Svh;
|
use hir::svh::Svh;
|
||||||
use middle::lang_items;
|
use middle::lang_items;
|
||||||
use middle::resolve_lifetime::ObjectLifetimeDefault;
|
|
||||||
use ty::{self, Ty, TyCtxt};
|
use ty::{self, Ty, TyCtxt};
|
||||||
use mir::Mir;
|
use mir::Mir;
|
||||||
use session::Session;
|
use session::Session;
|
||||||
|
@ -182,11 +181,7 @@ pub trait CrateStore<'tcx> {
|
||||||
-> ty::GenericPredicates<'tcx>;
|
-> ty::GenericPredicates<'tcx>;
|
||||||
fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||||
-> ty::GenericPredicates<'tcx>;
|
-> ty::GenericPredicates<'tcx>;
|
||||||
fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
fn item_generics(&self, def: DefId) -> ty::Generics;
|
||||||
-> 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_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
|
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 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;
|
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") }
|
-> ty::GenericPredicates<'tcx> { bug!("item_predicates") }
|
||||||
fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||||
-> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") }
|
-> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") }
|
||||||
fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
fn item_generics(&self, def: DefId) -> ty::Generics { bug!("item_generics") }
|
||||||
-> 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_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { bug!("item_attrs") }
|
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
|
fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef
|
||||||
{ bug!("trait_def") }
|
{ bug!("trait_def") }
|
||||||
|
|
|
@ -995,7 +995,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
let cstore = &self.sess.cstore;
|
let cstore = &self.sess.cstore;
|
||||||
self.xcrate_object_lifetime_defaults.entry(def_id).or_insert_with(|| {
|
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| {
|
unsubst.iter().map(|set| {
|
||||||
|
|
|
@ -64,7 +64,7 @@ pub struct GlobalArenas<'tcx> {
|
||||||
layout: TypedArena<Layout>,
|
layout: TypedArena<Layout>,
|
||||||
|
|
||||||
// references
|
// references
|
||||||
generics: TypedArena<ty::Generics<'tcx>>,
|
generics: TypedArena<ty::Generics>,
|
||||||
trait_def: TypedArena<ty::TraitDef>,
|
trait_def: TypedArena<ty::TraitDef>,
|
||||||
adt_def: TypedArena<ty::AdtDef>,
|
adt_def: TypedArena<ty::AdtDef>,
|
||||||
mir: TypedArena<RefCell<Mir<'tcx>>>,
|
mir: TypedArena<RefCell<Mir<'tcx>>>,
|
||||||
|
@ -467,9 +467,6 @@ pub struct GlobalCtxt<'tcx> {
|
||||||
// Cache for the type-contents routine. FIXME -- track deps?
|
// Cache for the type-contents routine. FIXME -- track deps?
|
||||||
pub tc_cache: RefCell<FxHashMap<Ty<'tcx>, ty::contents::TypeContents>>,
|
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
|
// FIXME dep tracking -- should be harmless enough
|
||||||
pub normalized_cache: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>,
|
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,
|
pub fn alloc_generics(self, generics: ty::Generics) -> &'gcx ty::Generics {
|
||||||
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> {
|
|
||||||
self.global_arenas.generics.alloc(generics)
|
self.global_arenas.generics.alloc(generics)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,7 +774,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
tc_cache: RefCell::new(FxHashMap()),
|
tc_cache: RefCell::new(FxHashMap()),
|
||||||
associated_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
associated_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||||
associated_item_def_ids: 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()),
|
normalized_cache: RefCell::new(FxHashMap()),
|
||||||
inhabitedness_cache: RefCell::new(FxHashMap()),
|
inhabitedness_cache: RefCell::new(FxHashMap()),
|
||||||
lang_items: lang_items,
|
lang_items: lang_items,
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use infer::type_variable;
|
use infer::type_variable;
|
||||||
use ty::{self, BoundRegion, Region, Ty, TyCtxt};
|
use ty::{self, BoundRegion, DefIdTree, Region, Ty, TyCtxt};
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
|
@ -287,8 +287,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
db.span_note(span, "a default was defined here...");
|
db.span_note(span, "a default was defined here...");
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
let item_def_id = self.parent(expected.def_id).unwrap();
|
||||||
db.note(&format!("a default is defined on `{}`",
|
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...");
|
db.span_note(span, "a second default was defined here...");
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
let item_def_id = self.parent(found.def_id).unwrap();
|
||||||
db.note(&format!("a second default is defined on `{}`",
|
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! { AssociatedItems: AssociatedItems(DefId) -> ty::AssociatedItem }
|
||||||
dep_map_ty! { Types: ItemSignature(DefId) -> Ty<'tcx> }
|
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! { Predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> }
|
||||||
dep_map_ty! { SuperPredicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> }
|
dep_map_ty! { SuperPredicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> }
|
||||||
dep_map_ty! { AssociatedItemDefIds: AssociatedItemDefIds(DefId) -> Rc<Vec<DefId>> }
|
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 hir::{map as hir_map, FreevarMap, TraitMap};
|
||||||
use middle;
|
use middle;
|
||||||
use hir::def::{Def, CtorKind, ExportMap};
|
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::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
|
||||||
use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
|
use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
|
||||||
|
use middle::resolve_lifetime::ObjectLifetimeDefault;
|
||||||
use mir::Mir;
|
use mir::Mir;
|
||||||
use traits;
|
use traits;
|
||||||
use ty;
|
use ty;
|
||||||
|
@ -33,6 +34,7 @@ use util::nodemap::{NodeSet, NodeMap, FxHashMap};
|
||||||
use serialize::{self, Encodable, Encoder};
|
use serialize::{self, Encodable, Encoder};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::{Cell, RefCell, Ref};
|
use std::cell::{Cell, RefCell, Ref};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -585,13 +587,13 @@ pub enum IntVarValue {
|
||||||
UintType(ast::UintTy),
|
UintType(ast::UintTy),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||||
pub struct TypeParameterDef<'tcx> {
|
pub struct TypeParameterDef {
|
||||||
pub name: Name,
|
pub name: Name,
|
||||||
pub def_id: DefId,
|
pub def_id: DefId,
|
||||||
pub index: u32,
|
pub index: u32,
|
||||||
pub default_def_id: DefId, // for use in error reporing about defaults
|
pub has_default: bool,
|
||||||
pub default: Option<Ty<'tcx>>,
|
pub object_lifetime_default: ObjectLifetimeDefault,
|
||||||
|
|
||||||
/// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
|
/// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
|
||||||
/// on generic parameter `T`, asserts data behind the parameter
|
/// on generic parameter `T`, asserts data behind the parameter
|
||||||
|
@ -628,16 +630,21 @@ impl RegionParameterDef {
|
||||||
/// Information about the formal type/lifetime parameters associated
|
/// Information about the formal type/lifetime parameters associated
|
||||||
/// with an item or method. Analogous to hir::Generics.
|
/// with an item or method. Analogous to hir::Generics.
|
||||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||||
pub struct Generics<'tcx> {
|
pub struct Generics {
|
||||||
pub parent: Option<DefId>,
|
pub parent: Option<DefId>,
|
||||||
pub parent_regions: u32,
|
pub parent_regions: u32,
|
||||||
pub parent_types: u32,
|
pub parent_types: u32,
|
||||||
pub regions: Vec<RegionParameterDef>,
|
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,
|
pub has_self: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Generics<'tcx> {
|
impl Generics {
|
||||||
pub fn parent_count(&self) -> usize {
|
pub fn parent_count(&self) -> usize {
|
||||||
self.parent_regions as usize + self.parent_types as 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 {
|
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]
|
&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()]
|
&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.
|
/// 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(
|
lookup_locally_or_in_crate_store(
|
||||||
"generics", did, &self.generics,
|
"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.
|
/// 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) {
|
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) {
|
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> {
|
impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> {
|
||||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||||
ty::GenericPredicates {
|
ty::GenericPredicates {
|
||||||
|
|
|
@ -184,7 +184,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
||||||
mut mk_type: FT)
|
mut mk_type: FT)
|
||||||
-> &'tcx Substs<'tcx>
|
-> &'tcx Substs<'tcx>
|
||||||
where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region,
|
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 defs = tcx.item_generics(def_id);
|
||||||
let mut substs = Vec::with_capacity(defs.count());
|
let mut substs = Vec::with_capacity(defs.count());
|
||||||
Substs::fill_item(&mut substs, tcx, defs, &mut mk_region, &mut mk_type);
|
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)
|
mut mk_type: FT)
|
||||||
-> &'tcx Substs<'tcx>
|
-> &'tcx Substs<'tcx>
|
||||||
where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region,
|
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 defs = tcx.item_generics(def_id);
|
||||||
let mut result = Vec::with_capacity(defs.count());
|
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>>,
|
fn fill_item<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
|
||||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
defs: &ty::Generics<'tcx>,
|
defs: &ty::Generics,
|
||||||
mk_region: &mut FR,
|
mk_region: &mut FR,
|
||||||
mk_type: &mut FT)
|
mk_type: &mut FT)
|
||||||
where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region,
|
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 {
|
if let Some(def_id) = defs.parent {
|
||||||
let parent_defs = tcx.item_generics(def_id);
|
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>>,
|
fn fill_single<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
|
||||||
defs: &ty::Generics<'tcx>,
|
defs: &ty::Generics,
|
||||||
mk_region: &mut FR,
|
mk_region: &mut FR,
|
||||||
mk_type: &mut FT)
|
mk_type: &mut FT)
|
||||||
where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region,
|
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.
|
// Handle Self first, before all regions.
|
||||||
let mut types = defs.types.iter();
|
let mut types = defs.types.iter();
|
||||||
if defs.parent.is_none() && defs.has_self {
|
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())
|
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 Substs<'tcx> {
|
||||||
tcx.mk_substs(self.iter().take(generics.count()).cloned())
|
tcx.mk_substs(self.iter().take(generics.count()).cloned())
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,11 +137,14 @@ pub fn parameterized(f: &mut fmt::Formatter,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !verbose {
|
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) {
|
if let Some(substs) = tcx.lift(&substs) {
|
||||||
let tps = substs.types().rev().skip(child_types);
|
let tps = substs.types().rev().skip(child_types);
|
||||||
for (def, actual) in generics.types.iter().rev().zip(tps) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
num_supplied_defaults += 1;
|
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 {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "TypeParameterDef({}, {:?}, {})",
|
write!(f, "TypeParameterDef({}, {:?}, {})",
|
||||||
self.name,
|
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::middle::cstore::{NativeLibrary, LinkMeta, LinkagePreference, LoadedMacro};
|
||||||
use rustc::hir::def::{self, Def};
|
use rustc::hir::def::{self, Def};
|
||||||
use rustc::middle::lang_items;
|
use rustc::middle::lang_items;
|
||||||
use rustc::middle::resolve_lifetime::ObjectLifetimeDefault;
|
|
||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
use rustc::ty::{self, Ty, TyCtxt};
|
use rustc::ty::{self, Ty, TyCtxt};
|
||||||
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
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)
|
self.get_crate_data(def.krate).get_super_predicates(def.index, tcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
fn item_generics(&self, def: DefId) -> ty::Generics {
|
||||||
-> ty::Generics<'tcx>
|
|
||||||
{
|
|
||||||
self.dep_graph.read(DepNode::MetaData(def));
|
self.dep_graph.read(DepNode::MetaData(def));
|
||||||
self.get_crate_data(def.krate).get_generics(def.index, tcx)
|
self.get_crate_data(def.krate).get_generics(def.index)
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>
|
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::{self, Def, CtorKind};
|
||||||
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||||
use rustc::middle::lang_items;
|
use rustc::middle::lang_items;
|
||||||
use rustc::middle::resolve_lifetime::ObjectLifetimeDefault;
|
|
||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
use rustc::ty::{self, Ty, TyCtxt};
|
use rustc::ty::{self, Ty, TyCtxt};
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
|
@ -601,30 +600,8 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_generics(&self,
|
pub fn get_generics(&self, item_id: DefIndex) -> ty::Generics {
|
||||||
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> {
|
|
||||||
self.entry(item_id).generics.unwrap().decode(self)
|
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> {
|
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 tcx = self.tcx;
|
||||||
let g = tcx.item_generics(def_id);
|
self.lazy(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,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_predicates(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
|
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,
|
EncodeContext::encode_info_for_foreign_item,
|
||||||
(def_id, ni));
|
(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) {
|
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
|
||||||
intravisit::walk_ty(self, ty);
|
intravisit::walk_ty(self, ty);
|
||||||
self.index.encode_info_for_ty(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> {
|
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) {
|
fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
|
||||||
if let hir::TyImplTrait(_) = ty.node {
|
if let hir::TyImplTrait(_) = ty.node {
|
||||||
let def_id = self.tcx.hir.local_def_id(ty.id);
|
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> {
|
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> {
|
fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
Entry {
|
Entry {
|
||||||
|
|
|
@ -16,7 +16,6 @@ use rustc::hir::def::{self, CtorKind};
|
||||||
use rustc::hir::def_id::{DefIndex, DefId};
|
use rustc::hir::def_id::{DefIndex, DefId};
|
||||||
use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary};
|
use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary};
|
||||||
use rustc::middle::lang_items;
|
use rustc::middle::lang_items;
|
||||||
use rustc::middle::resolve_lifetime::ObjectLifetimeDefault;
|
|
||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
use rustc::ty::{self, Ty, ReprOptions};
|
use rustc::ty::{self, Ty, ReprOptions};
|
||||||
use rustc_back::PanicStrategy;
|
use rustc_back::PanicStrategy;
|
||||||
|
@ -212,7 +211,7 @@ pub struct Entry<'tcx> {
|
||||||
pub ty: Option<Lazy<Ty<'tcx>>>,
|
pub ty: Option<Lazy<Ty<'tcx>>>,
|
||||||
pub inherent_impls: LazySeq<DefIndex>,
|
pub inherent_impls: LazySeq<DefIndex>,
|
||||||
pub variances: LazySeq<ty::Variance>,
|
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 predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>,
|
||||||
|
|
||||||
pub ast: Option<Lazy<astencode::Ast<'tcx>>>,
|
pub ast: Option<Lazy<astencode::Ast<'tcx>>>,
|
||||||
|
@ -246,20 +245,6 @@ pub enum EntryKind<'tcx> {
|
||||||
AssociatedConst(AssociatedContainer),
|
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)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct ModData {
|
pub struct ModData {
|
||||||
pub reexports: LazySeq<def::Export>,
|
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> {
|
impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
|
||||||
fn generics(&mut self) -> &mut Self {
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -892,7 +896,11 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
|
||||||
|
|
||||||
impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
|
impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
|
||||||
fn generics(&mut self) -> &mut Self {
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,33 @@
|
||||||
// use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
|
// use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
|
||||||
register_long_diagnostics! {
|
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##"
|
E0154: r##"
|
||||||
## Note: this error code is no longer emitted by the compiler.
|
## Note: this error code is no longer emitted by the compiler.
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,8 @@ enum ResolutionError<'a> {
|
||||||
AttemptToUseNonConstantValueInConstant,
|
AttemptToUseNonConstantValueInConstant,
|
||||||
/// error E0530: X bindings cannot shadow Ys
|
/// error E0530: X bindings cannot shadow Ys
|
||||||
BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>),
|
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,
|
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.span_label(binding.span, msg);
|
||||||
err
|
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.label_ribs.pop();
|
||||||
self.ribs[ValueNS].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)>;
|
pub type ErrorMessage = Option<(Span, String)>;
|
||||||
|
@ -718,6 +754,11 @@ enum RibKind<'a> {
|
||||||
|
|
||||||
// We passed through a `macro_rules!` statement with the given expansion
|
// We passed through a `macro_rules!` statement with the given expansion
|
||||||
MacroDefinition(Mark),
|
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.
|
/// 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> {
|
enum LexicalScopeBinding<'a> {
|
||||||
Item(&'a NameBinding<'a>),
|
Item(&'a NameBinding<'a>),
|
||||||
Def(Def),
|
Def(Def),
|
||||||
|
@ -1428,7 +1462,7 @@ impl<'a> Resolver<'a> {
|
||||||
if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() {
|
if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() {
|
||||||
// The ident resolves to a type parameter or local variable.
|
// The ident resolves to a type parameter or local variable.
|
||||||
return Some(LexicalScopeBinding::Def(
|
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.
|
// Resolve a local definition, potentially adjusting for closures.
|
||||||
fn adjust_local_def(&mut self, local_def: LocalDef, record_used: Option<Span>) -> Def {
|
fn adjust_local_def(&mut self,
|
||||||
let ribs = match local_def.ribs {
|
ns: Namespace,
|
||||||
Some((ns, i)) => &self.ribs[ns][i + 1..],
|
rib_index: usize,
|
||||||
None => &[] as &[_],
|
mut def: Def,
|
||||||
};
|
record_used: Option<Span>) -> Def {
|
||||||
let mut def = local_def.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 {
|
match def {
|
||||||
Def::Upvar(..) => {
|
Def::Upvar(..) => {
|
||||||
span_bug!(record_used.unwrap_or(DUMMY_SP), "unexpected {:?} in bindings", def)
|
span_bug!(record_used.unwrap_or(DUMMY_SP), "unexpected {:?} in bindings", def)
|
||||||
|
@ -2540,7 +2585,8 @@ impl<'a> Resolver<'a> {
|
||||||
Def::Local(def_id) => {
|
Def::Local(def_id) => {
|
||||||
for rib in ribs {
|
for rib in ribs {
|
||||||
match rib.kind {
|
match rib.kind {
|
||||||
NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) => {
|
NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) |
|
||||||
|
ForwardTyParamBanRibKind => {
|
||||||
// Nothing to do. Continue.
|
// Nothing to do. Continue.
|
||||||
}
|
}
|
||||||
ClosureRibKind(function_id) => {
|
ClosureRibKind(function_id) => {
|
||||||
|
@ -2593,7 +2639,7 @@ impl<'a> Resolver<'a> {
|
||||||
for rib in ribs {
|
for rib in ribs {
|
||||||
match rib.kind {
|
match rib.kind {
|
||||||
NormalRibKind | MethodRibKind(_) | ClosureRibKind(..) |
|
NormalRibKind | MethodRibKind(_) | ClosureRibKind(..) |
|
||||||
ModuleRibKind(..) | MacroDefinition(..) => {
|
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind => {
|
||||||
// Nothing to do. Continue.
|
// Nothing to do. Continue.
|
||||||
}
|
}
|
||||||
ItemRibKind => {
|
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>,
|
fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
generics: &ty::Generics<'tcx>,
|
generics: &ty::Generics,
|
||||||
substs: &Substs<'tcx>,
|
substs: &Substs<'tcx>,
|
||||||
file_metadata: DIFile,
|
file_metadata: DIFile,
|
||||||
name_to_append_suffix_to: &mut String)
|
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[..]);
|
return create_DIArray(DIB(cx), &template_params[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_type_parameter_names<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
fn get_type_parameter_names(cx: &CrateContext, generics: &ty::Generics) -> Vec<ast::Name> {
|
||||||
generics: &ty::Generics<'tcx>)
|
|
||||||
-> Vec<ast::Name> {
|
|
||||||
let mut names = generics.parent.map_or(vec![], |def_id| {
|
let mut names = generics.parent.map_or(vec![], |def_id| {
|
||||||
get_type_parameter_names(cx, cx.tcx().item_generics(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 super::namespace::item_namespace;
|
||||||
|
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
|
use rustc::ty::DefIdTree;
|
||||||
|
|
||||||
use llvm;
|
use llvm;
|
||||||
use llvm::debuginfo::{DIScope, DIBuilderRef, DIDescriptor, DIArray};
|
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)
|
pub fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: DefId)
|
||||||
-> (DIScope, Span) {
|
-> (DIScope, Span) {
|
||||||
let containing_scope = item_namespace(cx, DefId {
|
let containing_scope = item_namespace(cx, cx.tcx().parent(def_id)
|
||||||
krate: def_id.krate,
|
.expect("get_namespace_and_span_for_item: missing parent?"));
|
||||||
index: cx.tcx().def_key(def_id).parent
|
|
||||||
.expect("get_namespace_and_span_for_item: missing parent?")
|
|
||||||
});
|
|
||||||
|
|
||||||
// Try to get some span information, if we have an inlined item.
|
// Try to get some span information, if we have an inlined item.
|
||||||
let definition_span = cx.tcx().def_span(def_id);
|
let definition_span = cx.tcx().def_span(def_id);
|
||||||
|
|
|
@ -42,7 +42,7 @@ use std::cell::RefCell;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use syntax::{abi, ast};
|
use syntax::{abi, ast};
|
||||||
use syntax::feature_gate::{GateIssue, emit_feature_err};
|
use syntax::feature_gate::{GateIssue, emit_feature_err};
|
||||||
use syntax::symbol::{Symbol, keywords};
|
use syntax::symbol::Symbol;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
|
||||||
pub trait AstConv<'gcx, 'tcx> {
|
pub trait AstConv<'gcx, 'tcx> {
|
||||||
|
@ -53,7 +53,7 @@ pub trait AstConv<'gcx, 'tcx> {
|
||||||
|
|
||||||
/// Returns the generic type and lifetime parameters for an item.
|
/// Returns the generic type and lifetime parameters for an item.
|
||||||
fn get_generics(&self, span: Span, id: DefId)
|
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.
|
/// 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>;
|
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.
|
/// Same as ty_infer, but with a known type parameter definition.
|
||||||
fn ty_infer_for_def(&self,
|
fn ty_infer_for_def(&self,
|
||||||
_def: &ty::TypeParameterDef<'tcx>,
|
_def: &ty::TypeParameterDef,
|
||||||
_substs: &[Kind<'tcx>],
|
_substs: &[Kind<'tcx>],
|
||||||
span: Span) -> Ty<'tcx> {
|
span: Span) -> Ty<'tcx> {
|
||||||
self.ty_infer(span)
|
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 is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
|
||||||
let default_needs_object_self = |p: &ty::TypeParameterDef<'tcx>| {
|
let default_needs_object_self = |p: &ty::TypeParameterDef| {
|
||||||
if let Some(ref default) = p.default {
|
if is_object && p.has_default {
|
||||||
if is_object && default.has_self_ty() {
|
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
|
// There is no suitable inference default for a type parameter
|
||||||
// that references self, in an object type.
|
// that references self, in an object type.
|
||||||
return true;
|
return true;
|
||||||
|
@ -327,7 +328,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
self.ty_infer(span)
|
self.ty_infer(span)
|
||||||
};
|
};
|
||||||
ty_var
|
ty_var
|
||||||
} else if let Some(default) = def.default {
|
} else if def.has_default {
|
||||||
// No type parameter provided, but a default exists.
|
// No type parameter provided, but a default exists.
|
||||||
|
|
||||||
// If we are converting an object type, then the
|
// 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
|
tcx.types.err
|
||||||
} else {
|
} else {
|
||||||
// This is a default type parameter.
|
// 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 {
|
} else {
|
||||||
// We've already errored above about the mismatch.
|
// 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),
|
Err(ErrorReported) => return (tcx.types.err, Def::Err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(&ty::TyParam(_), Def::SelfTy(Some(trait_did), None)) => {
|
(&ty::TyParam(_), Def::SelfTy(Some(param_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::TyParam(param_did)) => {
|
(&ty::TyParam(_), Def::TyParam(param_did)) => {
|
||||||
let param_node_id = tcx.hir.as_local_node_id(param_did).unwrap();
|
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,
|
match self.find_bound_for_assoc_item(param_node_id,
|
||||||
param_name,
|
param_name,
|
||||||
assoc_name,
|
assoc_name,
|
||||||
|
@ -1063,21 +1058,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
tcx.prohibit_type_params(&path.segments);
|
tcx.prohibit_type_params(&path.segments);
|
||||||
|
|
||||||
let node_id = tcx.hir.as_local_node_id(did).unwrap();
|
let node_id = tcx.hir.as_local_node_id(did).unwrap();
|
||||||
let param = tcx.ty_param_defs.borrow().get(&node_id)
|
let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id));
|
||||||
.map(ty::ParamTy::for_def);
|
let index = match self.get_generics(span, item_def_id) {
|
||||||
if let Some(p) = param {
|
Ok(generics) => {
|
||||||
p.to_ty(tcx)
|
generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index]
|
||||||
} else {
|
}
|
||||||
// Only while computing defaults of earlier type
|
Err(ErrorReported) => return tcx.types.err
|
||||||
// parameters can a type parameter be missing its def.
|
};
|
||||||
struct_span_err!(tcx.sess, span, E0128,
|
tcx.mk_param(index, ::ty_param_name(tcx, node_id))
|
||||||
"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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Def::SelfTy(_, Some(def_id)) => {
|
Def::SelfTy(_, Some(def_id)) => {
|
||||||
// Self in impl (we know the concrete type).
|
// 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,
|
fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize,
|
||||||
ty_param_defs: &[ty::TypeParameterDef]) {
|
ty_param_defs: &[ty::TypeParameterDef]) {
|
||||||
let accepted = ty_param_defs.len();
|
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 {
|
if supplied < required {
|
||||||
let expected = if required < accepted {
|
let expected = if required < accepted {
|
||||||
"expected at least"
|
"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>,
|
fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
impl_m: &ty::AssociatedItem,
|
impl_m: &ty::AssociatedItem,
|
||||||
trait_generics: &ty::Generics<'tcx>,
|
trait_generics: &ty::Generics,
|
||||||
impl_generics: &ty::Generics<'tcx>,
|
impl_generics: &ty::Generics,
|
||||||
trait_to_skol_substs: &Substs<'tcx>,
|
trait_to_skol_substs: &Substs<'tcx>,
|
||||||
impl_to_skol_substs: &Substs<'tcx>)
|
impl_to_skol_substs: &Substs<'tcx>)
|
||||||
-> Result<(), ErrorReported> {
|
-> 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)
|
fn get_generics(&self, _: Span, id: DefId)
|
||||||
-> Result<&'tcx ty::Generics<'tcx>, ErrorReported>
|
-> Result<&'tcx ty::Generics, ErrorReported>
|
||||||
{
|
{
|
||||||
Ok(self.tcx().item_generics(id))
|
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)
|
node_id: ast::NodeId)
|
||||||
-> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
|
-> 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
|
let r = self.parameter_environment
|
||||||
.caller_bounds
|
.caller_bounds
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|predicate| {
|
.filter_map(|predicate| {
|
||||||
match *predicate {
|
match *predicate {
|
||||||
ty::Predicate::Trait(ref data) => {
|
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())
|
Some(data.to_poly_trait_ref())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -1426,7 +1429,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty_infer_for_def(&self,
|
fn ty_infer_for_def(&self,
|
||||||
ty_param_def: &ty::TypeParameterDef<'tcx>,
|
ty_param_def: &ty::TypeParameterDef,
|
||||||
substs: &[Kind<'tcx>],
|
substs: &[Kind<'tcx>],
|
||||||
span: Span) -> Ty<'tcx> {
|
span: Span) -> Ty<'tcx> {
|
||||||
self.type_var_for_def(span, ty_param_def, substs)
|
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) {
|
if let Some(ast_ty) = types.get(i) {
|
||||||
// A provided type parameter.
|
// A provided type parameter.
|
||||||
self.to_ty(ast_ty)
|
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.
|
// 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))
|
default.subst_spanned(self.tcx, substs, Some(span))
|
||||||
} else {
|
} else {
|
||||||
// No type parameters were provided, we can infer all.
|
// No type parameters were provided, we can infer all.
|
||||||
|
@ -4537,9 +4541,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
&generics.types
|
&generics.types
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let required_len = type_defs.iter()
|
let required_len = type_defs.iter().take_while(|d| !d.has_default).count();
|
||||||
.take_while(|d| d.default.is_none())
|
|
||||||
.count();
|
|
||||||
if types.len() > type_defs.len() {
|
if types.len() > type_defs.len() {
|
||||||
let span = types[type_defs.len()].span;
|
let span = types[type_defs.len()].span;
|
||||||
let expected_text = count_type_params(type_defs.len());
|
let expected_text = count_type_params(type_defs.len());
|
||||||
|
|
|
@ -62,6 +62,7 @@ use lint;
|
||||||
use constrained_type_params as ctp;
|
use constrained_type_params as ctp;
|
||||||
use middle::lang_items::SizedTraitLangItem;
|
use middle::lang_items::SizedTraitLangItem;
|
||||||
use middle::const_val::ConstVal;
|
use middle::const_val::ConstVal;
|
||||||
|
use middle::resolve_lifetime as rl;
|
||||||
use rustc_const_eval::EvalHint::UncheckedExprHint;
|
use rustc_const_eval::EvalHint::UncheckedExprHint;
|
||||||
use rustc_const_eval::{ConstContext, report_const_eval_err};
|
use rustc_const_eval::{ConstContext, report_const_eval_err};
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
|
@ -76,6 +77,7 @@ use CrateCtxt;
|
||||||
use rustc_const_math::ConstInt;
|
use rustc_const_math::ConstInt;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use syntax::{abi, ast, attr};
|
use syntax::{abi, ast, attr};
|
||||||
use syntax::symbol::{Symbol, keywords};
|
use syntax::symbol::{Symbol, keywords};
|
||||||
|
@ -186,6 +188,16 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> {
|
||||||
intravisit::walk_item(self, item);
|
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) {
|
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
|
||||||
if let hir::ExprClosure(..) = expr.node {
|
if let hir::ExprClosure(..) = expr.node {
|
||||||
let def_id = self.ccx.tcx.hir.local_def_id(expr.id);
|
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)));
|
tcx.item_path_str(def_id)));
|
||||||
}
|
}
|
||||||
AstConvRequest::GetTypeParameterBounds(id) => {
|
AstConvRequest::GetTypeParameterBounds(id) => {
|
||||||
let def = tcx.type_parameter_def(id);
|
|
||||||
err.note(
|
err.note(
|
||||||
&format!("the cycle begins when computing the bounds \
|
&format!("the cycle begins when computing the bounds \
|
||||||
for type parameter `{}`...",
|
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)));
|
tcx.item_path_str(def_id)));
|
||||||
}
|
}
|
||||||
AstConvRequest::GetTypeParameterBounds(id) => {
|
AstConvRequest::GetTypeParameterBounds(id) => {
|
||||||
let def = tcx.type_parameter_def(id);
|
|
||||||
err.note(
|
err.note(
|
||||||
&format!("...which then requires computing the bounds \
|
&format!("...which then requires computing the bounds \
|
||||||
for type parameter `{}`...",
|
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)));
|
tcx.item_path_str(def_id)));
|
||||||
}
|
}
|
||||||
AstConvRequest::GetTypeParameterBounds(id) => {
|
AstConvRequest::GetTypeParameterBounds(id) => {
|
||||||
let def = tcx.type_parameter_def(id);
|
|
||||||
err.note(
|
err.note(
|
||||||
&format!("...which then again requires computing the bounds \
|
&format!("...which then again requires computing the bounds \
|
||||||
for type parameter `{}`, completing the cycle.",
|
for type parameter `{}`, completing the cycle.",
|
||||||
def.name));
|
::ty_param_name(tcx, id)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit();
|
||||||
|
@ -385,7 +394,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_generics(&self, span: Span, id: DefId)
|
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), || {
|
self.ccx.cycle_check(span, AstConvRequest::GetGenerics(id), || {
|
||||||
Ok(generics_of_def_id(self.ccx, 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)
|
node_id: ast::NodeId)
|
||||||
-> Vec<ty::Predicate<'tcx>>
|
-> 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 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)
|
parent.get_type_parameter_bounds(astconv, span, node_id)
|
||||||
});
|
});
|
||||||
|
|
||||||
results.extend(self.predicates.iter().filter(|predicate| {
|
results.extend(self.predicates.iter().filter(|predicate| {
|
||||||
match **predicate {
|
match **predicate {
|
||||||
ty::Predicate::Trait(ref data) => {
|
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) => {
|
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::Equate(..) |
|
||||||
ty::Predicate::RegionOutlives(..) |
|
ty::Predicate::RegionOutlives(..) |
|
||||||
|
@ -568,7 +580,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
|
||||||
impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
|
impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
|
||||||
fn get_type_parameter_bounds(&self,
|
fn get_type_parameter_bounds(&self,
|
||||||
astconv: &AstConv<'tcx, 'tcx>,
|
astconv: &AstConv<'tcx, 'tcx>,
|
||||||
_: Span,
|
span: Span,
|
||||||
node_id: ast::NodeId)
|
node_id: ast::NodeId)
|
||||||
-> Vec<ty::Predicate<'tcx>>
|
-> 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
|
// written inline like `<T:Foo>` or in a where clause like
|
||||||
// `where T:Foo`.
|
// `where T:Foo`.
|
||||||
|
|
||||||
let def = astconv.tcx().type_parameter_def(node_id);
|
let tcx = astconv.tcx();
|
||||||
let ty = astconv.tcx().mk_param_from_def(&def);
|
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 =
|
let from_ty_params =
|
||||||
self.ty_params
|
self.ty_params
|
||||||
|
@ -594,7 +613,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
|
||||||
hir::WherePredicate::BoundPredicate(ref bp) => Some(bp),
|
hir::WherePredicate::BoundPredicate(ref bp) => Some(bp),
|
||||||
_ => None
|
_ => 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(|bp| bp.bounds.iter())
|
||||||
.flat_map(|b| predicates_from_bound(astconv, ty, b));
|
.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>,
|
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>,
|
struct_predicates: &ty::GenericPredicates<'tcx>,
|
||||||
field: &hir::StructField,
|
field: &hir::StructField,
|
||||||
ty_f: &'tcx ty::FieldDef)
|
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>,
|
fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||||
def: &'tcx ty::AdtDef,
|
def: &'tcx ty::AdtDef,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
generics: &'tcx ty::Generics<'tcx>,
|
generics: &'tcx ty::Generics,
|
||||||
predicates: ty::GenericPredicates<'tcx>,
|
predicates: ty::GenericPredicates<'tcx>,
|
||||||
variants: &[hir::Variant]) {
|
variants: &[hir::Variant]) {
|
||||||
// fill the field types
|
// 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>,
|
fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||||
def_id: DefId)
|
def_id: DefId)
|
||||||
-> &'tcx ty::Generics<'tcx> {
|
-> &'tcx ty::Generics {
|
||||||
let tcx = ccx.tcx;
|
let tcx = ccx.tcx;
|
||||||
let node_id = if let Some(id) = tcx.hir.as_local_node_id(def_id) {
|
let node_id = if let Some(id) = tcx.hir.as_local_node_id(def_id) {
|
||||||
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.
|
// the node id for the Self type parameter.
|
||||||
let param_id = item.id;
|
let param_id = item.id;
|
||||||
|
|
||||||
let parent = ccx.tcx.hir.get_parent(param_id);
|
opt_self = Some(ty::TypeParameterDef {
|
||||||
|
|
||||||
let def = ty::TypeParameterDef {
|
|
||||||
index: 0,
|
index: 0,
|
||||||
name: keywords::SelfType.name(),
|
name: keywords::SelfType.name(),
|
||||||
def_id: tcx.hir.local_def_id(param_id),
|
def_id: tcx.hir.local_def_id(param_id),
|
||||||
default_def_id: tcx.hir.local_def_id(parent),
|
has_default: false,
|
||||||
default: None,
|
object_lifetime_default: rl::Set1::Empty,
|
||||||
pure_wrt_drop: false,
|
pure_wrt_drop: false,
|
||||||
};
|
});
|
||||||
tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
|
|
||||||
opt_self = Some(def);
|
|
||||||
|
|
||||||
allow_defaults = true;
|
allow_defaults = true;
|
||||||
generics
|
generics
|
||||||
|
@ -1459,11 +1474,36 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let object_lifetime_defaults =
|
||||||
|
tcx.named_region_map.object_lifetime_defaults.get(&node_id);
|
||||||
|
|
||||||
// Now create the real type parameters.
|
// Now create the real type parameters.
|
||||||
let type_start = own_start + regions.len() as u32;
|
let type_start = own_start + regions.len() as u32;
|
||||||
let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| {
|
let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| {
|
||||||
let i = type_start + i as u32;
|
if p.name == keywords::SelfType.name() {
|
||||||
get_or_create_type_parameter_def(ccx, i, p, allow_defaults)
|
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();
|
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,
|
index: type_start + i as u32,
|
||||||
name: Symbol::intern("<upvar>"),
|
name: Symbol::intern("<upvar>"),
|
||||||
def_id: def_id,
|
def_id: def_id,
|
||||||
default_def_id: parent_def_id.unwrap(),
|
has_default: false,
|
||||||
default: None,
|
object_lifetime_default: rl::Set1::Empty,
|
||||||
pure_wrt_drop: false,
|
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 {
|
tcx.alloc_generics(ty::Generics {
|
||||||
parent: parent_def_id,
|
parent: parent_def_id,
|
||||||
parent_regions: parent_regions,
|
parent_regions: parent_regions,
|
||||||
parent_types: parent_types,
|
parent_types: parent_types,
|
||||||
regions: regions,
|
regions: regions,
|
||||||
types: types,
|
types: types,
|
||||||
|
type_param_to_index: type_param_to_index,
|
||||||
has_self: has_self || parent_has_self
|
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)
|
|def, _| ccx.tcx.mk_param_from_def(def)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
NodeTyParam(&hir::TyParam { default: Some(ref ty), .. }) => {
|
||||||
|
ccx.icx(&()).to_ty(ty)
|
||||||
|
}
|
||||||
x => {
|
x => {
|
||||||
bug!("unexpected sort of node in type_of_def_id(): {:?}", 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, }
|
pub enum SizedByDefault { Yes, No, }
|
||||||
|
|
||||||
/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
|
/// 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##"
|
E0131: r##"
|
||||||
It is not possible to define `main` with type parameters, or even with function
|
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 `()`.
|
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::ast;
|
||||||
use syntax::abi::Abi;
|
use syntax::abi::Abi;
|
||||||
|
use syntax::symbol::keywords;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
|
||||||
use std::iter;
|
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,
|
fn check_main_fn_ty(ccx: &CrateCtxt,
|
||||||
main_id: ast::NodeId,
|
main_id: ast::NodeId,
|
||||||
main_span: Span) {
|
main_span: Span) {
|
||||||
|
|
|
@ -279,7 +279,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_constraints_from_trait_ref(&mut self,
|
fn add_constraints_from_trait_ref(&mut self,
|
||||||
generics: &ty::Generics<'tcx>,
|
generics: &ty::Generics,
|
||||||
trait_ref: ty::TraitRef<'tcx>,
|
trait_ref: ty::TraitRef<'tcx>,
|
||||||
variance: VarianceTermPtr<'a>) {
|
variance: VarianceTermPtr<'a>) {
|
||||||
debug!("add_constraints_from_trait_ref: trait_ref={:?} variance={:?}",
|
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
|
/// in a context with the generics defined in `generics` and
|
||||||
/// ambient variance `variance`
|
/// ambient variance `variance`
|
||||||
fn add_constraints_from_ty(&mut self,
|
fn add_constraints_from_ty(&mut self,
|
||||||
generics: &ty::Generics<'tcx>,
|
generics: &ty::Generics,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
variance: VarianceTermPtr<'a>) {
|
variance: VarianceTermPtr<'a>) {
|
||||||
debug!("add_constraints_from_ty(ty={:?}, variance={:?})",
|
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,
|
/// Adds constraints appropriate for a nominal type (enum, struct,
|
||||||
/// object, etc) appearing in a context with ambient variance `variance`
|
/// object, etc) appearing in a context with ambient variance `variance`
|
||||||
fn add_constraints_from_substs(&mut self,
|
fn add_constraints_from_substs(&mut self,
|
||||||
generics: &ty::Generics<'tcx>,
|
generics: &ty::Generics,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
type_param_defs: &[ty::TypeParameterDef<'tcx>],
|
type_param_defs: &[ty::TypeParameterDef],
|
||||||
region_param_defs: &[ty::RegionParameterDef],
|
region_param_defs: &[ty::RegionParameterDef],
|
||||||
substs: &Substs<'tcx>,
|
substs: &Substs<'tcx>,
|
||||||
variance: VarianceTermPtr<'a>) {
|
variance: VarianceTermPtr<'a>) {
|
||||||
|
@ -465,7 +465,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
/// Adds constraints appropriate for a function with signature
|
/// Adds constraints appropriate for a function with signature
|
||||||
/// `sig` appearing in a context with ambient variance `variance`
|
/// `sig` appearing in a context with ambient variance `variance`
|
||||||
fn add_constraints_from_sig(&mut self,
|
fn add_constraints_from_sig(&mut self,
|
||||||
generics: &ty::Generics<'tcx>,
|
generics: &ty::Generics,
|
||||||
sig: &ty::PolyFnSig<'tcx>,
|
sig: &ty::PolyFnSig<'tcx>,
|
||||||
variance: VarianceTermPtr<'a>) {
|
variance: VarianceTermPtr<'a>) {
|
||||||
let contra = self.contravariant(variance);
|
let contra = self.contravariant(variance);
|
||||||
|
@ -478,7 +478,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
/// Adds constraints appropriate for a region appearing in a
|
/// Adds constraints appropriate for a region appearing in a
|
||||||
/// context with ambient variance `variance`
|
/// context with ambient variance `variance`
|
||||||
fn add_constraints_from_region(&mut self,
|
fn add_constraints_from_region(&mut self,
|
||||||
generics: &ty::Generics<'tcx>,
|
generics: &ty::Generics,
|
||||||
region: &'tcx ty::Region,
|
region: &'tcx ty::Region,
|
||||||
variance: VarianceTermPtr<'a>) {
|
variance: VarianceTermPtr<'a>) {
|
||||||
match *region {
|
match *region {
|
||||||
|
@ -518,7 +518,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
/// Adds constraints appropriate for a mutability-type pair
|
/// Adds constraints appropriate for a mutability-type pair
|
||||||
/// appearing in a context with ambient variance `variance`
|
/// appearing in a context with ambient variance `variance`
|
||||||
fn add_constraints_from_mt(&mut self,
|
fn add_constraints_from_mt(&mut self,
|
||||||
generics: &ty::Generics<'tcx>,
|
generics: &ty::Generics,
|
||||||
mt: &ty::TypeAndMut<'tcx>,
|
mt: &ty::TypeAndMut<'tcx>,
|
||||||
variance: VarianceTermPtr<'a>) {
|
variance: VarianceTermPtr<'a>) {
|
||||||
match mt.mutbl {
|
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 {
|
fn clean(&self, cx: &DocContext) -> TyParam {
|
||||||
cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx));
|
cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx));
|
||||||
TyParam {
|
TyParam {
|
||||||
name: self.name.clean(cx),
|
name: self.name.clean(cx),
|
||||||
did: self.def_id,
|
did: self.def_id,
|
||||||
bounds: vec![], // these are filled in from the where-clauses
|
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>) {
|
&'a ty::GenericPredicates<'tcx>) {
|
||||||
fn clean(&self, cx: &DocContext) -> Generics {
|
fn clean(&self, cx: &DocContext) -> Generics {
|
||||||
use self::WherePredicate as WP;
|
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_expr_post(&mut self, _ex: &'ast Expr) { }
|
||||||
fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) }
|
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_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) {
|
fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl, s: Span, _: NodeId) {
|
||||||
walk_fn(self, fk, fd, s)
|
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_attribute, &*param.attrs);
|
||||||
}
|
}
|
||||||
walk_list!(visitor, visit_lifetime_def, &generics.lifetimes);
|
walk_list!(visitor, visit_lifetime_def, &generics.lifetimes);
|
||||||
for predicate in &generics.where_clause.predicates {
|
walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates);
|
||||||
match *predicate {
|
}
|
||||||
WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty,
|
|
||||||
ref bounds,
|
pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a WherePredicate) {
|
||||||
ref bound_lifetimes,
|
match *predicate {
|
||||||
..}) => {
|
WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty,
|
||||||
visitor.visit_ty(bounded_ty);
|
ref bounds,
|
||||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
ref bound_lifetimes,
|
||||||
walk_list!(visitor, visit_lifetime_def, bound_lifetimes);
|
..}) => {
|
||||||
}
|
visitor.visit_ty(bounded_ty);
|
||||||
WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
|
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||||
ref bounds,
|
walk_list!(visitor, visit_lifetime_def, bound_lifetimes);
|
||||||
..}) => {
|
}
|
||||||
visitor.visit_lifetime(lifetime);
|
WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
|
||||||
walk_list!(visitor, visit_lifetime, bounds);
|
ref bounds,
|
||||||
}
|
..}) => {
|
||||||
WherePredicate::EqPredicate(WhereEqPredicate{ref lhs_ty,
|
visitor.visit_lifetime(lifetime);
|
||||||
ref rhs_ty,
|
walk_list!(visitor, visit_lifetime, bounds);
|
||||||
..}) => {
|
}
|
||||||
visitor.visit_ty(lhs_ty);
|
WherePredicate::EqPredicate(WhereEqPredicate{ref lhs_ty,
|
||||||
visitor.visit_ty(rhs_ty);
|
ref rhs_ty,
|
||||||
}
|
..}) => {
|
||||||
|
visitor.visit_ty(lhs_ty);
|
||||||
|
visitor.visit_ty(rhs_ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
trait Foo<X = Box<Foo>> {
|
trait Foo<X = Box<Foo>> {
|
||||||
//~^ ERROR unsupported cyclic reference
|
//~^ ERROR unsupported cyclic reference
|
||||||
|
//~| ERROR unsupported cyclic reference
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
|
|
||||||
struct Heap;
|
struct Heap;
|
||||||
|
|
||||||
struct Vec<A = Heap, T>;
|
struct Vec<A = Heap, T>(A, T);
|
||||||
//~^ ERROR type parameters with a default must be trailing
|
//~^ 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 must be trailing
|
||||||
//~| ERROR type parameters with a default cannot use forward declared identifiers
|
//~| ERROR type parameters with a default cannot use forward declared identifiers
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// Ensure that we get an error and not an ICE for this problematic case.
|
// 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
|
//~^ ERROR type parameters with a default cannot use forward declared identifiers
|
||||||
fn main() {
|
fn main() {
|
||||||
let x: Foo;
|
let x: Foo;
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
pub struct Foo<Bar=Bar>; //~ ERROR E0128
|
pub struct Foo<Bar=Bar>(Bar); //~ ERROR E0128
|
||||||
//~| NOTE defaulted type parameters cannot be forward declared
|
//~| NOTE defaulted type parameters cannot be forward declared
|
||||||
pub struct Baz(Foo);
|
pub struct Baz(Foo);
|
||||||
fn main() {}
|
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.
|
// 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: 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 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 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
|
impl Tr for S where Self::Assoc: Copy {} //~ ERROR `Self` type is used before it's determined
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue