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:
commit
39b463f153
32 changed files with 1122 additions and 675 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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={})",
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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(..) |
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) }),
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
36
src/test/run-pass/associated-types-issue-20220.rs
Normal file
36
src/test/run-pass/associated-types-issue-20220.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
47
src/test/run-pass/associated-types-stream.rs
Normal file
47
src/test/run-pass/associated-types-stream.rs
Normal 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);
|
||||
}
|
||||
36
src/test/run-pass/astconv-cycle-between-trait-and-type.rs
Normal file
36
src/test/run-pass/astconv-cycle-between-trait-and-type.rs
Normal 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() { }
|
||||
Loading…
Add table
Add a link
Reference in a new issue