Auto merge of #22182 - nikomatsakis:cycles-in-collect, r=nikomatsakis

This resolves a number of bugs that trigger stack overflows or other cyclic errors.

r? @nick29581 (it is based on work that you started)
f? @jroesch (also based on your branch)
This commit is contained in:
bors 2015-02-12 20:03:50 +00:00
commit 39b463f153
32 changed files with 1122 additions and 675 deletions

View file

@ -233,6 +233,14 @@ pub fn get_trait_def<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId) -> ty::TraitDe
decoder::get_trait_def(&*cdata, def.node, tcx)
}
pub fn get_predicates<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId)
-> ty::GenericPredicates<'tcx>
{
let cstore = &tcx.sess.cstore;
let cdata = cstore.get_crate_data(def.krate);
decoder::get_predicates(&*cdata, def.node, tcx)
}
pub fn get_field_type<'tcx>(tcx: &ty::ctxt<'tcx>, class_id: ast::DefId,
def: ast::DefId) -> ty::TypeScheme<'tcx> {
let cstore = &tcx.sess.cstore;

View file

@ -417,16 +417,22 @@ pub fn get_trait_def<'tcx>(cdata: Cmd,
}
}
pub fn get_predicates<'tcx>(cdata: Cmd,
item_id: ast::NodeId,
tcx: &ty::ctxt<'tcx>)
-> ty::GenericPredicates<'tcx>
{
let item_doc = lookup_item(item_id, cdata.data());
doc_predicates(item_doc, tcx, cdata, tag_item_generics)
}
pub fn get_type<'tcx>(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt<'tcx>)
-> ty::TypeScheme<'tcx> {
let item = lookup_item(id, cdata.data());
let t = item_type(ast::DefId { krate: cdata.cnum, node: id }, item, tcx,
-> ty::TypeScheme<'tcx>
{
let item_doc = lookup_item(id, cdata.data());
let t = item_type(ast::DefId { krate: cdata.cnum, node: id }, item_doc, tcx,
cdata);
let generics = doc_generics(item, tcx, cdata, tag_item_generics);
let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics);
ty::TypeScheme {
generics: generics,
ty: t
@ -882,14 +888,15 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
match item_sort(method_doc) {
'r' | 'p' => {
let generics = doc_generics(method_doc, tcx, cdata,
tag_method_ty_generics);
let generics = doc_generics(method_doc, tcx, cdata, tag_method_ty_generics);
let predicates = doc_predicates(method_doc, tcx, cdata, tag_method_ty_generics);
let fty = doc_method_fty(method_doc, tcx, cdata);
let explicit_self = get_explicit_self(method_doc);
let provided_source = get_provided_source(method_doc, cdata);
ty::MethodTraitItem(Rc::new(ty::Method::new(name,
generics,
predicates,
fty,
explicit_self,
vis,
@ -1520,6 +1527,17 @@ fn doc_generics<'tcx>(base_doc: rbml::Doc,
true
});
ty::Generics { types: types, regions: regions }
}
fn doc_predicates<'tcx>(base_doc: rbml::Doc,
tcx: &ty::ctxt<'tcx>,
cdata: Cmd,
tag: uint)
-> ty::GenericPredicates<'tcx>
{
let doc = reader::get_doc(base_doc, tag);
let mut predicates = subst::VecPerParamSpace::empty();
reader::tagged_docs(doc, tag_predicate, |predicate_doc| {
let space_doc = reader::get_doc(predicate_doc, tag_predicate_space);
@ -1533,7 +1551,7 @@ fn doc_generics<'tcx>(base_doc: rbml::Doc,
true
});
ty::Generics { types: types, regions: regions, predicates: predicates }
ty::GenericPredicates { predicates: predicates }
}
pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool {

View file

@ -139,11 +139,21 @@ fn encode_item_variances(rbml_w: &mut Encoder,
rbml_w.end_tag();
}
fn encode_bounds_and_type_for_item<'a, 'tcx>(rbml_w: &mut Encoder,
ecx: &EncodeContext<'a, 'tcx>,
id: ast::NodeId) {
encode_bounds_and_type(rbml_w,
ecx,
&ty::lookup_item_type(ecx.tcx, local_def(id)),
&ty::lookup_predicates(ecx.tcx, local_def(id)));
}
fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
ecx: &EncodeContext<'a, 'tcx>,
pty: &ty::TypeScheme<'tcx>) {
encode_generics(rbml_w, ecx, &pty.generics, tag_item_generics);
encode_type(ecx, rbml_w, pty.ty);
scheme: &ty::TypeScheme<'tcx>,
predicates: &ty::GenericPredicates<'tcx>) {
encode_generics(rbml_w, ecx, &scheme.generics, &predicates, tag_item_generics);
encode_type(ecx, rbml_w, scheme.ty);
}
fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) {
@ -353,8 +363,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
encode_disr_val(ecx, rbml_w, (*vi)[i].disr_val);
disr_val = (*vi)[i].disr_val;
}
encode_bounds_and_type(rbml_w, ecx,
&lookup_item_type(ecx.tcx, def_id));
encode_bounds_and_type_for_item(rbml_w, ecx, def_id.local_id());
ecx.tcx.map.with_path(variant.node.id, |path| encode_path(rbml_w, path));
rbml_w.end_tag();
@ -698,8 +707,7 @@ fn encode_info_for_struct(ecx: &EncodeContext,
token::get_name(nm), id);
encode_struct_field_family(rbml_w, field.vis);
encode_name(rbml_w, nm);
encode_bounds_and_type(rbml_w, ecx,
&lookup_item_type(ecx.tcx, local_def(id)));
encode_bounds_and_type_for_item(rbml_w, ecx, id);
encode_def_id(rbml_w, local_def(id));
let stab = stability::lookup(ecx.tcx, field.id);
@ -724,8 +732,7 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext,
rbml_w.start_tag(tag_items_data_item);
encode_def_id(rbml_w, local_def(ctor_id));
encode_family(rbml_w, 'o');
encode_bounds_and_type(rbml_w, ecx,
&lookup_item_type(ecx.tcx, local_def(ctor_id)));
encode_bounds_and_type_for_item(rbml_w, ecx, ctor_id);
encode_name(rbml_w, name.name);
ecx.tcx.map.with_path(ctor_id, |path| encode_path(rbml_w, path));
encode_parent_item(rbml_w, local_def(struct_id));
@ -749,6 +756,7 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext,
fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
ecx: &EncodeContext<'a, 'tcx>,
generics: &ty::Generics<'tcx>,
predicates: &ty::GenericPredicates<'tcx>,
tag: uint)
{
rbml_w.start_tag(tag);
@ -790,7 +798,7 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
rbml_w.end_tag();
}
for (space, _, predicate) in generics.predicates.iter_enumerated() {
for (space, _, predicate) in predicates.predicates.iter_enumerated() {
rbml_w.start_tag(tag_predicate);
rbml_w.wr_tagged_u8(tag_predicate_space, space as u8);
@ -810,7 +818,7 @@ fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
method_ty: &ty::Method<'tcx>) {
encode_def_id(rbml_w, method_ty.def_id);
encode_name(rbml_w, method_ty.name);
encode_generics(rbml_w, ecx, &method_ty.generics,
encode_generics(rbml_w, ecx, &method_ty.generics, &method_ty.predicates,
tag_method_ty_generics);
encode_method_fty(ecx, rbml_w, &method_ty.fty);
encode_visibility(rbml_w, method_ty.vis);
@ -844,15 +852,15 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
encode_stability(rbml_w, stab);
// The type for methods gets encoded twice, which is unfortunate.
let pty = lookup_item_type(ecx.tcx, m.def_id);
encode_bounds_and_type(rbml_w, ecx, &pty);
encode_bounds_and_type_for_item(rbml_w, ecx, m.def_id.local_id());
let elem = ast_map::PathName(m.name);
encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));
match ast_item_opt {
Some(&ast::MethodImplItem(ref ast_method)) => {
encode_attributes(rbml_w, &ast_method.attrs[]);
let any_types = !pty.generics.types.is_empty();
let scheme = ty::lookup_item_type(ecx.tcx, m.def_id);
let any_types = !scheme.generics.types.is_empty();
if any_types || is_default_impl || should_inline(&ast_method.attrs[]) {
encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id),
ast_item_opt.unwrap()));
@ -887,8 +895,7 @@ fn encode_info_for_associated_type(ecx: &EncodeContext,
encode_parent_item(rbml_w, local_def(parent_id));
encode_item_sort(rbml_w, 't');
let type_scheme = ty::lookup_item_type(ecx.tcx, associated_type.def_id);
encode_bounds_and_type(rbml_w, ecx, &type_scheme);
encode_bounds_and_type_for_item(rbml_w, ecx, associated_type.def_id.local_id());
let stab = stability::lookup(ecx.tcx, associated_type.def_id);
encode_stability(rbml_w, stab);
@ -1027,7 +1034,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
} else {
encode_family(rbml_w, 'c');
}
encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
encode_symbol(ecx, rbml_w, item.id);
encode_name(rbml_w, item.ident.name);
encode_path(rbml_w, path);
@ -1041,7 +1048,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
rbml_w.start_tag(tag_items_data_item);
encode_def_id(rbml_w, def_id);
encode_family(rbml_w, 'C');
encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
encode_name(rbml_w, item.ident.name);
encode_path(rbml_w, path);
encode_attributes(rbml_w, &item.attrs);
@ -1056,7 +1063,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_def_id(rbml_w, def_id);
encode_family(rbml_w, FN_FAMILY);
let tps_len = generics.ty_params.len();
encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
encode_name(rbml_w, item.ident.name);
encode_path(rbml_w, path);
encode_attributes(rbml_w, &item.attrs[]);
@ -1105,7 +1112,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
rbml_w.start_tag(tag_items_data_item);
encode_def_id(rbml_w, def_id);
encode_family(rbml_w, 'y');
encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
encode_name(rbml_w, item.ident.name);
encode_path(rbml_w, path);
encode_visibility(rbml_w, vis);
@ -1119,7 +1126,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_def_id(rbml_w, def_id);
encode_family(rbml_w, 't');
encode_item_variances(rbml_w, ecx, item.id);
encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
encode_name(rbml_w, item.ident.name);
encode_attributes(rbml_w, &item.attrs[]);
encode_repr_attrs(rbml_w, ecx, &item.attrs[]);
@ -1161,7 +1168,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
rbml_w.start_tag(tag_items_data_item);
encode_def_id(rbml_w, def_id);
encode_family(rbml_w, 'S');
encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
encode_item_variances(rbml_w, ecx, item.id);
encode_name(rbml_w, item.ident.name);
@ -1204,7 +1211,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
rbml_w.start_tag(tag_items_data_item);
encode_def_id(rbml_w, def_id);
encode_family(rbml_w, 'i');
encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
encode_name(rbml_w, item.ident.name);
encode_attributes(rbml_w, &item.attrs[]);
encode_unsafety(rbml_w, unsafety);
@ -1305,10 +1312,11 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_family(rbml_w, 'I');
encode_item_variances(rbml_w, ecx, item.id);
let trait_def = ty::lookup_trait_def(tcx, def_id);
let trait_predicates = ty::lookup_predicates(tcx, def_id);
encode_unsafety(rbml_w, trait_def.unsafety);
encode_paren_sugar(rbml_w, trait_def.paren_sugar);
encode_associated_type_names(rbml_w, &trait_def.associated_type_names);
encode_generics(rbml_w, ecx, &trait_def.generics, tag_item_generics);
encode_generics(rbml_w, ecx, &trait_def.generics, &trait_predicates, tag_item_generics);
encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
encode_name(rbml_w, item.ident.name);
encode_attributes(rbml_w, &item.attrs[]);
@ -1384,9 +1392,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
METHOD_FAMILY);
}
}
let pty = ty::lookup_item_type(tcx,
method_def_id);
encode_bounds_and_type(rbml_w, ecx, &pty);
encode_bounds_and_type_for_item(rbml_w, ecx, method_def_id.local_id());
is_nonstatic_method = method_ty.explicit_self !=
ty::StaticExplicitSelfCategory;
@ -1415,8 +1421,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
if is_nonstatic_method {
// FIXME: I feel like there is something funny
// going on.
let pty = ty::lookup_item_type(tcx, item_def_id.def_id());
encode_bounds_and_type(rbml_w, ecx, &pty);
encode_bounds_and_type_for_item(rbml_w, ecx, item_def_id.def_id().local_id());
}
};
match trait_item {
@ -1468,8 +1473,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
match nitem.node {
ast::ForeignItemFn(ref fndecl, _) => {
encode_family(rbml_w, FN_FAMILY);
encode_bounds_and_type(rbml_w, ecx,
&lookup_item_type(ecx.tcx,local_def(nitem.id)));
encode_bounds_and_type_for_item(rbml_w, ecx, nitem.id);
encode_name(rbml_w, nitem.ident.name);
if abi == abi::RustIntrinsic {
encode_inlined_item(ecx, rbml_w, IIForeignRef(nitem));
@ -1486,8 +1490,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
} else {
encode_family(rbml_w, 'c');
}
encode_bounds_and_type(rbml_w, ecx,
&lookup_item_type(ecx.tcx,local_def(nitem.id)));
encode_bounds_and_type_for_item(rbml_w, ecx, nitem.id);
encode_attributes(rbml_w, &*nitem.attrs);
let stab = stability::lookup(ecx.tcx, ast_util::local_def(nitem.id));
encode_stability(rbml_w, stab);

View file

@ -951,11 +951,6 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
Ok(encode_vec_per_param_space(
this, &type_scheme.generics.regions,
|this, def| def.encode(this).unwrap()))
});
this.emit_struct_field("predicates", 2, |this| {
Ok(encode_vec_per_param_space(
this, &type_scheme.generics.predicates,
|this, def| this.emit_predicate(ecx, def)))
})
})
});
@ -1574,7 +1569,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
fn read_type_scheme<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-> ty::TypeScheme<'tcx> {
self.read_struct("TypeScheme", 2, |this| {
self.read_struct("TypeScheme", 3, |this| {
Ok(ty::TypeScheme {
generics: this.read_struct_field("generics", 0, |this| {
this.read_struct("Generics", 2, |this| {
@ -1590,12 +1585,6 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
Ok(this.read_vec_per_param_space(
|this| Decodable::decode(this).unwrap()))
}).unwrap(),
predicates:
this.read_struct_field("predicates", 2, |this| {
Ok(this.read_vec_per_param_space(
|this| this.read_predicate(dcx)))
}).unwrap(),
})
})
}).unwrap(),

View file

@ -18,6 +18,7 @@ use middle::ty_fold::{self, TypeFoldable, TypeFolder};
use util::ppaux::Repr;
use std::fmt;
use std::iter::IntoIterator;
use std::slice::Iter;
use std::vec::{Vec, IntoIter};
use syntax::codemap::{Span, DUMMY_SP};
@ -529,6 +530,23 @@ impl<'a,T> Iterator for EnumeratedItems<'a,T> {
}
}
impl<T> IntoIterator for VecPerParamSpace<T> {
type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> {
self.into_vec().into_iter()
}
}
impl<'a,T> IntoIterator for &'a VecPerParamSpace<T> {
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
self.as_slice().into_iter()
}
}
///////////////////////////////////////////////////////////////////////////
// Public trait `Subst`
//

View file

@ -283,7 +283,7 @@ pub fn overlapping_impls(infcx: &InferCtxt,
/// Creates predicate obligations from the generic bounds.
pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
cause: ObligationCause<'tcx>,
generic_bounds: &ty::GenericBounds<'tcx>)
generic_bounds: &ty::InstantiatedPredicates<'tcx>)
-> PredicateObligations<'tcx>
{
util::predicates_for_generics(tcx, cause, 0, generic_bounds)

View file

@ -130,7 +130,10 @@ fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
// Search for a predicate like `Self : Sized` amongst the trait bounds.
let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
let free_substs = ty::construct_free_substs(tcx, &trait_def.generics, ast::DUMMY_NODE_ID);
let predicates = trait_def.generics.to_bounds(tcx, &free_substs).predicates.into_vec();
let trait_predicates = ty::lookup_predicates(tcx, trait_def_id);
let predicates = trait_predicates.instantiate(tcx, &free_substs).predicates.into_vec();
elaborate_predicates(tcx, predicates)
.any(|predicate| {
match predicate {

View file

@ -561,8 +561,8 @@ fn assemble_candidates_from_trait_def<'cx,'tcx>(
};
// If so, extract what we know from the trait and try to come up with a good answer.
let trait_def = ty::lookup_trait_def(selcx.tcx(), trait_ref.def_id);
let bounds = trait_def.generics.to_bounds(selcx.tcx(), trait_ref.substs);
let trait_predicates = ty::lookup_predicates(selcx.tcx(), trait_ref.def_id);
let bounds = trait_predicates.instantiate(selcx.tcx(), trait_ref.substs);
assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref,
candidate_set, bounds.predicates.into_vec());
}

View file

@ -923,8 +923,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
projection_trait_ref={}",
projection_trait_ref.repr(self.tcx()));
let trait_def = ty::lookup_trait_def(self.tcx(), projection_trait_ref.def_id);
let bounds = trait_def.generics.to_bounds(self.tcx(), projection_trait_ref.substs);
let trait_predicates = ty::lookup_predicates(self.tcx(), projection_trait_ref.def_id);
let bounds = trait_predicates.instantiate(self.tcx(), projection_trait_ref.substs);
debug!("match_projection_obligation_against_bounds_from_trait: \
bounds={}",
bounds.repr(self.tcx()));
@ -2314,8 +2314,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
snapshot: &infer::CombinedSnapshot)
-> VecPerParamSpace<PredicateObligation<'tcx>>
{
let impl_generics = ty::lookup_item_type(self.tcx(), impl_def_id).generics;
let bounds = impl_generics.to_bounds(self.tcx(), impl_substs);
let impl_bounds = ty::lookup_predicates(self.tcx(), impl_def_id);
let bounds = impl_bounds.instantiate(self.tcx(), impl_substs);
let normalized_bounds =
project::normalize_with_depth(self, cause.clone(), recursion_depth, &bounds);
let normalized_bounds =

View file

@ -290,7 +290,7 @@ impl<'tcx> fmt::Debug for super::VtableObjectData<'tcx> {
pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
cause: ObligationCause<'tcx>,
recursion_depth: uint,
generic_bounds: &ty::GenericBounds<'tcx>)
generic_bounds: &ty::InstantiatedPredicates<'tcx>)
-> VecPerParamSpace<PredicateObligation<'tcx>>
{
debug!("predicates_for_generics(generic_bounds={})",

View file

@ -192,7 +192,8 @@ impl ImplOrTraitItemId {
#[derive(Clone, Debug)]
pub struct Method<'tcx> {
pub name: ast::Name,
pub generics: ty::Generics<'tcx>,
pub generics: Generics<'tcx>,
pub predicates: GenericPredicates<'tcx>,
pub fty: BareFnTy<'tcx>,
pub explicit_self: ExplicitSelfCategory,
pub vis: ast::Visibility,
@ -206,6 +207,7 @@ pub struct Method<'tcx> {
impl<'tcx> Method<'tcx> {
pub fn new(name: ast::Name,
generics: ty::Generics<'tcx>,
predicates: GenericPredicates<'tcx>,
fty: BareFnTy<'tcx>,
explicit_self: ExplicitSelfCategory,
vis: ast::Visibility,
@ -216,6 +218,7 @@ impl<'tcx> Method<'tcx> {
Method {
name: name,
generics: generics,
predicates: predicates,
fty: fty,
explicit_self: explicit_self,
vis: vis,
@ -710,6 +713,10 @@ pub struct ctxt<'tcx> {
pub trait_refs: RefCell<NodeMap<Rc<TraitRef<'tcx>>>>,
pub trait_defs: RefCell<DefIdMap<Rc<TraitDef<'tcx>>>>,
/// Maps from the def-id of an item (trait/struct/enum/fn) to its
/// associated predicates.
pub predicates: RefCell<DefIdMap<GenericPredicates<'tcx>>>,
/// Maps from node-id of a trait object cast (like `foo as
/// Box<Trait>`) to the trait reference.
pub object_cast_map: ObjectCastMap<'tcx>,
@ -1782,7 +1789,6 @@ impl RegionParameterDef {
pub struct Generics<'tcx> {
pub types: VecPerParamSpace<TypeParameterDef<'tcx>>,
pub regions: VecPerParamSpace<RegionParameterDef>,
pub predicates: VecPerParamSpace<Predicate<'tcx>>,
}
impl<'tcx> Generics<'tcx> {
@ -1790,10 +1796,13 @@ impl<'tcx> Generics<'tcx> {
Generics {
types: VecPerParamSpace::empty(),
regions: VecPerParamSpace::empty(),
predicates: VecPerParamSpace::empty(),
}
}
pub fn is_empty(&self) -> bool {
self.types.is_empty() && self.regions.is_empty()
}
pub fn has_type_params(&self, space: subst::ParamSpace) -> bool {
!self.types.is_empty_in(space)
}
@ -1801,14 +1810,24 @@ impl<'tcx> Generics<'tcx> {
pub fn has_region_params(&self, space: subst::ParamSpace) -> bool {
!self.regions.is_empty_in(space)
}
}
pub fn is_empty(&self) -> bool {
self.types.is_empty() && self.regions.is_empty()
/// Bounds on generics.
#[derive(Clone, Debug)]
pub struct GenericPredicates<'tcx> {
pub predicates: VecPerParamSpace<Predicate<'tcx>>,
}
impl<'tcx> GenericPredicates<'tcx> {
pub fn empty() -> GenericPredicates<'tcx> {
GenericPredicates {
predicates: VecPerParamSpace::empty(),
}
}
pub fn to_bounds(&self, tcx: &ty::ctxt<'tcx>, substs: &Substs<'tcx>)
-> GenericBounds<'tcx> {
GenericBounds {
pub fn instantiate(&self, tcx: &ty::ctxt<'tcx>, substs: &Substs<'tcx>)
-> InstantiatedPredicates<'tcx> {
InstantiatedPredicates {
predicates: self.predicates.subst(tcx, substs),
}
}
@ -2022,11 +2041,11 @@ impl<'tcx> Predicate<'tcx> {
/// Represents the bounds declared on a particular set of type
/// parameters. Should eventually be generalized into a flag list of
/// where clauses. You can obtain a `GenericBounds` list from a
/// `Generics` by using the `to_bounds` method. Note that this method
/// reflects an important semantic invariant of `GenericBounds`: while
/// the bounds in a `Generics` are expressed in terms of the bound type
/// parameters of the impl/trait/whatever, a `GenericBounds` instance
/// where clauses. You can obtain a `InstantiatedPredicates` list from a
/// `GenericPredicates` by using the `instantiate` method. Note that this method
/// reflects an important semantic invariant of `InstantiatedPredicates`: while
/// the `GenericPredicates` are expressed in terms of the bound type
/// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance
/// represented a set of bounds for some particular instantiation,
/// meaning that the generic parameters have been substituted with
/// their values.
@ -2035,18 +2054,18 @@ impl<'tcx> Predicate<'tcx> {
///
/// struct Foo<T,U:Bar<T>> { ... }
///
/// Here, the `Generics` for `Foo` would contain a list of bounds like
/// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like
/// `[[], [U:Bar<T>]]`. Now if there were some particular reference
/// like `Foo<int,uint>`, then the `GenericBounds` would be `[[],
/// like `Foo<int,uint>`, then the `InstantiatedPredicates` would be `[[],
/// [uint:Bar<int>]]`.
#[derive(Clone, Debug)]
pub struct GenericBounds<'tcx> {
pub struct InstantiatedPredicates<'tcx> {
pub predicates: VecPerParamSpace<Predicate<'tcx>>,
}
impl<'tcx> GenericBounds<'tcx> {
pub fn empty() -> GenericBounds<'tcx> {
GenericBounds { predicates: VecPerParamSpace::empty() }
impl<'tcx> InstantiatedPredicates<'tcx> {
pub fn empty() -> InstantiatedPredicates<'tcx> {
InstantiatedPredicates { predicates: VecPerParamSpace::empty() }
}
pub fn has_escaping_regions(&self) -> bool {
@ -2134,10 +2153,12 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
match ty::impl_or_trait_item(cx, method_def_id) {
MethodTraitItem(ref method_ty) => {
let method_generics = &method_ty.generics;
let method_bounds = &method_ty.predicates;
construct_parameter_environment(
cx,
method.span,
method_generics,
method_bounds,
method.pe_body().id)
}
TypeTraitItem(_) => {
@ -2169,10 +2190,12 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
match ty::impl_or_trait_item(cx, method_def_id) {
MethodTraitItem(ref method_ty) => {
let method_generics = &method_ty.generics;
let method_bounds = &method_ty.predicates;
construct_parameter_environment(
cx,
method.span,
method_generics,
method_bounds,
method.pe_body().id)
}
TypeTraitItem(_) => {
@ -2195,11 +2218,13 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
ast::ItemFn(_, _, _, _, ref body) => {
// We assume this is a function.
let fn_def_id = ast_util::local_def(id);
let fn_pty = ty::lookup_item_type(cx, fn_def_id);
let fn_scheme = lookup_item_type(cx, fn_def_id);
let fn_predicates = lookup_predicates(cx, fn_def_id);
construct_parameter_environment(cx,
item.span,
&fn_pty.generics,
&fn_scheme.generics,
&fn_predicates,
body.id)
}
ast::ItemEnum(..) |
@ -2208,8 +2233,13 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
ast::ItemConst(..) |
ast::ItemStatic(..) => {
let def_id = ast_util::local_def(id);
let pty = ty::lookup_item_type(cx, def_id);
construct_parameter_environment(cx, item.span, &pty.generics, id)
let scheme = lookup_item_type(cx, def_id);
let predicates = lookup_predicates(cx, def_id);
construct_parameter_environment(cx,
item.span,
&scheme.generics,
&predicates,
id)
}
_ => {
cx.sess.span_bug(item.span,
@ -2248,10 +2278,13 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
/// stray references in a comment or something). We try to reserve the
/// "poly" prefix to refer to higher-ranked things, as in
/// `PolyTraitRef`.
///
/// Note that each item also comes with predicates, see
/// `lookup_predicates`.
#[derive(Clone, Debug)]
pub struct TypeScheme<'tcx> {
pub generics: Generics<'tcx>,
pub ty: Ty<'tcx>
pub ty: Ty<'tcx>,
}
/// As `TypeScheme` but for a trait ref.
@ -2393,6 +2426,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
item_substs: RefCell::new(NodeMap()),
trait_refs: RefCell::new(NodeMap()),
trait_defs: RefCell::new(DefIdMap()),
predicates: RefCell::new(DefIdMap()),
object_cast_map: RefCell::new(NodeMap()),
map: map,
intrinsic_defs: RefCell::new(DefIdMap()),
@ -5378,13 +5412,23 @@ pub fn lookup_item_type<'tcx>(cx: &ctxt<'tcx>,
/// Given the did of a trait, returns its canonical trait ref.
pub fn lookup_trait_def<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
-> Rc<ty::TraitDef<'tcx>> {
-> Rc<TraitDef<'tcx>> {
memoized(&cx.trait_defs, did, |did: DefId| {
assert!(did.krate != ast::LOCAL_CRATE);
Rc::new(csearch::get_trait_def(cx, did))
})
}
/// Given the did of a trait, returns its full set of predicates.
pub fn lookup_predicates<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
-> GenericPredicates<'tcx>
{
memoized(&cx.predicates, did, |did: DefId| {
assert!(did.krate != ast::LOCAL_CRATE);
csearch::get_predicates(cx, did)
})
}
/// Given a reference to a trait, returns the "superbounds" declared
/// on the trait, with appropriate substitutions applied. Basically,
/// this applies a filter to the where clauses on the trait, returning
@ -6287,7 +6331,7 @@ pub fn empty_parameter_environment<'a,'tcx>(cx: &'a ctxt<'tcx>) -> ParameterEnvi
/// parameters in the same way, this only has an effect on regions.
pub fn construct_free_substs<'a,'tcx>(
tcx: &'a ctxt<'tcx>,
generics: &ty::Generics<'tcx>,
generics: &Generics<'tcx>,
free_id: ast::NodeId)
-> Substs<'tcx>
{
@ -6332,6 +6376,7 @@ pub fn construct_parameter_environment<'a,'tcx>(
tcx: &'a ctxt<'tcx>,
span: Span,
generics: &ty::Generics<'tcx>,
generic_predicates: &ty::GenericPredicates<'tcx>,
free_id: ast::NodeId)
-> ParameterEnvironment<'a, 'tcx>
{
@ -6346,7 +6391,7 @@ pub fn construct_parameter_environment<'a,'tcx>(
// Compute the bounds on Self and the type parameters.
//
let bounds = generics.to_bounds(tcx, &free_substs);
let bounds = generic_predicates.instantiate(tcx, &free_substs);
let bounds = liberate_late_bound_regions(tcx, free_id_outlive, &ty::Binder(bounds));
let predicates = bounds.predicates.into_vec();
@ -6980,8 +7025,7 @@ impl<'tcx,T:RegionEscape> RegionEscape for VecPerParamSpace<T> {
impl<'tcx> RegionEscape for TypeScheme<'tcx> {
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
self.ty.has_regions_escaping_depth(depth) ||
self.generics.has_regions_escaping_depth(depth)
self.ty.has_regions_escaping_depth(depth)
}
}
@ -6991,7 +7035,7 @@ impl RegionEscape for Region {
}
}
impl<'tcx> RegionEscape for Generics<'tcx> {
impl<'tcx> RegionEscape for GenericPredicates<'tcx> {
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
self.predicates.has_regions_escaping_depth(depth)
}
@ -7100,7 +7144,7 @@ impl<'tcx> HasProjectionTypes for ClosureUpvar<'tcx> {
}
}
impl<'tcx> HasProjectionTypes for ty::GenericBounds<'tcx> {
impl<'tcx> HasProjectionTypes for ty::InstantiatedPredicates<'tcx> {
fn has_projection_types(&self) -> bool {
self.predicates.has_projection_types()
}

View file

@ -400,6 +400,13 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Generics<'tcx> {
ty::Generics {
types: self.types.fold_with(folder),
regions: self.regions.fold_with(folder),
}
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> {
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::GenericPredicates<'tcx> {
ty::GenericPredicates {
predicates: self.predicates.fold_with(folder),
}
}
@ -440,9 +447,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::GenericBounds<'tcx> {
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::GenericBounds<'tcx> {
ty::GenericBounds {
impl<'tcx> TypeFoldable<'tcx> for ty::InstantiatedPredicates<'tcx> {
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::InstantiatedPredicates<'tcx> {
ty::InstantiatedPredicates {
predicates: self.predicates.fold_with(folder),
}
}

View file

@ -395,8 +395,8 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
}
ty_enum(did, substs) | ty_struct(did, substs) => {
let base = ty::item_path_str(cx, did);
let generics = ty::lookup_item_type(cx, did).generics;
parameterized(cx, &base, substs, &generics, did, &[])
parameterized(cx, &base, substs, did, &[],
|| ty::lookup_item_type(cx, did).generics)
}
ty_trait(ref data) => {
data.user_string(cx)
@ -444,23 +444,40 @@ pub fn explicit_self_category_to_str(category: &ty::ExplicitSelfCategory)
}
}
pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
base: &str,
substs: &subst::Substs<'tcx>,
generics: &ty::Generics<'tcx>,
did: ast::DefId,
projections: &[ty::ProjectionPredicate<'tcx>])
-> String
pub fn parameterized<'tcx,GG>(cx: &ctxt<'tcx>,
base: &str,
substs: &subst::Substs<'tcx>,
did: ast::DefId,
projections: &[ty::ProjectionPredicate<'tcx>],
get_generics: GG)
-> String
where GG : FnOnce() -> ty::Generics<'tcx>
{
if cx.sess.verbose() {
if substs.is_noop() {
return format!("{}", base);
} else {
return format!("{}<{},{}>",
base,
substs.regions.repr(cx),
substs.types.repr(cx));
let mut strings = vec![];
match substs.regions {
subst::ErasedRegions => {
strings.push(format!(".."));
}
subst::NonerasedRegions(ref regions) => {
for region in regions.iter() {
strings.push(region.repr(cx));
}
}
}
for ty in substs.types.iter() {
strings.push(ty.repr(cx));
}
for projection in projections.iter() {
strings.push(format!("{}={}",
projection.projection_ty.item_name.user_string(cx),
projection.ty.user_string(cx)));
}
return if strings.is_empty() {
format!("{}", base)
} else {
format!("{}<{}>", base, strings.connect(","))
};
}
let mut strs = Vec::new();
@ -484,6 +501,13 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
}
}
// It is important to execute this conditionally, only if -Z
// verbose is false. Otherwise, debug logs can sometimes cause
// ICEs trying to fetch the generics early in the pipeline. This
// is kind of a hacky workaround in that -Z verbose is required to
// avoid those ICEs.
let generics = get_generics();
let tps = substs.types.get_slice(subst::TypeSpace);
let ty_params = generics.types.get_slice(subst::TypeSpace);
let has_defaults = ty_params.last().map_or(false, |def| def.default.is_some());
@ -645,13 +669,12 @@ impl<'tcx> UserString<'tcx> for TraitAndProjections<'tcx> {
fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
let &(ref trait_ref, ref projection_bounds) = self;
let base = ty::item_path_str(tcx, trait_ref.def_id);
let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id);
parameterized(tcx,
&base,
trait_ref.substs,
&trait_def.generics,
trait_ref.def_id,
&projection_bounds[])
&projection_bounds[],
|| ty::lookup_trait_def(tcx, trait_ref.def_id).generics.clone())
}
}
@ -687,10 +710,9 @@ impl<'tcx> UserString<'tcx> for ty::TyTrait<'tcx> {
}
impl<'tcx> Repr<'tcx> for ty::TypeParameterDef<'tcx> {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
format!("TypeParameterDef({:?}, {}, {:?}/{})",
fn repr(&self, _tcx: &ctxt<'tcx>) -> String {
format!("TypeParameterDef({:?}, {:?}/{})",
self.def_id,
self.bounds.repr(tcx),
self.space,
self.index)
}
@ -781,11 +803,8 @@ impl<'tcx> Repr<'tcx> for ty::TraitRef<'tcx> {
// to enumerate the `for<...>` etc because the debruijn index
// tells you everything you need to know.
let base = ty::item_path_str(tcx, self.def_id);
let trait_def = ty::lookup_trait_def(tcx, self.def_id);
format!("TraitRef({}, {})",
self.substs.self_ty().repr(tcx),
parameterized(tcx, &base, self.substs,
&trait_def.generics, self.def_id, &[]))
parameterized(tcx, &base, self.substs, self.def_id, &[],
|| ty::lookup_trait_def(tcx, self.def_id).generics.clone())
}
}
@ -987,16 +1006,22 @@ impl<'tcx> Repr<'tcx> for ty::TypeScheme<'tcx> {
impl<'tcx> Repr<'tcx> for ty::Generics<'tcx> {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
format!("Generics(types: {}, regions: {}, predicates: {})",
format!("Generics(types: {}, regions: {})",
self.types.repr(tcx),
self.regions.repr(tcx),
self.regions.repr(tcx))
}
}
impl<'tcx> Repr<'tcx> for ty::GenericPredicates<'tcx> {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
format!("GenericPredicates(predicates: {})",
self.predicates.repr(tcx))
}
}
impl<'tcx> Repr<'tcx> for ty::GenericBounds<'tcx> {
impl<'tcx> Repr<'tcx> for ty::InstantiatedPredicates<'tcx> {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
format!("GenericBounds({})",
format!("InstantiatedPredicates({})",
self.predicates.repr(tcx))
}
}
@ -1249,9 +1274,8 @@ impl<'tcx, T> UserString<'tcx> for ty::Binder<T>
impl<'tcx> UserString<'tcx> for ty::TraitRef<'tcx> {
fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
let path_str = ty::item_path_str(tcx, self.def_id);
let trait_def = ty::lookup_trait_def(tcx, self.def_id);
parameterized(tcx, &path_str, self.substs,
&trait_def.generics, self.def_id, &[])
parameterized(tcx, &path_str, self.substs, self.def_id, &[],
|| ty::lookup_trait_def(tcx, self.def_id).generics.clone())
}
}

View file

@ -16,11 +16,12 @@
//! somewhat differently during the collect and check phases,
//! particularly with respect to looking up the types of top-level
//! items. In the collect phase, the crate context is used as the
//! `AstConv` instance; in this phase, the `get_item_type_scheme()` function
//! triggers a recursive call to `ty_of_item()` (note that
//! `ast_ty_to_ty()` will detect recursive types and report an error).
//! In the check phase, when the FnCtxt is used as the `AstConv`,
//! `get_item_type_scheme()` just looks up the item type in `tcx.tcache`.
//! `AstConv` instance; in this phase, the `get_item_type_scheme()`
//! function triggers a recursive call to `type_scheme_of_item()`
//! (note that `ast_ty_to_ty()` will detect recursive types and report
//! an error). In the check phase, when the FnCtxt is used as the
//! `AstConv`, `get_item_type_scheme()` just looks up the item type in
//! `tcx.tcache` (using `ty::lookup_item_type`).
//!
//! The `RegionScope` trait controls what happens when the user does
//! not specify a region in some location where a region is required

View file

@ -467,8 +467,14 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
}
};
instantiate_path(pcx.fcx, path, ty::lookup_item_type(tcx, enum_def_id),
None, def, pat.span, pat.id);
instantiate_path(pcx.fcx,
path,
ty::lookup_item_type(tcx, enum_def_id),
&ty::lookup_predicates(tcx, enum_def_id),
None,
def,
pat.span,
pat.id);
let pat_ty = fcx.node_ty(pat.id);
demand::eqtype(fcx, pat.span, expected, pat_ty);
@ -499,6 +505,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
.map_or_else(|| def.def_id(), |(enum_def, _)| enum_def);
let ctor_scheme = ty::lookup_item_type(tcx, enum_def);
let ctor_predicates = ty::lookup_predicates(tcx, enum_def);
let path_scheme = if ty::is_fn_ty(ctor_scheme.ty) {
let fn_ret = ty::assert_no_late_bound_regions(tcx, &ty::ty_fn_ret(ctor_scheme.ty));
ty::TypeScheme {
@ -508,7 +515,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
} else {
ctor_scheme
};
instantiate_path(pcx.fcx, path, path_scheme, None, def, pat.span, pat.id);
instantiate_path(pcx.fcx, path, path_scheme, &ctor_predicates, None, def, pat.span, pat.id);
let pat_ty = fcx.node_ty(pat.id);
demand::eqtype(fcx, pat.span, expected, pat_ty);

View file

@ -205,7 +205,7 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
// however, because we want to replace all late-bound regions with
// region variables.
let impl_bounds =
impl_m.generics.to_bounds(tcx, impl_to_skol_substs);
impl_m.predicates.instantiate(tcx, impl_to_skol_substs);
let (impl_bounds, _) =
infcx.replace_late_bound_regions_with_fresh_var(
@ -216,7 +216,7 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
impl_bounds.repr(tcx));
// Normalize the associated types in the trait_bounds.
let trait_bounds = trait_m.generics.to_bounds(tcx, &trait_to_skol_substs);
let trait_bounds = trait_m.predicates.instantiate(tcx, &trait_to_skol_substs);
// Obtain the predicate split predicate sets for each.
let trait_pred = trait_bounds.predicates.split();

View file

@ -131,8 +131,9 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
let dtor_typescheme = ty::lookup_item_type(rcx.tcx(), impl_did);
let dtor_generics = dtor_typescheme.generics;
let dtor_predicates = ty::lookup_predicates(rcx.tcx(), impl_did);
let has_pred_of_interest = dtor_generics.predicates.iter().any(|pred| {
let has_pred_of_interest = dtor_predicates.predicates.iter().any(|pred| {
// In `impl<T> Drop where ...`, we automatically
// assume some predicate will be meaningful and thus
// represents a type through which we could reach

View file

@ -46,7 +46,7 @@ struct InstantiatedMethodSig<'tcx> {
/// Generic bounds on the method's parameters which must be added
/// as pending obligations.
method_bounds: ty::GenericBounds<'tcx>,
method_predicates: ty::InstantiatedPredicates<'tcx>,
}
pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
@ -99,7 +99,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
// Create the final signature for the method, replacing late-bound regions.
let InstantiatedMethodSig {
method_sig, all_substs, method_bounds
method_sig, all_substs, method_predicates
} = self.instantiate_method_sig(&pick, all_substs);
let method_self_ty = method_sig.inputs[0];
@ -107,7 +107,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
self.unify_receivers(self_ty, method_self_ty);
// Add any trait/regions obligations specified on the method's type parameters.
self.add_obligations(&pick, &all_substs, &method_bounds);
self.add_obligations(&pick, &all_substs, &method_predicates);
// Create the final `MethodCallee`.
let fty = ty::mk_bare_fn(self.tcx(), None, self.tcx().mk_bare_fn(ty::BareFnTy {
@ -416,18 +416,19 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
// that obligation is not necessarily satisfied. (In the
// future, it would be.) But we know that the true `Self` DOES implement
// the trait. So we just delete this requirement. Hack hack hack.
let mut method_bounds = pick.method_ty.generics.to_bounds(self.tcx(), &all_substs);
let mut method_predicates = pick.method_ty.predicates.instantiate(self.tcx(), &all_substs);
match pick.kind {
probe::ObjectPick(..) => {
assert_eq!(method_bounds.predicates.get_slice(subst::SelfSpace).len(), 1);
method_bounds.predicates.pop(subst::SelfSpace);
assert_eq!(method_predicates.predicates.get_slice(subst::SelfSpace).len(), 1);
method_predicates.predicates.pop(subst::SelfSpace);
}
_ => { }
}
let method_bounds = self.fcx.normalize_associated_types_in(self.span, &method_bounds);
let method_predicates = self.fcx.normalize_associated_types_in(self.span,
&method_predicates);
debug!("method_bounds after subst = {}",
method_bounds.repr(self.tcx()));
debug!("method_predicates after subst = {}",
method_predicates.repr(self.tcx()));
// Instantiate late-bound regions and substitute the trait
// parameters into the method type to get the actual method type.
@ -446,22 +447,22 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
InstantiatedMethodSig {
method_sig: method_sig,
all_substs: all_substs,
method_bounds: method_bounds,
method_predicates: method_predicates,
}
}
fn add_obligations(&mut self,
pick: &probe::Pick<'tcx>,
all_substs: &subst::Substs<'tcx>,
method_bounds: &ty::GenericBounds<'tcx>) {
debug!("add_obligations: pick={} all_substs={} method_bounds={}",
method_predicates: &ty::InstantiatedPredicates<'tcx>) {
debug!("add_obligations: pick={} all_substs={} method_predicates={}",
pick.repr(self.tcx()),
all_substs.repr(self.tcx()),
method_bounds.repr(self.tcx()));
method_predicates.repr(self.tcx()));
self.fcx.add_obligations_for_parameters(
traits::ObligationCause::misc(self.span, self.fcx.body_id),
method_bounds);
method_predicates);
self.fcx.add_default_region_param_bounds(
all_substs,

View file

@ -221,7 +221,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
//
// Note that as the method comes from a trait, it should not have
// any late-bound regions appearing in its bounds.
let method_bounds = fcx.instantiate_bounds(span, trait_ref.substs, &method_ty.generics);
let method_bounds = fcx.instantiate_bounds(span, trait_ref.substs, &method_ty.predicates);
assert!(!method_bounds.has_escaping_regions());
fcx.add_obligations_for_parameters(
traits::ObligationCause::misc(span, fcx.body_id),

View file

@ -666,8 +666,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
debug!("assemble_projection_candidates: projection_trait_ref={}",
projection_trait_ref.repr(self.tcx()));
let trait_def = ty::lookup_trait_def(self.tcx(), projection_trait_ref.def_id);
let bounds = trait_def.generics.to_bounds(self.tcx(), projection_trait_ref.substs);
let trait_predicates = ty::lookup_predicates(self.tcx(),
projection_trait_ref.def_id);
let bounds = trait_predicates.instantiate(self.tcx(), projection_trait_ref.substs);
let predicates = bounds.predicates.into_vec();
debug!("assemble_projection_candidates: predicates={}",
predicates.repr(self.tcx()));
@ -943,8 +944,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
// Check whether the impl imposes obligations we have to worry about.
let impl_generics = ty::lookup_item_type(self.tcx(), impl_def_id).generics;
let impl_bounds = impl_generics.to_bounds(self.tcx(), substs);
let impl_bounds = ty::lookup_predicates(self.tcx(), impl_def_id);
let impl_bounds = impl_bounds.instantiate(self.tcx(), substs);
let traits::Normalized { value: impl_bounds,
obligations: norm_obligations } =
traits::normalize(selcx, cause.clone(), &impl_bounds);

View file

@ -93,7 +93,7 @@ use middle::pat_util::{self, pat_id_map};
use middle::region::{self, CodeExtent};
use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
use middle::traits;
use middle::ty::{FnSig, VariantInfo, TypeScheme};
use middle::ty::{FnSig, GenericPredicates, VariantInfo, TypeScheme};
use middle::ty::{Disr, ParamTy, ParameterEnvironment};
use middle::ty::{self, HasProjectionTypes, RegionEscape, Ty};
use middle::ty::liberate_late_bound_regions;
@ -101,7 +101,7 @@ use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
use middle::ty_fold::{TypeFolder, TypeFoldable};
use rscope::RegionScope;
use session::Session;
use {CrateCtxt, lookup_def_ccx, no_params, require_same_types};
use {CrateCtxt, lookup_def_ccx, require_same_types};
use TypeAndSubsts;
use lint;
use util::common::{block_query, indenter, loop_query};
@ -1446,11 +1446,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn instantiate_bounds(&self,
span: Span,
substs: &Substs<'tcx>,
generics: &ty::Generics<'tcx>)
-> ty::GenericBounds<'tcx>
bounds: &ty::GenericPredicates<'tcx>)
-> ty::InstantiatedPredicates<'tcx>
{
ty::GenericBounds {
predicates: self.instantiate_type_scheme(span, substs, &generics.predicates)
ty::InstantiatedPredicates {
predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates)
}
}
@ -1561,12 +1561,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
let type_scheme =
ty::lookup_item_type(self.tcx(), def_id);
let type_predicates =
ty::lookup_predicates(self.tcx(), def_id);
let substs =
self.infcx().fresh_substs_for_generics(
span,
&type_scheme.generics);
let bounds =
self.instantiate_bounds(span, &substs, &type_scheme.generics);
self.instantiate_bounds(span, &substs, &type_predicates);
self.add_obligations_for_parameters(
traits::ObligationCause::new(
span,
@ -1594,7 +1596,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
let tcx = self.tcx();
let ty::TypeScheme { generics, ty: decl_ty } = ty::lookup_item_type(tcx, did);
let ty::TypeScheme { generics, ty: decl_ty } =
ty::lookup_item_type(tcx, did);
let wants_params =
generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);
@ -1843,16 +1846,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
pub fn add_obligations_for_parameters(&self,
cause: traits::ObligationCause<'tcx>,
generic_bounds: &ty::GenericBounds<'tcx>)
predicates: &ty::InstantiatedPredicates<'tcx>)
{
assert!(!generic_bounds.has_escaping_regions());
assert!(!predicates.has_escaping_regions());
debug!("add_obligations_for_parameters(generic_bounds={})",
generic_bounds.repr(self.tcx()));
debug!("add_obligations_for_parameters(predicates={})",
predicates.repr(self.tcx()));
let obligations = traits::predicates_for_generics(self.tcx(),
cause,
generic_bounds);
predicates);
obligations.map_move(|o| self.register_predicate(o));
}
@ -3616,8 +3619,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
}
ast::ExprPath(ref path) => {
let defn = lookup_def(fcx, path.span, id);
let pty = type_scheme_for_def(fcx, expr.span, defn);
instantiate_path(fcx, path, pty, None, defn, expr.span, expr.id);
let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn);
instantiate_path(fcx, path, scheme, &predicates, None, defn, expr.span, expr.id);
// We always require that the type provided as the value for
// a type parameter outlives the moment of instantiation.
@ -3629,10 +3632,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None);
let defn = lookup_def(fcx, expr.span, id);
let pty = type_scheme_for_def(fcx, expr.span, defn);
let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn);
let mut path = qpath.trait_ref.path.clone();
path.segments.push(qpath.item_path.clone());
instantiate_path(fcx, &path, pty, Some(self_ty), defn, expr.span, expr.id);
instantiate_path(fcx, &path, scheme, &predicates, Some(self_ty),
defn, expr.span, expr.id);
// We always require that the type provided as the value for
// a type parameter outlives the moment of instantiation.
@ -4048,9 +4052,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
};
if let Some(did) = did {
let polytype = ty::lookup_item_type(tcx, did);
let predicates = ty::lookup_predicates(tcx, did);
let substs = Substs::new_type(vec![idx_type], vec![]);
let bounds = fcx.instantiate_bounds(expr.span, &substs, &polytype.generics);
let bounds = fcx.instantiate_bounds(expr.span, &substs, &predicates);
fcx.add_obligations_for_parameters(
traits::ObligationCause::new(expr.span,
fcx.body_id,
@ -4631,46 +4635,36 @@ pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
}
// Returns the type parameter count and the type for the given definition.
pub fn type_scheme_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
sp: Span,
defn: def::Def)
-> TypeScheme<'tcx> {
fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
sp: Span,
defn: def::Def)
-> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
match defn {
def::DefLocal(nid) | def::DefUpvar(nid, _) => {
let typ = fcx.local_ty(sp, nid);
return no_params(typ);
}
def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) |
def::DefStatic(id, _) | def::DefVariant(_, id, _) |
def::DefStruct(id) | def::DefConst(id) => {
return ty::lookup_item_type(fcx.ccx.tcx, id);
}
def::DefTrait(_) |
def::DefTy(..) |
def::DefAssociatedTy(..) |
def::DefAssociatedPath(..) |
def::DefPrimTy(_) |
def::DefTyParam(..) => {
fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
}
def::DefMod(..) | def::DefForeignMod(..) => {
fcx.ccx.tcx.sess.span_bug(sp, "expected value, found module");
}
def::DefUse(..) => {
fcx.ccx.tcx.sess.span_bug(sp, "expected value, found use");
}
def::DefRegion(..) => {
fcx.ccx.tcx.sess.span_bug(sp, "expected value, found region");
}
def::DefTyParamBinder(..) => {
fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type parameter");
}
def::DefLabel(..) => {
fcx.ccx.tcx.sess.span_bug(sp, "expected value, found label");
}
def::DefSelfTy(..) => {
fcx.ccx.tcx.sess.span_bug(sp, "expected value, found self ty");
}
def::DefLocal(nid) | def::DefUpvar(nid, _) => {
let typ = fcx.local_ty(sp, nid);
(ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
ty::GenericPredicates::empty())
}
def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) |
def::DefStatic(id, _) | def::DefVariant(_, id, _) |
def::DefStruct(id) | def::DefConst(id) => {
(ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id))
}
def::DefTrait(_) |
def::DefTy(..) |
def::DefAssociatedTy(..) |
def::DefAssociatedPath(..) |
def::DefPrimTy(_) |
def::DefTyParam(..) |
def::DefMod(..) |
def::DefForeignMod(..) |
def::DefUse(..) |
def::DefRegion(..) |
def::DefTyParamBinder(..) |
def::DefLabel(..) |
def::DefSelfTy(..) => {
fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
}
}
}
@ -4679,6 +4673,7 @@ pub fn type_scheme_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
path: &ast::Path,
type_scheme: TypeScheme<'tcx>,
type_predicates: &ty::GenericPredicates<'tcx>,
opt_self_ty: Option<Ty<'tcx>>,
def: def::Def,
span: Span,
@ -4864,7 +4859,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// Add all the obligations that are required, substituting and
// normalized appropriately.
let bounds = fcx.instantiate_bounds(span, &substs, &type_scheme.generics);
let bounds = fcx.instantiate_bounds(span, &substs, &type_predicates);
fcx.add_obligations_for_parameters(
traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
&bounds);

View file

@ -1588,8 +1588,8 @@ fn projection_bounds<'a,'tcx>(rcx: &Rcx<'a, 'tcx>,
// ```
//
// we can thus deduce that `<T as SomeTrait<'a>>::SomeType : 'a`.
let trait_def = ty::lookup_trait_def(tcx, projection_ty.trait_ref.def_id);
let predicates = trait_def.generics.predicates.as_slice().to_vec();
let trait_predicates = ty::lookup_predicates(tcx, projection_ty.trait_ref.def_id);
let predicates = trait_predicates.predicates.as_slice().to_vec();
traits::elaborate_predicates(tcx, predicates)
.filter_map(|predicate| {
// we're only interesting in `T : 'a` style predicates:

View file

@ -107,12 +107,12 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
});
}
ast::ItemTrait(..) => {
let trait_def =
ty::lookup_trait_def(ccx.tcx, local_def(item.id));
let trait_predicates =
ty::lookup_predicates(ccx.tcx, local_def(item.id));
reject_non_type_param_bounds(
ccx.tcx,
item.span,
&trait_def.generics);
&trait_predicates);
}
_ => {}
}
@ -124,11 +124,13 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
let ccx = self.ccx;
let item_def_id = local_def(item.id);
let type_scheme = ty::lookup_item_type(ccx.tcx, item_def_id);
reject_non_type_param_bounds(ccx.tcx, item.span, &type_scheme.generics);
let type_predicates = ty::lookup_predicates(ccx.tcx, item_def_id);
reject_non_type_param_bounds(ccx.tcx, item.span, &type_predicates);
let param_env =
ty::construct_parameter_environment(ccx.tcx,
item.span,
&type_scheme.generics,
&type_predicates,
item.id);
let inh = Inherited::new(ccx.tcx, param_env);
let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(type_scheme.ty), item.id);
@ -283,9 +285,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
// Reject any predicates that do not involve a type parameter.
fn reject_non_type_param_bounds<'tcx>(tcx: &ty::ctxt<'tcx>,
span: Span,
generics: &ty::Generics<'tcx>) {
for predicate in generics.predicates.iter() {
predicates: &ty::GenericPredicates<'tcx>) {
for predicate in predicates.predicates.iter() {
match predicate {
&ty::Predicate::Trait(ty::Binder(ref tr)) => {
let found_param = tr.input_types().iter()
@ -367,7 +368,7 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
reject_non_type_param_bounds(
self.ccx.tcx,
method.span,
&ty_method.generics);
&ty_method.predicates);
reject_shadowing_type_parameters(
self.ccx.tcx,
method.span,
@ -415,9 +416,11 @@ impl<'cx,'tcx> BoundsChecker<'cx,'tcx> {
/// Note that it does not (currently, at least) check that `A : Copy` (that check is delegated
/// to the point where impl `A : Trait<B>` is implemented).
pub fn check_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
let trait_def = ty::lookup_trait_def(self.fcx.tcx(), trait_ref.def_id);
let trait_predicates = ty::lookup_predicates(self.fcx.tcx(), trait_ref.def_id);
let bounds = self.fcx.instantiate_bounds(self.span, trait_ref.substs, &trait_def.generics);
let bounds = self.fcx.instantiate_bounds(self.span,
trait_ref.substs,
&trait_predicates);
self.fcx.add_obligations_for_parameters(
traits::ObligationCause::new(
@ -482,8 +485,9 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
match t.sty{
ty::ty_struct(type_id, substs) |
ty::ty_enum(type_id, substs) => {
let type_scheme = ty::lookup_item_type(self.fcx.tcx(), type_id);
let bounds = self.fcx.instantiate_bounds(self.span, substs, &type_scheme.generics);
let type_predicates = ty::lookup_predicates(self.fcx.tcx(), type_id);
let bounds = self.fcx.instantiate_bounds(self.span, substs,
&type_predicates);
if self.binding_count == 0 {
self.fcx.add_obligations_for_parameters(
@ -603,10 +607,10 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
.collect()
}
fn filter_to_trait_obligations<'tcx>(bounds: ty::GenericBounds<'tcx>)
-> ty::GenericBounds<'tcx>
fn filter_to_trait_obligations<'tcx>(bounds: ty::InstantiatedPredicates<'tcx>)
-> ty::InstantiatedPredicates<'tcx>
{
let mut result = ty::GenericBounds::empty();
let mut result = ty::InstantiatedPredicates::empty();
for (space, _, predicate) in bounds.predicates.iter_enumerated() {
match *predicate {
ty::Predicate::Trait(..) |

View file

@ -247,6 +247,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
debug!("new_polytype={}", new_polytype.repr(tcx));
tcx.tcache.borrow_mut().insert(new_did, new_polytype);
tcx.predicates.borrow_mut().insert(new_did, new_method_ty.predicates.clone());
tcx.impl_or_trait_items
.borrow_mut()
.insert(new_did, ty::MethodTraitItem(new_method_ty));
@ -555,6 +556,7 @@ fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
debug!("subst_receiver_types_in_method_ty: combined_substs={}",
combined_substs.repr(tcx));
let method_predicates = method.predicates.subst(tcx, &combined_substs);
let mut method_generics = method.generics.subst(tcx, &combined_substs);
// replace the type parameters declared on the trait with those
@ -579,6 +581,7 @@ fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
ty::Method::new(
method.name,
method_generics,
method_predicates,
method_fty,
method.explicit_self,
method.vis,

File diff suppressed because it is too large Load diff

View file

@ -102,7 +102,6 @@ pub use rustc::util;
use middle::def;
use middle::infer;
use middle::subst;
use middle::subst::VecPerParamSpace;
use middle::ty::{self, Ty};
use session::config;
use util::common::time;
@ -177,17 +176,6 @@ fn lookup_def_ccx(ccx: &CrateCtxt, sp: Span, id: ast::NodeId)
lookup_def_tcx(ccx.tcx, sp, id)
}
fn no_params<'tcx>(t: Ty<'tcx>) -> ty::TypeScheme<'tcx> {
ty::TypeScheme {
generics: ty::Generics {
types: VecPerParamSpace::empty(),
regions: VecPerParamSpace::empty(),
predicates: VecPerParamSpace::empty(),
},
ty: t
}
}
fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>,
maybe_infcx: Option<&infer::InferCtxt<'a, 'tcx>>,
t1_is_expected: bool,

View file

@ -166,10 +166,11 @@ pub fn build_external_trait(cx: &DocContext, tcx: &ty::ctxt,
}
});
let trait_def = ty::lookup_trait_def(tcx, did);
let predicates = ty::lookup_predicates(tcx, did);
let bounds = trait_def.bounds.clean(cx);
clean::Trait {
unsafety: def.unsafety,
generics: (&def.generics, subst::TypeSpace).clean(cx),
generics: (&def.generics, &predicates, subst::TypeSpace).clean(cx),
items: items.collect(),
bounds: bounds,
}
@ -181,9 +182,10 @@ fn build_external_function(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) ->
ty::ty_bare_fn(_, ref f) => ((did, &f.sig).clean(cx), f.unsafety),
_ => panic!("bad function"),
};
let predicates = ty::lookup_predicates(tcx, did);
clean::Function {
decl: decl,
generics: (&t.generics, subst::FnSpace).clean(cx),
generics: (&t.generics, &predicates, subst::FnSpace).clean(cx),
unsafety: style,
}
}
@ -192,6 +194,7 @@ fn build_struct(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::Stru
use syntax::parse::token::special_idents::unnamed_field;
let t = ty::lookup_item_type(tcx, did);
let predicates = ty::lookup_predicates(tcx, did);
let fields = ty::lookup_struct_fields(tcx, did);
clean::Struct {
@ -201,7 +204,7 @@ fn build_struct(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::Stru
[ref f, ..] if f.name == unnamed_field.name => doctree::Tuple,
_ => doctree::Plain,
},
generics: (&t.generics, subst::TypeSpace).clean(cx),
generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx),
fields: fields.clean(cx),
fields_stripped: false,
}
@ -209,10 +212,11 @@ fn build_struct(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::Stru
fn build_type(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum {
let t = ty::lookup_item_type(tcx, did);
let predicates = ty::lookup_predicates(tcx, did);
match t.ty.sty {
ty::ty_enum(edid, _) if !csearch::is_typedef(&tcx.sess.cstore, did) => {
return clean::EnumItem(clean::Enum {
generics: (&t.generics, subst::TypeSpace).clean(cx),
generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx),
variants_stripped: false,
variants: ty::enum_variants(tcx, edid).clean(cx),
})
@ -222,7 +226,7 @@ fn build_type(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEn
clean::TypedefItem(clean::Typedef {
type_: t.ty.clean(cx),
generics: (&t.generics, subst::TypeSpace).clean(cx),
generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx),
})
}
@ -293,6 +297,7 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
let attrs = load_attrs(cx, tcx, did);
let ty = ty::lookup_item_type(tcx, did);
let predicates = ty::lookup_predicates(tcx, did);
let trait_items = csearch::get_impl_items(&tcx.sess.cstore, did)
.iter()
.filter_map(|did| {
@ -323,9 +328,10 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
ty::TypeTraitItem(ref assoc_ty) => {
let did = assoc_ty.def_id;
let type_scheme = ty::lookup_item_type(tcx, did);
let predicates = ty::lookup_predicates(tcx, did);
// Not sure the choice of ParamSpace actually matters here, because an
// associated type won't have generics on the LHS
let typedef = (type_scheme, subst::ParamSpace::TypeSpace).clean(cx);
let typedef = (type_scheme, predicates, subst::ParamSpace::TypeSpace).clean(cx);
Some(clean::Item {
name: Some(assoc_ty.name.clean(cx)),
inner: clean::TypedefItem(typedef),
@ -349,7 +355,7 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
}
}),
for_: ty.ty.clean(cx),
generics: (&ty.generics, subst::TypeSpace).clean(cx),
generics: (&ty.generics, &predicates, subst::TypeSpace).clean(cx),
items: trait_items,
polarity: polarity.map(|p| { p.clean(cx) }),
}),

View file

@ -860,7 +860,9 @@ impl Clean<Generics> for ast::Generics {
}
}
impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>, subst::ParamSpace) {
impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
&'a ty::GenericPredicates<'tcx>,
subst::ParamSpace) {
fn clean(&self, cx: &DocContext) -> Generics {
use std::collections::HashSet;
use syntax::ast::TraitBoundModifier as TBM;
@ -885,7 +887,8 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>, subst::ParamSpace) {
false
}
let (gens, space) = *self;
let (gens, preds, space) = *self;
// Bounds in the type_params and lifetimes fields are repeated in the predicates
// field (see rustc_typeck::collect::ty_generics), so remove them.
let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| {
@ -899,7 +902,8 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>, subst::ParamSpace) {
srp.clean(cx)
}).collect::<Vec<_>>();
let where_predicates = gens.predicates.get_slice(space).to_vec().clean(cx);
let where_predicates = preds.predicates.get_slice(space).to_vec().clean(cx);
// Type parameters have a Sized bound by default unless removed with ?Sized.
// Scan through the predicates and mark any type parameter with a Sized
// bound, removing the bounds as we find them.
@ -913,6 +917,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>, subst::ParamSpace) {
}
Some(pred)
}).collect::<Vec<_>>();
// Finally, run through the type parameters again and insert a ?Sized unbound for
// any we didn't find to be Sized.
for tp in &stripped_typarams {
@ -1303,7 +1308,7 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
source: Span::empty(),
inner: TyMethodItem(TyMethod {
unsafety: self.fty.unsafety,
generics: (&self.generics, subst::FnSpace).clean(cx),
generics: (&self.generics, &self.predicates, subst::FnSpace).clean(cx),
self_: self_,
decl: (self.def_id, &sig).clean(cx),
abi: self.fty.abi
@ -2560,12 +2565,12 @@ impl Clean<Item> for ast::Typedef {
}
}
impl<'a> Clean<Typedef> for (ty::TypeScheme<'a>, ParamSpace) {
impl<'a> Clean<Typedef> for (ty::TypeScheme<'a>, ty::GenericPredicates<'a>, ParamSpace) {
fn clean(&self, cx: &DocContext) -> Typedef {
let (ref ty_scheme, ps) = *self;
let (ref ty_scheme, ref predicates, ps) = *self;
Typedef {
type_: ty_scheme.ty.clean(cx),
generics: (&ty_scheme.generics, ps).clean(cx)
generics: (&ty_scheme.generics, predicates, ps).clean(cx)
}
}
}

View file

@ -366,6 +366,14 @@ pub struct DefId {
pub node: NodeId,
}
impl DefId {
/// Read the node id, asserting that this def-id is krate-local.
pub fn local_id(&self) -> NodeId {
assert_eq!(self.krate, LOCAL_CRATE);
self.node
}
}
/// Item definitions in the currently-compiled crate would have the CrateNum
/// LOCAL_CRATE in their DefId.
pub const LOCAL_CRATE: CrateNum = 0;

View file

@ -0,0 +1,36 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test references to `Self::Item` in the trait. Issue #20220.
use std::vec;
trait IntoIteratorX {
type Item;
type IntoIter: Iterator<Item=Self::Item>;
fn into_iter_x(self) -> Self::IntoIter;
}
impl<T> IntoIteratorX for Vec<T> {
type Item = T;
type IntoIter = vec::IntoIter<T>;
fn into_iter_x(self) -> vec::IntoIter<T> {
self.into_iter()
}
}
fn main() {
let vec = vec![1, 2, 3];
for (i, e) in vec.into_iter().enumerate() {
assert_eq!(i+1, e);
}
}

View file

@ -0,0 +1,47 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test references to the trait `Stream` in the bounds for associated
// types defined on `Stream`. Issue #20551.
trait Stream {
type Car;
type Cdr: Stream;
fn car(&self) -> Self::Car;
fn cdr(self) -> Self::Cdr;
}
impl Stream for () {
type Car = ();
type Cdr = ();
fn car(&self) -> () { () }
fn cdr(self) -> () { self }
}
impl<T,U> Stream for (T, U)
where T : Clone, U : Stream
{
type Car = T;
type Cdr = U;
fn car(&self) -> T { self.0.clone() }
fn cdr(self) -> U { self.1 }
}
fn main() {
let p = (22, (44, (66, ())));
assert_eq!(p.car(), 22);
let p = p.cdr();
assert_eq!(p.car(), 44);
let p = p.cdr();
assert_eq!(p.car(), 66);
}

View file

@ -0,0 +1,36 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test that we are able to successfully compile a setup where a trait
// (`Trait1`) references a struct (`SomeType<u32>`) which in turn
// carries a predicate that references the trait (`u32 : Trait1`,
// substituted).
#![allow(dead_code)]
trait Trait1 : Trait2<SomeType<u32>> {
fn dumb(&self) { }
}
trait Trait2<A> {
fn dumber(&self, _: A) { }
}
struct SomeType<A>
where A : Trait1
{
a: A
}
impl Trait1 for u32 { }
impl Trait2<SomeType<u32>> for u32 { }
fn main() { }