Implement "perfect forwarding" for HR impls (#19730).
This commit is contained in:
parent
c2ca1a4b62
commit
f45c0ef51e
src
librustc
lint
metadata
middle
librustc_trans
librustc_typeck
librustdoc/clean
test/compile-fail
@ -1784,9 +1784,7 @@ impl LintPass for Stability {
|
||||
method_num: index,
|
||||
..
|
||||
}) => {
|
||||
ty::trait_item(cx.tcx,
|
||||
trait_ref.def_id(),
|
||||
index).def_id()
|
||||
ty::trait_item(cx.tcx, trait_ref.def_id, index).def_id()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ pub fn get_field_type<'tcx>(tcx: &ty::ctxt<'tcx>, class_id: ast::DefId,
|
||||
// if there is one.
|
||||
pub fn get_impl_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
def: ast::DefId)
|
||||
-> Option<Rc<ty::PolyTraitRef<'tcx>>> {
|
||||
-> Option<Rc<ty::TraitRef<'tcx>>> {
|
||||
let cstore = &tcx.sess.cstore;
|
||||
let cdata = cstore.get_crate_data(def.krate);
|
||||
decoder::get_impl_trait(&*cdata, def.node, tcx)
|
||||
|
@ -425,11 +425,11 @@ pub fn get_repr_attrs(cdata: Cmd, id: ast::NodeId) -> Vec<attr::ReprAttr> {
|
||||
pub fn get_impl_trait<'tcx>(cdata: Cmd,
|
||||
id: ast::NodeId,
|
||||
tcx: &ty::ctxt<'tcx>)
|
||||
-> Option<Rc<ty::PolyTraitRef<'tcx>>>
|
||||
-> Option<Rc<ty::TraitRef<'tcx>>>
|
||||
{
|
||||
let item_doc = lookup_item(id, cdata.data());
|
||||
reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| {
|
||||
Rc::new(ty::Binder(doc_trait_ref(tp, tcx, cdata)))
|
||||
Rc::new(doc_trait_ref(tp, tcx, cdata))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -887,7 +887,7 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
|
||||
this.emit_enum_variant("MethodTypeParam", 2, 1, |this| {
|
||||
this.emit_struct("MethodParam", 2, |this| {
|
||||
try!(this.emit_struct_field("trait_ref", 0, |this| {
|
||||
Ok(this.emit_trait_ref(ecx, &p.trait_ref.0))
|
||||
Ok(this.emit_trait_ref(ecx, &*p.trait_ref))
|
||||
}));
|
||||
try!(this.emit_struct_field("method_num", 0, |this| {
|
||||
this.emit_uint(p.method_num)
|
||||
@ -901,7 +901,7 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
|
||||
this.emit_enum_variant("MethodTraitObject", 3, 1, |this| {
|
||||
this.emit_struct("MethodObject", 2, |this| {
|
||||
try!(this.emit_struct_field("trait_ref", 0, |this| {
|
||||
Ok(this.emit_trait_ref(ecx, &o.trait_ref.0))
|
||||
Ok(this.emit_trait_ref(ecx, &*o.trait_ref))
|
||||
}));
|
||||
try!(this.emit_struct_field("object_trait_id", 0, |this| {
|
||||
Ok(this.emit_def_id(o.object_trait_id))
|
||||
@ -1457,7 +1457,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
|
||||
ty::MethodParam {
|
||||
trait_ref: {
|
||||
this.read_struct_field("trait_ref", 0, |this| {
|
||||
Ok(this.read_poly_trait_ref(dcx))
|
||||
Ok(this.read_trait_ref(dcx))
|
||||
}).unwrap()
|
||||
},
|
||||
method_num: {
|
||||
@ -1475,7 +1475,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
|
||||
ty::MethodObject {
|
||||
trait_ref: {
|
||||
this.read_struct_field("trait_ref", 0, |this| {
|
||||
Ok(this.read_poly_trait_ref(dcx))
|
||||
Ok(this.read_trait_ref(dcx))
|
||||
}).unwrap()
|
||||
},
|
||||
object_trait_id: {
|
||||
|
@ -112,7 +112,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
||||
..
|
||||
}) => {
|
||||
let trait_item = ty::trait_item(self.tcx,
|
||||
trait_ref.def_id(),
|
||||
trait_ref.def_id,
|
||||
index);
|
||||
match trait_item {
|
||||
ty::MethodTraitItem(method) => {
|
||||
|
@ -265,7 +265,7 @@ impl OverloadedCallType {
|
||||
}
|
||||
Some(ref trait_ref) => (*trait_ref).clone(),
|
||||
};
|
||||
OverloadedCallType::from_trait_id(tcx, trait_ref.def_id())
|
||||
OverloadedCallType::from_trait_id(tcx, trait_ref.def_id)
|
||||
}
|
||||
|
||||
fn from_unboxed_closure(tcx: &ty::ctxt, closure_did: ast::DefId)
|
||||
@ -292,7 +292,7 @@ impl OverloadedCallType {
|
||||
}
|
||||
MethodTypeParam(MethodParam { ref trait_ref, .. }) |
|
||||
MethodTraitObject(MethodObject { ref trait_ref, .. }) => {
|
||||
OverloadedCallType::from_trait_id(tcx, trait_ref.def_id())
|
||||
OverloadedCallType::from_trait_id(tcx, trait_ref.def_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -395,7 +395,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<String> {
|
||||
match *values {
|
||||
infer::Types(ref exp_found) => self.expected_found_str(exp_found),
|
||||
infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found)
|
||||
infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found),
|
||||
infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1647,6 +1648,16 @@ impl<'tcx> Resolvable<'tcx> for Ty<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Resolvable<'tcx> for Rc<ty::TraitRef<'tcx>> {
|
||||
fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>)
|
||||
-> Rc<ty::TraitRef<'tcx>> {
|
||||
Rc::new(infcx.resolve_type_vars_if_possible(&**self))
|
||||
}
|
||||
fn contains_error(&self) -> bool {
|
||||
ty::trait_ref_contains_error(&**self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Resolvable<'tcx> for Rc<ty::PolyTraitRef<'tcx>> {
|
||||
fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>)
|
||||
-> Rc<ty::PolyTraitRef<'tcx>> {
|
||||
|
@ -219,7 +219,7 @@ impl<'tcx,C> HigherRankedRelations<'tcx> for C
|
||||
self.infcx().resolve_type_vars_if_possible(&result0);
|
||||
debug!("glb result0 = {}", result0.repr(self.tcx()));
|
||||
|
||||
// Generalize the regions appearing in fn_ty0 if possible
|
||||
// Generalize the regions appearing in result0 if possible
|
||||
let new_vars = self.infcx().region_vars_confined_to_snapshot(snapshot);
|
||||
let span = self.trace().origin.span();
|
||||
let result1 =
|
||||
@ -358,7 +358,7 @@ fn fold_regions_in<'tcx, T, F>(tcx: &ty::ctxt<'tcx>,
|
||||
where T : Combineable<'tcx>,
|
||||
F : FnMut(ty::Region, ty::DebruijnIndex) -> ty::Region,
|
||||
{
|
||||
unbound_value.fold_with(&mut ty_fold::RegionFolder::new(tcx, |region, current_depth| {
|
||||
unbound_value.fold_with(&mut ty_fold::RegionFolder::new(tcx, &mut |region, current_depth| {
|
||||
// we should only be encountering "escaping" late-bound regions here,
|
||||
// because the ones at the current level should have been replaced
|
||||
// with fresh variables
|
||||
@ -414,11 +414,11 @@ impl<'a,'tcx> InferCtxtExt<'tcx> for InferCtxt<'a,'tcx> {
|
||||
*
|
||||
* The reason is that when we walk through the subtyping
|
||||
* algorith, we begin by replacing `'a` with a skolemized
|
||||
* variable `'0`. We then have `fn(_#0t) <: fn(&'0 int)`. This
|
||||
* can be made true by unifying `_#0t` with `&'0 int`. In the
|
||||
* variable `'1`. We then have `fn(_#0t) <: fn(&'1 int)`. This
|
||||
* can be made true by unifying `_#0t` with `&'1 int`. In the
|
||||
* process, we create a fresh variable for the skolemized
|
||||
* region, `'$0`, and hence we have that `_#0t == &'$0
|
||||
* int`. However, because `'$0` was created during the sub
|
||||
* region, `'$2`, and hence we have that `_#0t == &'$2
|
||||
* int`. However, because `'$2` was created during the sub
|
||||
* computation, if we're not careful we will erroneously
|
||||
* assume it is one of the transient region variables
|
||||
* representing a lub/glb internally. Not good.
|
||||
@ -522,3 +522,93 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// This code converts from skolemized regions back to late-bound
|
||||
/// regions. It works by replacing each region in the taint set of a
|
||||
/// skolemized region with a bound-region. The bound region will be bound
|
||||
/// by the outer-most binder in `value`; the caller must ensure that there is
|
||||
/// such a binder and it is the right place.
|
||||
///
|
||||
/// This routine is only intended to be used when the leak-check has
|
||||
/// passed; currently, it's used in the trait matching code to create
|
||||
/// a set of nested obligations frmo an impl that matches against
|
||||
/// something higher-ranked. More details can be found in
|
||||
/// `middle::traits::doc.rs`.
|
||||
///
|
||||
/// As a brief example, consider the obligation `for<'a> Fn(&'a int)
|
||||
/// -> &'a int`, and the impl:
|
||||
///
|
||||
/// impl<A,R> Fn<A,R> for SomethingOrOther
|
||||
/// where A : Clone
|
||||
/// { ... }
|
||||
///
|
||||
/// Here we will have replaced `'a` with a skolemized region
|
||||
/// `'0`. This means that our substitution will be `{A=>&'0
|
||||
/// int, R=>&'0 int}`.
|
||||
///
|
||||
/// When we apply the substitution to the bounds, we will wind up with
|
||||
/// `&'0 int : Clone` as a predicate. As a last step, we then go and
|
||||
/// replace `'0` with a late-bound region `'a`. The depth is matched
|
||||
/// to the depth of the predicate, in this case 1, so that the final
|
||||
/// predicate is `for<'a> &'a int : Clone`.
|
||||
pub fn plug_leaks<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
|
||||
skol_map: SkolemizationMap,
|
||||
snapshot: &CombinedSnapshot,
|
||||
value: &T)
|
||||
-> T
|
||||
where T : TypeFoldable<'tcx> + Repr<'tcx>
|
||||
{
|
||||
debug_assert!(leak_check(infcx, &skol_map, snapshot).is_ok());
|
||||
|
||||
debug!("plug_leaks(skol_map={}, value={})",
|
||||
skol_map.repr(infcx.tcx),
|
||||
value.repr(infcx.tcx));
|
||||
|
||||
// Compute a mapping from the "taint set" of each skolemized
|
||||
// region back to the `ty::BoundRegion` that it originally
|
||||
// represented. Because `leak_check` passed, we know that that
|
||||
// these taint sets are mutually disjoint.
|
||||
let inv_skol_map: FnvHashMap<ty::Region, ty::BoundRegion> =
|
||||
skol_map
|
||||
.into_iter()
|
||||
.flat_map(|(skol_br, skol)| {
|
||||
infcx.tainted_regions(snapshot, skol)
|
||||
.into_iter()
|
||||
.map(move |tainted_region| (tainted_region, skol_br))
|
||||
})
|
||||
.collect();
|
||||
|
||||
debug!("plug_leaks: inv_skol_map={}",
|
||||
inv_skol_map.repr(infcx.tcx));
|
||||
|
||||
// Remove any instantiated type variables from `value`; those can hide
|
||||
// references to regions from the `fold_regions` code below.
|
||||
let value = infcx.resolve_type_vars_if_possible(value);
|
||||
|
||||
// Map any skolemization byproducts back to a late-bound
|
||||
// region. Put that late-bound region at whatever the outermost
|
||||
// binder is that we encountered in `value`. The caller is
|
||||
// responsible for ensuring that (a) `value` contains at least one
|
||||
// binder and (b) that binder is the one we want to use.
|
||||
let result = ty_fold::fold_regions(infcx.tcx, &value, |r, current_depth| {
|
||||
match inv_skol_map.get(&r) {
|
||||
None => r,
|
||||
Some(br) => {
|
||||
// It is the responsibility of the caller to ensure
|
||||
// that each skolemized region appears within a
|
||||
// binder. In practice, this routine is only used by
|
||||
// trait checking, and all of the skolemized regions
|
||||
// appear inside predicates, which always have
|
||||
// binders, so this assert is satisfied.
|
||||
assert!(current_depth > 1);
|
||||
|
||||
ty::ReLateBound(ty::DebruijnIndex::new(current_depth - 1), br.clone())
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
debug!("plug_leaks: result={}",
|
||||
result.repr(infcx.tcx));
|
||||
|
||||
result
|
||||
}
|
||||
|
@ -137,7 +137,8 @@ impl Copy for TypeOrigin {}
|
||||
#[deriving(Clone, Show)]
|
||||
pub enum ValuePairs<'tcx> {
|
||||
Types(ty::expected_found<Ty<'tcx>>),
|
||||
TraitRefs(ty::expected_found<Rc<ty::PolyTraitRef<'tcx>>>),
|
||||
TraitRefs(ty::expected_found<Rc<ty::TraitRef<'tcx>>>),
|
||||
PolyTraitRefs(ty::expected_found<Rc<ty::PolyTraitRef<'tcx>>>),
|
||||
}
|
||||
|
||||
/// The trace designates the path through inference that we took to
|
||||
@ -349,7 +350,7 @@ pub fn can_mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
|
||||
b: Ty<'tcx>)
|
||||
-> ures<'tcx> {
|
||||
debug!("can_mk_subty({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx));
|
||||
cx.probe(|| {
|
||||
cx.probe(|_| {
|
||||
let trace = TypeTrace {
|
||||
origin: Misc(codemap::DUMMY_SP),
|
||||
values: Types(expected_found(true, a, b))
|
||||
@ -362,7 +363,7 @@ pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
|
||||
a: Ty<'tcx>, b: Ty<'tcx>)
|
||||
-> ures<'tcx> {
|
||||
debug!("can_mk_subty({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx));
|
||||
cx.probe(|| {
|
||||
cx.probe(|_| {
|
||||
let trace = TypeTrace {
|
||||
origin: Misc(codemap::DUMMY_SP),
|
||||
values: Types(expected_found(true, a, b))
|
||||
@ -634,11 +635,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
|
||||
/// Execute `f` then unroll any bindings it creates
|
||||
pub fn probe<R, F>(&self, f: F) -> R where
|
||||
F: FnOnce() -> R,
|
||||
F: FnOnce(&CombinedSnapshot) -> R,
|
||||
{
|
||||
debug!("probe()");
|
||||
let snapshot = self.start_snapshot();
|
||||
let r = f();
|
||||
let r = f(&snapshot);
|
||||
self.rollback_to(snapshot);
|
||||
r
|
||||
}
|
||||
@ -683,12 +684,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn sub_poly_trait_refs(&self,
|
||||
a_is_expected: bool,
|
||||
origin: TypeOrigin,
|
||||
a: Rc<ty::PolyTraitRef<'tcx>>,
|
||||
b: Rc<ty::PolyTraitRef<'tcx>>)
|
||||
-> ures<'tcx>
|
||||
pub fn sub_trait_refs(&self,
|
||||
a_is_expected: bool,
|
||||
origin: TypeOrigin,
|
||||
a: Rc<ty::TraitRef<'tcx>>,
|
||||
b: Rc<ty::TraitRef<'tcx>>)
|
||||
-> ures<'tcx>
|
||||
{
|
||||
debug!("sub_trait_refs({} <: {})",
|
||||
a.repr(self.tcx),
|
||||
@ -696,8 +697,26 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
self.commit_if_ok(|| {
|
||||
let trace = TypeTrace {
|
||||
origin: origin,
|
||||
values: TraitRefs(expected_found(a_is_expected,
|
||||
a.clone(), b.clone()))
|
||||
values: TraitRefs(expected_found(a_is_expected, a.clone(), b.clone()))
|
||||
};
|
||||
self.sub(a_is_expected, trace).trait_refs(&*a, &*b).to_ures()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn sub_poly_trait_refs(&self,
|
||||
a_is_expected: bool,
|
||||
origin: TypeOrigin,
|
||||
a: Rc<ty::PolyTraitRef<'tcx>>,
|
||||
b: Rc<ty::PolyTraitRef<'tcx>>)
|
||||
-> ures<'tcx>
|
||||
{
|
||||
debug!("sub_poly_trait_refs({} <: {})",
|
||||
a.repr(self.tcx),
|
||||
b.repr(self.tcx));
|
||||
self.commit_if_ok(|| {
|
||||
let trace = TypeTrace {
|
||||
origin: origin,
|
||||
values: PolyTraitRefs(expected_found(a_is_expected, a.clone(), b.clone()))
|
||||
};
|
||||
self.sub(a_is_expected, trace).binders(&*a, &*b).to_ures()
|
||||
})
|
||||
@ -727,6 +746,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn plug_leaks<T>(&self,
|
||||
skol_map: SkolemizationMap,
|
||||
snapshot: &CombinedSnapshot,
|
||||
value: &T)
|
||||
-> T
|
||||
where T : TypeFoldable<'tcx> + Repr<'tcx>
|
||||
{
|
||||
/*! See `higher_ranked::leak_check` */
|
||||
|
||||
higher_ranked::plug_leaks(self, skol_map, snapshot, value)
|
||||
}
|
||||
|
||||
pub fn equality_predicate(&self,
|
||||
span: Span,
|
||||
predicate: &ty::PolyEquatePredicate<'tcx>)
|
||||
|
@ -257,8 +257,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
|
||||
};
|
||||
let tr = ty::impl_trait_ref(self.tcx, local_def(item.id));
|
||||
let public_trait = tr.clone().map_or(false, |tr| {
|
||||
!is_local(tr.def_id()) ||
|
||||
self.exported_items.contains(&tr.def_id().node)
|
||||
!is_local(tr.def_id) ||
|
||||
self.exported_items.contains(&tr.def_id.node)
|
||||
});
|
||||
|
||||
if public_ty || public_trait {
|
||||
@ -407,7 +407,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
||||
match ty::impl_trait_ref(self.tcx, id) {
|
||||
Some(t) => {
|
||||
debug!("privacy - impl of trait {}", id);
|
||||
self.def_privacy(t.def_id())
|
||||
self.def_privacy(t.def_id)
|
||||
}
|
||||
None => {
|
||||
debug!("privacy - found a method {}",
|
||||
@ -432,7 +432,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
||||
match ty::impl_trait_ref(self.tcx, id) {
|
||||
Some(t) => {
|
||||
debug!("privacy - impl of trait {}", id);
|
||||
self.def_privacy(t.def_id())
|
||||
self.def_privacy(t.def_id)
|
||||
}
|
||||
None => {
|
||||
debug!("privacy - found a typedef {}",
|
||||
@ -811,7 +811,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
||||
// is whether the trait itself is accessible or not.
|
||||
MethodTypeParam(MethodParam { ref trait_ref, .. }) |
|
||||
MethodTraitObject(MethodObject { ref trait_ref, .. }) => {
|
||||
self.report_error(self.ensure_public(span, trait_ref.def_id(),
|
||||
self.report_error(self.ensure_public(span, trait_ref.def_id,
|
||||
None, "source trait"));
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +108,8 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
|
||||
ast::ItemTy(_, ref generics) |
|
||||
ast::ItemEnum(_, ref generics) |
|
||||
ast::ItemStruct(_, ref generics) |
|
||||
ast::ItemTrait(_, ref generics, _, _, _) => {
|
||||
ast::ItemTrait(_, ref generics, _, _, _) |
|
||||
ast::ItemImpl(_, ref generics, _, _, _) => {
|
||||
// These kinds of items have only early bound lifetime parameters.
|
||||
let lifetimes = &generics.lifetimes;
|
||||
let early_scope = EarlyScope(subst::TypeSpace, lifetimes, &ROOT_SCOPE);
|
||||
@ -117,12 +118,6 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
|
||||
visit::walk_item(this, item);
|
||||
});
|
||||
}
|
||||
ast::ItemImpl(_, ref generics, _, _, _) => {
|
||||
// Impls have both early- and late-bound lifetimes.
|
||||
this.visit_early_late(subst::TypeSpace, generics, |this| {
|
||||
visit::walk_item(this, item);
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ use super::util;
|
||||
use middle::subst;
|
||||
use middle::subst::Subst;
|
||||
use middle::ty::{mod, Ty};
|
||||
use middle::infer::{mod, InferCtxt};
|
||||
use middle::infer::InferCtxt;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::DUMMY_SP;
|
||||
@ -38,12 +38,7 @@ pub fn impl_can_satisfy(infcx: &InferCtxt,
|
||||
let impl1_substs =
|
||||
util::fresh_substs_for_impl(infcx, DUMMY_SP, impl1_def_id);
|
||||
let impl1_trait_ref =
|
||||
ty::impl_trait_ref(infcx.tcx, impl1_def_id).unwrap()
|
||||
.subst(infcx.tcx, &impl1_substs);
|
||||
let impl1_trait_ref =
|
||||
infcx.replace_late_bound_regions_with_fresh_var(DUMMY_SP,
|
||||
infer::FnCall,
|
||||
&*impl1_trait_ref).0;
|
||||
(*ty::impl_trait_ref(infcx.tcx, impl1_def_id).unwrap()).subst(infcx.tcx, &impl1_substs);
|
||||
|
||||
// Determine whether `impl2` can provide an implementation for those
|
||||
// same types.
|
||||
@ -67,15 +62,15 @@ pub fn impl_is_local(tcx: &ty::ctxt,
|
||||
debug!("trait_ref={}", trait_ref.repr(tcx));
|
||||
|
||||
// If the trait is local to the crate, ok.
|
||||
if trait_ref.def_id().krate == ast::LOCAL_CRATE {
|
||||
if trait_ref.def_id.krate == ast::LOCAL_CRATE {
|
||||
debug!("trait {} is local to current crate",
|
||||
trait_ref.def_id().repr(tcx));
|
||||
trait_ref.def_id.repr(tcx));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, at least one of the input types must be local to the
|
||||
// crate.
|
||||
trait_ref.0.input_types().iter().any(|&t| ty_is_local(tcx, t))
|
||||
trait_ref.input_types().iter().any(|&t| ty_is_local(tcx, t))
|
||||
}
|
||||
|
||||
pub fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
|
@ -360,10 +360,7 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
|
||||
// For now, we just check that there are no higher-ranked
|
||||
// regions. If there are, we will call this obligation an
|
||||
// error. Eventually we should be able to support some
|
||||
// cases here, I imagine (e.g., `for<'a> &'a int : 'a`).
|
||||
//
|
||||
// TODO This is overly conservative, but good enough for
|
||||
// now.
|
||||
// cases here, I imagine (e.g., `for<'a> int : 'a`).
|
||||
if ty::count_late_bound_regions(selcx.tcx(), binder) != 0 {
|
||||
errors.push(
|
||||
FulfillmentError::new(
|
||||
|
@ -289,7 +289,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
ty::Predicate::Equate(ref p) => {
|
||||
let result = self.infcx.probe(|| {
|
||||
let result = self.infcx.probe(|_| {
|
||||
self.infcx.equality_predicate(obligation.cause.span, p)
|
||||
});
|
||||
match result {
|
||||
@ -410,13 +410,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
impl_def_id.repr(self.tcx()),
|
||||
obligation.repr(self.tcx()));
|
||||
|
||||
self.infcx.probe(|| {
|
||||
match self.match_impl(impl_def_id, obligation) {
|
||||
self.infcx.probe(|snapshot| {
|
||||
let (skol_obligation_trait_ref, skol_map) =
|
||||
self.infcx().skolemize_late_bound_regions(&*obligation.trait_ref, snapshot);
|
||||
match self.match_impl(impl_def_id, obligation, snapshot,
|
||||
&skol_map, Rc::new(skol_obligation_trait_ref)) {
|
||||
Ok(substs) => {
|
||||
let vtable_impl = self.vtable_impl(impl_def_id,
|
||||
substs,
|
||||
obligation.cause,
|
||||
obligation.recursion_depth + 1);
|
||||
obligation.recursion_depth + 1,
|
||||
skol_map,
|
||||
snapshot);
|
||||
self.winnow_selection(None, VtableImpl(vtable_impl)).may_apply()
|
||||
}
|
||||
Err(()) => {
|
||||
@ -711,8 +716,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
let matching_bounds =
|
||||
all_bounds.filter(
|
||||
|bound| self.infcx.probe(
|
||||
|| self.match_trait_refs(obligation,
|
||||
(*bound).clone())).is_ok());
|
||||
|_| self.match_where_clause(obligation, bound.clone())).is_ok());
|
||||
|
||||
let param_candidates =
|
||||
matching_bounds.map(
|
||||
@ -819,8 +823,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
{
|
||||
let all_impls = self.all_impls(obligation.trait_ref.def_id());
|
||||
for &impl_def_id in all_impls.iter() {
|
||||
self.infcx.probe(|| {
|
||||
match self.match_impl(impl_def_id, obligation) {
|
||||
self.infcx.probe(|snapshot| {
|
||||
let (skol_obligation_trait_ref, skol_map) =
|
||||
self.infcx().skolemize_late_bound_regions(&*obligation.trait_ref, snapshot);
|
||||
match self.match_impl(impl_def_id, obligation, snapshot,
|
||||
&skol_map, Rc::new(skol_obligation_trait_ref)) {
|
||||
Ok(_) => {
|
||||
candidates.vec.push(ImplCandidate(impl_def_id));
|
||||
}
|
||||
@ -848,15 +855,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
candidate: &Candidate<'tcx>)
|
||||
-> EvaluationResult<'tcx>
|
||||
{
|
||||
/*!
|
||||
* Further evaluate `candidate` to decide whether all type parameters match
|
||||
* and whether nested obligations are met. Returns true if `candidate` remains
|
||||
* viable after this further scrutiny.
|
||||
*/
|
||||
|
||||
debug!("winnow_candidate: depth={} candidate={}",
|
||||
stack.obligation.recursion_depth, candidate.repr(self.tcx()));
|
||||
let result = self.infcx.probe(|| {
|
||||
debug!("winnow_candidate: candidate={}", candidate.repr(self.tcx()));
|
||||
let result = self.infcx.probe(|_| {
|
||||
let candidate = (*candidate).clone();
|
||||
match self.confirm_candidate(stack.obligation, candidate) {
|
||||
Ok(selection) => self.winnow_selection(Some(stack), selection),
|
||||
@ -919,17 +919,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
candidate_i.repr(self.tcx()),
|
||||
candidate_j.repr(self.tcx()));
|
||||
|
||||
self.infcx.probe(|| {
|
||||
self.infcx.probe(|snapshot| {
|
||||
let (skol_obligation_trait_ref, skol_map) =
|
||||
self.infcx().skolemize_late_bound_regions(
|
||||
&*stack.obligation.trait_ref, snapshot);
|
||||
let impl_substs =
|
||||
self.rematch_impl(impl_def_id, stack.obligation);
|
||||
self.rematch_impl(impl_def_id, stack.obligation, snapshot,
|
||||
&skol_map, Rc::new(skol_obligation_trait_ref));
|
||||
let impl_trait_ref =
|
||||
ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap();
|
||||
let impl_trait_ref =
|
||||
impl_trait_ref.subst(self.tcx(), &impl_substs);
|
||||
let poly_impl_trait_ref =
|
||||
Rc::new(ty::Binder((*impl_trait_ref).clone()));
|
||||
let origin =
|
||||
infer::RelateOutputImplTypes(stack.obligation.cause.span);
|
||||
self.infcx
|
||||
.sub_poly_trait_refs(false, origin, impl_trait_ref, vt.bound.clone())
|
||||
.sub_poly_trait_refs(false, origin, poly_impl_trait_ref, vt.bound.clone())
|
||||
.is_ok()
|
||||
})
|
||||
}
|
||||
@ -1400,10 +1406,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
obligation.repr(self.tcx()),
|
||||
param.repr(self.tcx()));
|
||||
|
||||
let () = try!(self.confirm(obligation.cause,
|
||||
obligation.trait_ref.clone(),
|
||||
param.bound.clone()));
|
||||
Ok(param)
|
||||
// During evaluation, we already checked that this
|
||||
// where-clause trait-ref could be unified with the obligation
|
||||
// trait-ref. Repeat that unification now without any
|
||||
// transactional boundary; it should not fail.
|
||||
match self.confirm_poly_trait_refs(obligation.cause,
|
||||
obligation.trait_ref.clone(),
|
||||
param.bound.clone()) {
|
||||
Ok(()) => Ok(param),
|
||||
Err(_) => {
|
||||
self.tcx().sess.bug(
|
||||
format!("Where clause `{}` was applicable to `{}` but now is not",
|
||||
param.bound.repr(self.tcx()),
|
||||
obligation.repr(self.tcx())).as_slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn confirm_builtin_candidate(&mut self,
|
||||
@ -1476,23 +1493,44 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
|
||||
// First, create the substitutions by matching the impl again,
|
||||
// this time not in a probe.
|
||||
let substs = self.rematch_impl(impl_def_id, obligation);
|
||||
debug!("confirm_impl_candidate substs={}", substs);
|
||||
Ok(self.vtable_impl(impl_def_id, substs, obligation.cause, obligation.recursion_depth + 1))
|
||||
self.infcx.try(|snapshot| {
|
||||
let (skol_obligation_trait_ref, skol_map) =
|
||||
self.infcx().skolemize_late_bound_regions(&*obligation.trait_ref, snapshot);
|
||||
let substs = self.rematch_impl(impl_def_id, obligation,
|
||||
snapshot, &skol_map, Rc::new(skol_obligation_trait_ref));
|
||||
debug!("confirm_impl_candidate substs={}", substs);
|
||||
Ok(self.vtable_impl(impl_def_id, substs, obligation.cause,
|
||||
obligation.recursion_depth + 1, skol_map, snapshot))
|
||||
})
|
||||
}
|
||||
|
||||
fn vtable_impl(&mut self,
|
||||
impl_def_id: ast::DefId,
|
||||
substs: Substs<'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
recursion_depth: uint)
|
||||
recursion_depth: uint,
|
||||
skol_map: infer::SkolemizationMap,
|
||||
snapshot: &infer::CombinedSnapshot)
|
||||
-> VtableImplData<'tcx, PredicateObligation<'tcx>>
|
||||
{
|
||||
debug!("vtable_impl(impl_def_id={}, substs={}, recursion_depth={}, skol_map={})",
|
||||
impl_def_id.repr(self.tcx()),
|
||||
substs.repr(self.tcx()),
|
||||
recursion_depth,
|
||||
skol_map.repr(self.tcx()));
|
||||
|
||||
let impl_predicates =
|
||||
self.impl_predicates(cause,
|
||||
recursion_depth,
|
||||
impl_def_id,
|
||||
&substs);
|
||||
&substs,
|
||||
skol_map,
|
||||
snapshot);
|
||||
|
||||
debug!("vtable_impl: impl_def_id={} impl_predicates={}",
|
||||
impl_def_id.repr(self.tcx()),
|
||||
impl_predicates.repr(self.tcx()));
|
||||
|
||||
VtableImplData { impl_def_id: impl_def_id,
|
||||
substs: substs,
|
||||
nested: impl_predicates }
|
||||
@ -1535,10 +1573,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
substs: substs,
|
||||
}));
|
||||
|
||||
let () =
|
||||
try!(self.confirm(obligation.cause,
|
||||
obligation.trait_ref.clone(),
|
||||
trait_ref));
|
||||
try!(self.confirm_poly_trait_refs(obligation.cause,
|
||||
obligation.trait_ref.clone(),
|
||||
trait_ref));
|
||||
|
||||
Ok(self_ty)
|
||||
}
|
||||
@ -1582,9 +1619,52 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
closure_def_id.repr(self.tcx()),
|
||||
trait_ref.repr(self.tcx()));
|
||||
|
||||
self.confirm(obligation.cause,
|
||||
obligation.trait_ref.clone(),
|
||||
trait_ref)
|
||||
self.confirm_poly_trait_refs(obligation.cause,
|
||||
obligation.trait_ref.clone(),
|
||||
trait_ref)
|
||||
}
|
||||
|
||||
/// In the case of unboxed closure types and fn pointers,
|
||||
/// we currently treat the input type parameters on the trait as
|
||||
/// outputs. This means that when we have a match we have only
|
||||
/// considered the self type, so we have to go back and make sure
|
||||
/// to relate the argument types too. This is kind of wrong, but
|
||||
/// since we control the full set of impls, also not that wrong,
|
||||
/// and it DOES yield better error messages (since we don't report
|
||||
/// errors as if there is no applicable impl, but rather report
|
||||
/// errors are about mismatched argument types.
|
||||
///
|
||||
/// Here is an example. Imagine we have an unboxed closure expression
|
||||
/// and we desugared it so that the type of the expression is
|
||||
/// `Closure`, and `Closure` expects an int as argument. Then it
|
||||
/// is "as if" the compiler generated this impl:
|
||||
///
|
||||
/// impl Fn(int) for Closure { ... }
|
||||
///
|
||||
/// Now imagine our obligation is `Fn(uint) for Closure`. So far
|
||||
/// we have matched the self-type `Closure`. At this point we'll
|
||||
/// compare the `int` to `uint` and generate an error.
|
||||
///
|
||||
/// Note that this checking occurs *after* the impl has selected,
|
||||
/// because these output type parameters should not affect the
|
||||
/// selection of the impl. Therefore, if there is a mismatch, we
|
||||
/// report an error to the user.
|
||||
fn confirm_poly_trait_refs(&mut self,
|
||||
obligation_cause: ObligationCause,
|
||||
obligation_trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
|
||||
expected_trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
|
||||
-> Result<(), SelectionError<'tcx>>
|
||||
{
|
||||
let origin = infer::RelateOutputImplTypes(obligation_cause.span);
|
||||
|
||||
let obligation_trait_ref = obligation_trait_ref.clone();
|
||||
match self.infcx.sub_poly_trait_refs(false,
|
||||
origin,
|
||||
expected_trait_ref.clone(),
|
||||
obligation_trait_ref.clone()) {
|
||||
Ok(()) => Ok(()),
|
||||
Err(e) => Err(OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e))
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -1599,10 +1679,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
|
||||
fn rematch_impl(&mut self,
|
||||
impl_def_id: ast::DefId,
|
||||
obligation: &TraitObligation<'tcx>)
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
snapshot: &infer::CombinedSnapshot,
|
||||
skol_map: &infer::SkolemizationMap,
|
||||
skol_obligation_trait_ref: Rc<ty::TraitRef<'tcx>>)
|
||||
-> Substs<'tcx>
|
||||
{
|
||||
match self.match_impl(impl_def_id, obligation) {
|
||||
match self.match_impl(impl_def_id, obligation, snapshot,
|
||||
skol_map, skol_obligation_trait_ref) {
|
||||
Ok(substs) => {
|
||||
substs
|
||||
}
|
||||
@ -1618,11 +1702,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
|
||||
fn match_impl(&mut self,
|
||||
impl_def_id: ast::DefId,
|
||||
obligation: &TraitObligation<'tcx>)
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
snapshot: &infer::CombinedSnapshot,
|
||||
skol_map: &infer::SkolemizationMap,
|
||||
skol_obligation_trait_ref: Rc<ty::TraitRef<'tcx>>)
|
||||
-> Result<Substs<'tcx>, ()>
|
||||
{
|
||||
let impl_trait_ref = ty::impl_trait_ref(self.tcx(),
|
||||
impl_def_id).unwrap();
|
||||
let impl_trait_ref = ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap();
|
||||
|
||||
// Before we create the substitutions and everything, first
|
||||
// consider a "quick reject". This avoids creating more types
|
||||
@ -1638,15 +1724,42 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
let impl_trait_ref = impl_trait_ref.subst(self.tcx(),
|
||||
&impl_substs);
|
||||
|
||||
match self.match_trait_refs(obligation, impl_trait_ref) {
|
||||
Ok(()) => Ok(impl_substs),
|
||||
Err(()) => Err(())
|
||||
debug!("match_impl(impl_def_id={}, obligation={}, \
|
||||
impl_trait_ref={}, skol_obligation_trait_ref={})",
|
||||
impl_def_id.repr(self.tcx()),
|
||||
obligation.repr(self.tcx()),
|
||||
impl_trait_ref.repr(self.tcx()),
|
||||
skol_obligation_trait_ref.repr(self.tcx()));
|
||||
|
||||
let origin = infer::RelateOutputImplTypes(obligation.cause.span);
|
||||
match self.infcx.sub_trait_refs(false,
|
||||
origin,
|
||||
impl_trait_ref,
|
||||
skol_obligation_trait_ref) {
|
||||
Ok(()) => { }
|
||||
Err(e) => {
|
||||
debug!("match_impl: failed sub_trait_refs due to `{}`",
|
||||
ty::type_err_to_str(self.tcx(), &e));
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
|
||||
match self.infcx.leak_check(skol_map, snapshot) {
|
||||
Ok(()) => { }
|
||||
Err(e) => {
|
||||
debug!("match_impl: failed leak check due to `{}`",
|
||||
ty::type_err_to_str(self.tcx(), &e));
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
|
||||
debug!("match_impl: success impl_substs={}", impl_substs.repr(self.tcx()));
|
||||
Ok(impl_substs)
|
||||
}
|
||||
|
||||
fn fast_reject_trait_refs(&mut self,
|
||||
obligation: &TraitObligation,
|
||||
impl_trait_ref: &ty::PolyTraitRef)
|
||||
impl_trait_ref: &ty::TraitRef)
|
||||
-> bool
|
||||
{
|
||||
// We can avoid creating type variables and doing the full
|
||||
@ -1667,19 +1780,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
fn match_trait_refs(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
|
||||
fn match_where_clause(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
where_clause_trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
|
||||
-> Result<(),()>
|
||||
{
|
||||
debug!("match_trait_refs: obligation={} trait_ref={}",
|
||||
debug!("match_where_clause: obligation={} where_clause_trait_ref={}",
|
||||
obligation.repr(self.tcx()),
|
||||
trait_ref.repr(self.tcx()));
|
||||
where_clause_trait_ref.repr(self.tcx()));
|
||||
|
||||
let origin = infer::RelateOutputImplTypes(obligation.cause.span);
|
||||
match self.infcx.sub_poly_trait_refs(false,
|
||||
origin,
|
||||
trait_ref,
|
||||
where_clause_trait_ref,
|
||||
obligation.trait_ref.clone()) {
|
||||
Ok(()) => Ok(()),
|
||||
Err(_) => Err(()),
|
||||
@ -1754,78 +1867,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Confirmation
|
||||
//
|
||||
// The final step of selection: once we know how an obligation is
|
||||
// is resolved, we confirm that selection in order to have
|
||||
// side-effects on the typing environment. This step also unifies
|
||||
// the output type parameters from the obligation with those found
|
||||
// on the impl/bound, which may yield type errors.
|
||||
|
||||
/// Relates the output type parameters from an impl to the
|
||||
/// trait. This may lead to type errors. The confirmation step
|
||||
/// is separated from the main match procedure because these
|
||||
/// type errors do not cause us to select another impl.
|
||||
///
|
||||
/// As an example, consider matching the obligation
|
||||
/// `Iterator<char> for Elems<int>` using the following impl:
|
||||
///
|
||||
/// impl<T> Iterator<T> for Elems<T> { ... }
|
||||
///
|
||||
/// The match phase will succeed with substitution `T=int`.
|
||||
/// The confirm step will then try to unify `int` and `char`
|
||||
/// and yield an error.
|
||||
fn confirm_impl_vtable(&mut self,
|
||||
impl_def_id: ast::DefId,
|
||||
obligation_cause: ObligationCause<'tcx>,
|
||||
obligation_trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
|
||||
substs: &Substs<'tcx>)
|
||||
-> Result<(), SelectionError<'tcx>>
|
||||
{
|
||||
let impl_trait_ref = ty::impl_trait_ref(self.tcx(),
|
||||
impl_def_id).unwrap();
|
||||
let impl_trait_ref = impl_trait_ref.subst(self.tcx(),
|
||||
substs);
|
||||
self.confirm(obligation_cause, obligation_trait_ref, impl_trait_ref)
|
||||
}
|
||||
|
||||
/// After we have determined which impl applies, and with what substitutions, there is one last
|
||||
/// step. We have to go back and relate the "output" type parameters from the obligation to the
|
||||
/// types that are specified in the impl.
|
||||
///
|
||||
/// For example, imagine we have:
|
||||
///
|
||||
/// impl<T> Iterator<T> for Vec<T> { ... }
|
||||
///
|
||||
/// and our obligation is `Iterator<Foo> for Vec<int>` (note the mismatch in the obligation
|
||||
/// types). Up until this step, no error would be reported: the self type is `Vec<int>`, and
|
||||
/// that matches `Vec<T>` with the substitution `T=int`. At this stage, we could then go and
|
||||
/// check that the type parameters to the `Iterator` trait match. (In terms of the parameters,
|
||||
/// the `expected_trait_ref` here would be `Iterator<int> for Vec<int>`, and the
|
||||
/// `obligation_trait_ref` would be `Iterator<Foo> for Vec<int>`.
|
||||
///
|
||||
/// Note that this checking occurs *after* the impl has selected, because these output type
|
||||
/// parameters should not affect the selection of the impl. Therefore, if there is a mismatch,
|
||||
/// we report an error to the user.
|
||||
fn confirm(&mut self,
|
||||
obligation_cause: ObligationCause,
|
||||
obligation_trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
|
||||
expected_trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
|
||||
-> Result<(), SelectionError<'tcx>>
|
||||
{
|
||||
let origin = infer::RelateOutputImplTypes(obligation_cause.span);
|
||||
|
||||
let obligation_trait_ref = obligation_trait_ref.clone();
|
||||
match self.infcx.sub_poly_trait_refs(false,
|
||||
origin,
|
||||
expected_trait_ref.clone(),
|
||||
obligation_trait_ref.clone()) {
|
||||
Ok(()) => Ok(()),
|
||||
Err(e) => Err(OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e))
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Miscellany
|
||||
|
||||
@ -1857,11 +1898,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
cause: ObligationCause<'tcx>,
|
||||
recursion_depth: uint,
|
||||
impl_def_id: ast::DefId,
|
||||
impl_substs: &Substs<'tcx>)
|
||||
impl_substs: &Substs<'tcx>,
|
||||
skol_map: infer::SkolemizationMap,
|
||||
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 bounds = self.infcx().plug_leaks(skol_map, snapshot, &bounds);
|
||||
util::predicates_for_generics(self.tcx(), cause, recursion_depth, &bounds)
|
||||
}
|
||||
|
||||
|
@ -478,8 +478,10 @@ pub enum MethodOrigin<'tcx> {
|
||||
#[deriving(Clone, Show)]
|
||||
pub struct MethodParam<'tcx> {
|
||||
// the precise trait reference that occurs as a bound -- this may
|
||||
// be a supertrait of what the user actually typed.
|
||||
pub trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
|
||||
// be a supertrait of what the user actually typed. Note that it
|
||||
// never contains bound regions; those regions should have been
|
||||
// instantiated with fresh variables at this point.
|
||||
pub trait_ref: Rc<ty::TraitRef<'tcx>>,
|
||||
|
||||
// index of uint in the list of methods for the trait
|
||||
pub method_num: uint,
|
||||
@ -489,7 +491,7 @@ pub struct MethodParam<'tcx> {
|
||||
#[deriving(Clone, Show)]
|
||||
pub struct MethodObject<'tcx> {
|
||||
// the (super)trait containing the method to be invoked
|
||||
pub trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
|
||||
pub trait_ref: Rc<ty::TraitRef<'tcx>>,
|
||||
|
||||
// the actual base trait id of the object
|
||||
pub object_trait_id: ast::DefId,
|
||||
@ -665,7 +667,7 @@ pub struct ctxt<'tcx> {
|
||||
/// A cache for the trait_items() routine
|
||||
pub trait_items_cache: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItem<'tcx>>>>>,
|
||||
|
||||
pub impl_trait_cache: RefCell<DefIdMap<Option<Rc<ty::PolyTraitRef<'tcx>>>>>,
|
||||
pub impl_trait_cache: RefCell<DefIdMap<Option<Rc<ty::TraitRef<'tcx>>>>>,
|
||||
|
||||
pub trait_refs: RefCell<NodeMap<Rc<TraitRef<'tcx>>>>,
|
||||
pub trait_defs: RefCell<DefIdMap<Rc<TraitDef<'tcx>>>>,
|
||||
@ -1306,7 +1308,7 @@ pub enum sty<'tcx> {
|
||||
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
||||
pub struct TyTrait<'tcx> {
|
||||
// Principal trait reference.
|
||||
pub principal: PolyTraitRef<'tcx>, // would use Rc<TraitRef>, but it runs afoul of some static rules
|
||||
pub principal: PolyTraitRef<'tcx>,
|
||||
pub bounds: ExistentialBounds
|
||||
}
|
||||
|
||||
@ -1315,7 +1317,9 @@ impl<'tcx> TyTrait<'tcx> {
|
||||
/// we convert the principal trait-ref into a normal trait-ref,
|
||||
/// you must give *some* self-type. A common choice is `mk_err()`
|
||||
/// or some skolemized type.
|
||||
pub fn principal_trait_ref_with_self_ty(&self, self_ty: Ty<'tcx>) -> Rc<ty::PolyTraitRef<'tcx>> {
|
||||
pub fn principal_trait_ref_with_self_ty(&self, self_ty: Ty<'tcx>)
|
||||
-> Rc<ty::PolyTraitRef<'tcx>>
|
||||
{
|
||||
Rc::new(ty::Binder(ty::TraitRef {
|
||||
def_id: self.principal.def_id(),
|
||||
substs: self.principal.substs().with_self_ty(self_ty),
|
||||
@ -4818,7 +4822,7 @@ pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
|
||||
}
|
||||
|
||||
pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
|
||||
-> Option<Rc<PolyTraitRef<'tcx>>> {
|
||||
-> Option<Rc<TraitRef<'tcx>>> {
|
||||
memoized(&cx.impl_trait_cache, id, |id: ast::DefId| {
|
||||
if id.krate == ast::LOCAL_CRATE {
|
||||
debug!("(impl_trait_ref) searching for trait impl {}", id);
|
||||
@ -4828,9 +4832,8 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
|
||||
ast::ItemImpl(_, _, ref opt_trait, _, _) => {
|
||||
match opt_trait {
|
||||
&Some(ref t) => {
|
||||
let trait_ref =
|
||||
(*ty::node_id_to_trait_ref(cx, t.ref_id)).clone();
|
||||
Some(Rc::new(ty::Binder(trait_ref)))
|
||||
let trait_ref = ty::node_id_to_trait_ref(cx, t.ref_id);
|
||||
Some(trait_ref)
|
||||
}
|
||||
&None => None
|
||||
}
|
||||
@ -5736,7 +5739,7 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
|
||||
// Record the trait->implementation mappings, if applicable.
|
||||
let associated_traits = csearch::get_impl_trait(tcx, impl_def_id);
|
||||
for trait_ref in associated_traits.iter() {
|
||||
record_trait_implementation(tcx, trait_ref.def_id(), impl_def_id);
|
||||
record_trait_implementation(tcx, trait_ref.def_id, impl_def_id);
|
||||
}
|
||||
|
||||
// For any methods that use a default implementation, add them to
|
||||
@ -6432,26 +6435,24 @@ pub fn replace_late_bound_regions<'tcx, T, F>(
|
||||
debug!("replace_late_bound_regions({})", binder.repr(tcx));
|
||||
|
||||
let mut map = FnvHashMap::new();
|
||||
let value = {
|
||||
let mut f = ty_fold::RegionFolder::new(tcx, |region, current_depth| {
|
||||
debug!("region={}", region.repr(tcx));
|
||||
match region {
|
||||
ty::ReLateBound(debruijn, br) if debruijn.depth == current_depth => {
|
||||
* match map.entry(br) {
|
||||
Vacant(entry) => entry.set(mapf(br, debruijn)),
|
||||
Occupied(entry) => entry.into_mut(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
region
|
||||
|
||||
// Note: fold the field `0`, not the binder, so that late-bound
|
||||
// regions bound by `binder` are considered free.
|
||||
let value = ty_fold::fold_regions(tcx, &binder.0, |region, current_depth| {
|
||||
debug!("region={}", region.repr(tcx));
|
||||
match region {
|
||||
ty::ReLateBound(debruijn, br) if debruijn.depth == current_depth => {
|
||||
* match map.entry(br) {
|
||||
Vacant(entry) => entry.set(mapf(br, debruijn)),
|
||||
Occupied(entry) => entry.into_mut(),
|
||||
}
|
||||
}
|
||||
});
|
||||
_ => {
|
||||
region
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Note: fold the field `0`, not the binder, so that late-bound
|
||||
// regions bound by `binder` are considered free.
|
||||
binder.0.fold_with(&mut f)
|
||||
};
|
||||
debug!("resulting map: {} value: {}", map, value.repr(tcx));
|
||||
(value, map)
|
||||
}
|
||||
|
@ -730,14 +730,17 @@ impl<'a, 'tcx, F> TypeFolder<'tcx> for BottomUpFolder<'a, 'tcx, F> where
|
||||
/// regions (aka "lifetimes") that are bound within a type are not
|
||||
/// visited by this folder; only regions that occur free will be
|
||||
/// visited by `fld_r`.
|
||||
pub struct RegionFolder<'a, 'tcx: 'a, F> where F: FnMut(ty::Region, uint) -> ty::Region {
|
||||
|
||||
pub struct RegionFolder<'a, 'tcx: 'a> {
|
||||
tcx: &'a ty::ctxt<'tcx>,
|
||||
current_depth: uint,
|
||||
fld_r: F,
|
||||
fld_r: &'a mut (FnMut(ty::Region, uint) -> ty::Region + 'a),
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, F> RegionFolder<'a, 'tcx, F> where F: FnMut(ty::Region, uint) -> ty::Region {
|
||||
pub fn new(tcx: &'a ty::ctxt<'tcx>, fld_r: F) -> RegionFolder<'a, 'tcx, F> {
|
||||
impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
|
||||
pub fn new<F>(tcx: &'a ty::ctxt<'tcx>, fld_r: &'a mut F) -> RegionFolder<'a, 'tcx>
|
||||
where F : FnMut(ty::Region, uint) -> ty::Region
|
||||
{
|
||||
RegionFolder {
|
||||
tcx: tcx,
|
||||
current_depth: 1,
|
||||
@ -750,15 +753,21 @@ pub fn collect_regions<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> Vec<ty::Regio
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
let mut vec = Vec::new();
|
||||
{
|
||||
let mut folder = RegionFolder::new(tcx, |r, _| { vec.push(r); r });
|
||||
value.fold_with(&mut folder);
|
||||
}
|
||||
fold_regions(tcx, value, |r, _| { vec.push(r); r });
|
||||
vec
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, F> TypeFolder<'tcx> for RegionFolder<'a, 'tcx, F> where
|
||||
F: FnMut(ty::Region, uint) -> ty::Region,
|
||||
pub fn fold_regions<'tcx,T,F>(tcx: &ty::ctxt<'tcx>,
|
||||
value: &T,
|
||||
mut f: F)
|
||||
-> T
|
||||
where F : FnMut(ty::Region, uint) -> ty::Region,
|
||||
T : TypeFoldable<'tcx>,
|
||||
{
|
||||
value.fold_with(&mut RegionFolder::new(tcx, &mut f))
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx>
|
||||
{
|
||||
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.tcx }
|
||||
|
||||
@ -780,7 +789,7 @@ impl<'a, 'tcx, F> TypeFolder<'tcx> for RegionFolder<'a, 'tcx, F> where
|
||||
_ => {
|
||||
debug!("RegionFolder.fold_region({}) folding free region (current_depth={})",
|
||||
r.repr(self.tcx()), self.current_depth);
|
||||
(self.fld_r)(r, self.current_depth)
|
||||
self.fld_r.call_mut((r, self.current_depth))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -836,7 +845,7 @@ pub fn shift_regions<'tcx, T:TypeFoldable<'tcx>+Repr<'tcx>>(tcx: &ty::ctxt<'tcx>
|
||||
debug!("shift_regions(value={}, amount={})",
|
||||
value.repr(tcx), amount);
|
||||
|
||||
value.fold_with(&mut RegionFolder::new(tcx, |region, _current_depth| {
|
||||
value.fold_with(&mut RegionFolder::new(tcx, &mut |region, _current_depth| {
|
||||
shift_region(region, amount)
|
||||
}))
|
||||
}
|
||||
|
@ -941,14 +941,14 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
||||
ty::MethodTypeParam(ref mp) => {
|
||||
// method invoked on a type parameter
|
||||
let trait_item = ty::trait_item(&self.analysis.ty_cx,
|
||||
mp.trait_ref.def_id(),
|
||||
mp.trait_ref.def_id,
|
||||
mp.method_num);
|
||||
(None, Some(trait_item.def_id()))
|
||||
}
|
||||
ty::MethodTraitObject(ref mo) => {
|
||||
// method invoked on a trait instance
|
||||
let trait_item = ty::trait_item(&self.analysis.ty_cx,
|
||||
mo.trait_ref.def_id(),
|
||||
mo.trait_ref.def_id,
|
||||
mo.method_num);
|
||||
(None, Some(trait_item.def_id()))
|
||||
}
|
||||
|
@ -421,12 +421,11 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
|
||||
let impl_or_trait_item = ty::impl_or_trait_item(tcx, source_id);
|
||||
match impl_or_trait_item {
|
||||
ty::MethodTraitItem(method) => {
|
||||
let poly_trait_ref = ty::impl_trait_ref(tcx, impl_id).unwrap();
|
||||
let trait_ref = ty::erase_late_bound_regions(tcx, &*poly_trait_ref);
|
||||
let trait_ref = ty::impl_trait_ref(tcx, impl_id).unwrap();
|
||||
|
||||
// Compute the first substitution
|
||||
let first_subst =
|
||||
ty::make_substs_for_receiver_types(tcx, &trait_ref, &*method)
|
||||
ty::make_substs_for_receiver_types(tcx, &*trait_ref, &*method)
|
||||
.erase_regions();
|
||||
|
||||
// And compose them
|
||||
|
@ -133,14 +133,14 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
method_num
|
||||
}) => {
|
||||
let trait_ref =
|
||||
Rc::new(trait_ref.subst(bcx.tcx(), bcx.fcx.param_substs));
|
||||
Rc::new(ty::Binder((**trait_ref).subst(bcx.tcx(), bcx.fcx.param_substs)));
|
||||
let span = bcx.tcx().map.span(method_call.expr_id);
|
||||
debug!("method_call={} trait_ref={}",
|
||||
method_call,
|
||||
trait_ref.repr(bcx.tcx()));
|
||||
let origin = fulfill_obligation(bcx.ccx(),
|
||||
span,
|
||||
(*trait_ref).clone());
|
||||
trait_ref.clone());
|
||||
debug!("origin = {}", origin.repr(bcx.tcx()));
|
||||
trans_monomorphized_callee(bcx, method_call, trait_ref.def_id(),
|
||||
method_num, origin)
|
||||
@ -618,7 +618,7 @@ fn emit_vtable_methods<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let tcx = ccx.tcx();
|
||||
|
||||
let trt_id = match ty::impl_trait_ref(tcx, impl_id) {
|
||||
Some(t_id) => t_id.def_id(),
|
||||
Some(t_id) => t_id.def_id,
|
||||
None => ccx.sess().bug("make_impl_vtable: don't know how to \
|
||||
make a vtable for a type impl!")
|
||||
};
|
||||
|
@ -53,8 +53,7 @@ use middle::def;
|
||||
use middle::resolve_lifetime as rl;
|
||||
use middle::subst::{FnSpace, TypeSpace, AssocSpace, SelfSpace, Subst, Substs};
|
||||
use middle::subst::{VecPerParamSpace};
|
||||
use middle::ty::{mod, Ty};
|
||||
use middle::ty_fold;
|
||||
use middle::ty::{mod, RegionEscape, Ty};
|
||||
use rscope::{mod, UnelidableRscope, RegionScope, SpecificRscope,
|
||||
ShiftedRscope, BindingRscope};
|
||||
use TypeAndSubsts;
|
||||
@ -533,7 +532,8 @@ pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
|
||||
-> Rc<ty::PolyTraitRef<'tcx>>
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
{
|
||||
let trait_ref = instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty, allow_eq);
|
||||
let trait_ref =
|
||||
instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty, allow_eq);
|
||||
let trait_ref = (*trait_ref).clone();
|
||||
Rc::new(ty::Binder(trait_ref)) // Ugh.
|
||||
}
|
||||
@ -1200,10 +1200,9 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
|
||||
let (self_ty, mut implied_output_region) = match opt_self_info {
|
||||
None => (None, None),
|
||||
Some(self_info) => {
|
||||
// Shift regions in the self type by 1 to account for the binding
|
||||
// level introduced by the function itself.
|
||||
let untransformed_self_ty =
|
||||
ty_fold::shift_regions(this.tcx(), 1, &self_info.untransformed_self_ty);
|
||||
// This type comes from an impl or trait; no late-bound
|
||||
// regions should be present.
|
||||
assert!(!self_info.untransformed_self_ty.has_escaping_regions());
|
||||
|
||||
// Figure out and record the explicit self category.
|
||||
let explicit_self_category =
|
||||
@ -1214,19 +1213,19 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
|
||||
(None, None)
|
||||
}
|
||||
ty::ByValueExplicitSelfCategory => {
|
||||
(Some(untransformed_self_ty), None)
|
||||
(Some(self_info.untransformed_self_ty), None)
|
||||
}
|
||||
ty::ByReferenceExplicitSelfCategory(region, mutability) => {
|
||||
(Some(ty::mk_rptr(this.tcx(),
|
||||
region,
|
||||
ty::mt {
|
||||
ty: untransformed_self_ty,
|
||||
ty: self_info.untransformed_self_ty,
|
||||
mutbl: mutability
|
||||
})),
|
||||
Some(region))
|
||||
}
|
||||
ty::ByBoxExplicitSelfCategory => {
|
||||
(Some(ty::mk_uniq(this.tcx(), untransformed_self_ty)), None)
|
||||
(Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty)), None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -222,17 +222,19 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||
// argument type), but those cases have already
|
||||
// been ruled out when we deemed the trait to be
|
||||
// "object safe".
|
||||
let original_trait_ref =
|
||||
let original_poly_trait_ref =
|
||||
data.principal_trait_ref_with_self_ty(object_ty);
|
||||
let upcast_poly_trait_ref =
|
||||
this.upcast(original_poly_trait_ref.clone(), trait_def_id);
|
||||
let upcast_trait_ref =
|
||||
this.upcast(original_trait_ref.clone(), trait_def_id);
|
||||
debug!("original_trait_ref={} upcast_trait_ref={} target_trait={}",
|
||||
original_trait_ref.repr(this.tcx()),
|
||||
this.replace_late_bound_regions_with_fresh_var(&*upcast_poly_trait_ref);
|
||||
debug!("original_poly_trait_ref={} upcast_trait_ref={} target_trait={}",
|
||||
original_poly_trait_ref.repr(this.tcx()),
|
||||
upcast_trait_ref.repr(this.tcx()),
|
||||
trait_def_id.repr(this.tcx()));
|
||||
let substs = upcast_trait_ref.substs().clone();
|
||||
let substs = upcast_trait_ref.substs.clone();
|
||||
let origin = MethodTraitObject(MethodObject {
|
||||
trait_ref: upcast_trait_ref,
|
||||
trait_ref: Rc::new(upcast_trait_ref),
|
||||
object_trait_id: trait_def_id,
|
||||
method_num: method_num,
|
||||
real_index: real_index,
|
||||
@ -257,7 +259,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||
.subst(self.tcx(), &impl_polytype.substs);
|
||||
let origin = MethodTypeParam(MethodParam { trait_ref: impl_trait_ref.clone(),
|
||||
method_num: method_num });
|
||||
(impl_trait_ref.substs().clone(), origin)
|
||||
(impl_trait_ref.substs.clone(), origin)
|
||||
}
|
||||
|
||||
probe::TraitPick(trait_def_id, method_num) => {
|
||||
@ -273,16 +275,20 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||
self.infcx().next_ty_var());
|
||||
|
||||
let trait_ref =
|
||||
Rc::new(ty::Binder(ty::TraitRef::new(trait_def_id, substs.clone())));
|
||||
Rc::new(ty::TraitRef::new(trait_def_id, substs.clone()));
|
||||
let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
|
||||
method_num: method_num });
|
||||
(substs, origin)
|
||||
}
|
||||
|
||||
probe::WhereClausePick(ref trait_ref, method_num) => {
|
||||
let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref.clone(),
|
||||
probe::WhereClausePick(ref poly_trait_ref, method_num) => {
|
||||
// Where clauses can have bound regions in them. We need to instantiate
|
||||
// those to convert from a poly-trait-ref to a trait-ref.
|
||||
let trait_ref = self.replace_late_bound_regions_with_fresh_var(&**poly_trait_ref);
|
||||
let substs = trait_ref.substs.clone();
|
||||
let origin = MethodTypeParam(MethodParam { trait_ref: Rc::new(trait_ref),
|
||||
method_num: method_num });
|
||||
(trait_ref.substs().clone(), origin)
|
||||
(substs, origin)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -379,25 +385,9 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||
all_substs: subst::Substs<'tcx>)
|
||||
-> InstantiatedMethodSig<'tcx>
|
||||
{
|
||||
// If this method comes from an impl (as opposed to a trait),
|
||||
// it may have late-bound regions from the impl that appear in
|
||||
// the substitutions, method signature, and
|
||||
// bounds. Instantiate those at this point. (If it comes from
|
||||
// a trait, this step has no effect, as there are no
|
||||
// late-bound regions to instantiate.)
|
||||
//
|
||||
// The binder level here corresponds to the impl.
|
||||
let (all_substs, (method_sig, method_generics)) =
|
||||
self.replace_late_bound_regions_with_fresh_var(
|
||||
&ty::Binder((all_substs,
|
||||
(pick.method_ty.fty.sig.clone(),
|
||||
pick.method_ty.generics.clone()))));
|
||||
|
||||
debug!("late-bound lifetimes from impl instantiated, \
|
||||
all_substs={} method_sig={} method_generics={}",
|
||||
all_substs.repr(self.tcx()),
|
||||
method_sig.repr(self.tcx()),
|
||||
method_generics.repr(self.tcx()));
|
||||
debug!("instantiate_method_sig(pick={}, all_substs={})",
|
||||
pick.repr(self.tcx()),
|
||||
all_substs.repr(self.tcx()));
|
||||
|
||||
// Instantiate the bounds on the method with the
|
||||
// type/early-bound-regions substitutions performed. The only
|
||||
@ -427,8 +417,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||
all_substs.clone()
|
||||
}
|
||||
};
|
||||
let method_bounds =
|
||||
method_generics.to_bounds(self.tcx(), &method_bounds_substs);
|
||||
let method_bounds = pick.method_ty.generics.to_bounds(self.tcx(), &method_bounds_substs);
|
||||
|
||||
debug!("method_bounds after subst = {}",
|
||||
method_bounds.repr(self.tcx()));
|
||||
@ -436,7 +425,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||
// Substitute the type/early-bound-regions into the method
|
||||
// signature. In addition, the method signature may bind
|
||||
// late-bound regions, so instantiate those.
|
||||
let method_sig = method_sig.subst(self.tcx(), &all_substs);
|
||||
let method_sig = pick.method_ty.fty.sig.subst(self.tcx(), &all_substs);
|
||||
let method_sig = self.replace_late_bound_regions_with_fresh_var(&method_sig);
|
||||
|
||||
debug!("late-bound lifetimes from method instantiated, method_sig={}",
|
||||
|
@ -166,12 +166,13 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
|
||||
|
||||
// Construct a trait-reference `self_ty : Trait<input_tys>`
|
||||
let substs = subst::Substs::new_trait(input_types, Vec::new(), assoc_types, self_ty);
|
||||
let trait_ref = Rc::new(ty::Binder(ty::TraitRef::new(trait_def_id, substs)));
|
||||
let trait_ref = Rc::new(ty::TraitRef::new(trait_def_id, substs));
|
||||
|
||||
// Construct an obligation
|
||||
let poly_trait_ref = Rc::new(ty::Binder((*trait_ref).clone()));
|
||||
let obligation = traits::Obligation::misc(span,
|
||||
fcx.body_id,
|
||||
ty::Predicate::Trait(trait_ref.clone()));
|
||||
poly_trait_ref.as_predicate());
|
||||
|
||||
// Now we want to know if this can be matched
|
||||
let mut selcx = traits::SelectionContext::new(fcx.infcx(),
|
||||
@ -194,11 +195,8 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
|
||||
|
||||
// Substitute the trait parameters into the method type and
|
||||
// instantiate late-bound regions to get the actual method type.
|
||||
//
|
||||
// Note that as the method comes from a trait, it can only have
|
||||
// late-bound regions from the fn itself, not the impl.
|
||||
let ref bare_fn_ty = method_ty.fty;
|
||||
let fn_sig = bare_fn_ty.sig.subst(tcx, trait_ref.substs());
|
||||
let fn_sig = bare_fn_ty.sig.subst(tcx, &trait_ref.substs);
|
||||
let fn_sig = fcx.infcx().replace_late_bound_regions_with_fresh_var(span,
|
||||
infer::FnCall,
|
||||
&fn_sig).0;
|
||||
@ -221,7 +219,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a 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 = method_ty.generics.to_bounds(fcx.tcx(), trait_ref.substs());
|
||||
let method_bounds = method_ty.generics.to_bounds(fcx.tcx(), &trait_ref.substs);
|
||||
assert!(!method_bounds.has_escaping_regions());
|
||||
fcx.add_obligations_for_parameters(
|
||||
traits::ObligationCause::misc(span, fcx.body_id),
|
||||
@ -293,7 +291,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
|
||||
origin: MethodTypeParam(MethodParam{trait_ref: trait_ref.clone(),
|
||||
method_num: method_num}),
|
||||
ty: fty,
|
||||
substs: trait_ref.substs().clone()
|
||||
substs: trait_ref.substs.clone()
|
||||
};
|
||||
|
||||
debug!("callee = {}", callee.repr(fcx.tcx()));
|
||||
@ -379,7 +377,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
None => format!(""),
|
||||
Some(trait_ref) => format!(" of the trait `{}`",
|
||||
ty::item_path_str(fcx.tcx(),
|
||||
trait_ref.def_id())),
|
||||
trait_ref.def_id)),
|
||||
};
|
||||
|
||||
span_note!(fcx.sess(), method_span,
|
||||
|
@ -19,7 +19,6 @@ use middle::subst;
|
||||
use middle::subst::Subst;
|
||||
use middle::traits;
|
||||
use middle::ty::{mod, Ty};
|
||||
use middle::ty::{MethodObject};
|
||||
use middle::ty_fold::TypeFoldable;
|
||||
use middle::infer;
|
||||
use middle::infer::InferCtxt;
|
||||
@ -58,8 +57,8 @@ struct Candidate<'tcx> {
|
||||
|
||||
enum CandidateKind<'tcx> {
|
||||
InherentImplCandidate(/* Impl */ ast::DefId, subst::Substs<'tcx>),
|
||||
ObjectCandidate(MethodObject<'tcx>),
|
||||
ExtensionImplCandidate(/* Impl */ ast::DefId, Rc<ty::PolyTraitRef<'tcx>>,
|
||||
ObjectCandidate(/* Trait */ ast::DefId, /* method_num */ uint, /* real_index */ uint),
|
||||
ExtensionImplCandidate(/* Impl */ ast::DefId, Rc<ty::TraitRef<'tcx>>,
|
||||
subst::Substs<'tcx>, MethodIndex),
|
||||
UnboxedClosureCandidate(/* Trait */ ast::DefId, MethodIndex),
|
||||
WhereClauseCandidate(Rc<ty::PolyTraitRef<'tcx>>, MethodIndex),
|
||||
@ -149,7 +148,7 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
// this creates one big transaction so that all type variables etc
|
||||
// that we create during the probe process are removed later
|
||||
let mut dummy = Some((steps, opt_simplified_steps)); // FIXME(#18101) need once closures
|
||||
fcx.infcx().probe(|| {
|
||||
fcx.infcx().probe(|_| {
|
||||
let (steps, opt_simplified_steps) = dummy.take().unwrap();
|
||||
let mut probe_cx = ProbeContext::new(fcx, span, method_name, steps, opt_simplified_steps);
|
||||
probe_cx.assemble_inherent_candidates();
|
||||
@ -313,12 +312,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
||||
this.inherent_candidates.push(Candidate {
|
||||
xform_self_ty: xform_self_ty,
|
||||
method_ty: m,
|
||||
kind: ObjectCandidate(MethodObject {
|
||||
trait_ref: new_trait_ref,
|
||||
object_trait_id: trait_ref.def_id(),
|
||||
method_num: method_num,
|
||||
real_index: vtable_index
|
||||
})
|
||||
kind: ObjectCandidate(new_trait_ref.def_id(), method_num, vtable_index)
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -502,7 +496,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
||||
|
||||
// Determine the receiver type that the method itself expects.
|
||||
let xform_self_ty =
|
||||
self.xform_self_ty(&method, impl_trait_ref.substs());
|
||||
self.xform_self_ty(&method, &impl_trait_ref.substs);
|
||||
|
||||
debug!("xform_self_ty={}", xform_self_ty.repr(self.tcx()));
|
||||
|
||||
@ -748,7 +742,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
||||
self_ty.repr(self.tcx()),
|
||||
probe.repr(self.tcx()));
|
||||
|
||||
self.infcx().probe(|| {
|
||||
self.infcx().probe(|_| {
|
||||
// First check that the self type can be related.
|
||||
match self.make_sub_ty(self_ty, probe.xform_self_ty) {
|
||||
Ok(()) => { }
|
||||
@ -1033,8 +1027,8 @@ impl<'tcx> Candidate<'tcx> {
|
||||
InherentImplCandidate(def_id, _) => {
|
||||
InherentImplPick(def_id)
|
||||
}
|
||||
ObjectCandidate(ref data) => {
|
||||
ObjectPick(data.trait_ref.def_id(), data.method_num, data.real_index)
|
||||
ObjectCandidate(def_id, method_num, real_index) => {
|
||||
ObjectPick(def_id, method_num, real_index)
|
||||
}
|
||||
ExtensionImplCandidate(def_id, _, _, index) => {
|
||||
ExtensionImplPick(def_id, index)
|
||||
@ -1059,7 +1053,7 @@ impl<'tcx> Candidate<'tcx> {
|
||||
fn to_source(&self) -> CandidateSource {
|
||||
match self.kind {
|
||||
InherentImplCandidate(def_id, _) => ImplSource(def_id),
|
||||
ObjectCandidate(ref obj) => TraitSource(obj.trait_ref.def_id()),
|
||||
ObjectCandidate(def_id, _, _) => TraitSource(def_id),
|
||||
ExtensionImplCandidate(def_id, _, _, _) => ImplSource(def_id),
|
||||
UnboxedClosureCandidate(trait_def_id, _) => TraitSource(trait_def_id),
|
||||
WhereClauseCandidate(ref trait_ref, _) => TraitSource(trait_ref.def_id()),
|
||||
@ -1075,7 +1069,9 @@ impl<'tcx> Candidate<'tcx> {
|
||||
UnboxedClosureCandidate(trait_def_id, method_num) => {
|
||||
Some((trait_def_id, method_num))
|
||||
}
|
||||
ExtensionImplCandidate(_, ref trait_ref, _, method_num) |
|
||||
ExtensionImplCandidate(_, ref trait_ref, _, method_num) => {
|
||||
Some((trait_ref.def_id, method_num))
|
||||
}
|
||||
WhereClauseCandidate(ref trait_ref, method_num) => {
|
||||
Some((trait_ref.def_id(), method_num))
|
||||
}
|
||||
@ -1096,8 +1092,8 @@ impl<'tcx> Repr<'tcx> for CandidateKind<'tcx> {
|
||||
match *self {
|
||||
InherentImplCandidate(ref a, ref b) =>
|
||||
format!("InherentImplCandidate({},{})", a.repr(tcx), b.repr(tcx)),
|
||||
ObjectCandidate(ref a) =>
|
||||
format!("ObjectCandidate({})", a.repr(tcx)),
|
||||
ObjectCandidate(a, b, c) =>
|
||||
format!("ObjectCandidate({},{},{})", a.repr(tcx), b, c),
|
||||
ExtensionImplCandidate(ref a, ref b, ref c, ref d) =>
|
||||
format!("ExtensionImplCandidate({},{},{},{})", a.repr(tcx), b.repr(tcx),
|
||||
c.repr(tcx), d),
|
||||
|
@ -719,12 +719,7 @@ fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
|
||||
|
||||
let fty = ty::node_id_to_type(ccx.tcx, method.id);
|
||||
debug!("fty (raw): {}", fty.repr(ccx.tcx));
|
||||
|
||||
let body_id = method.pe_body().id;
|
||||
let fty = liberate_late_bound_regions(
|
||||
ccx.tcx, CodeExtent::from_node_id(body_id), &ty::Binder(fty));
|
||||
debug!("fty (liberated): {}", fty.repr(ccx.tcx));
|
||||
debug!("check_method_body: fty={}", fty.repr(ccx.tcx));
|
||||
|
||||
check_bare_fn(ccx,
|
||||
&*method.pe_fn_decl(),
|
||||
@ -736,11 +731,11 @@ fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
|
||||
fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
impl_span: Span,
|
||||
impl_trait_ref: &ty::PolyTraitRef<'tcx>,
|
||||
impl_trait_ref: &ty::TraitRef<'tcx>,
|
||||
impl_items: &[ast::ImplItem]) {
|
||||
// Locate trait methods
|
||||
let tcx = ccx.tcx;
|
||||
let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id());
|
||||
let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
|
||||
|
||||
// Check existing impl methods to see if they are both present in trait
|
||||
// and compatible with trait signature
|
||||
@ -834,8 +829,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
|
||||
// Check for missing items from trait
|
||||
let provided_methods = ty::provided_trait_methods(tcx,
|
||||
impl_trait_ref.def_id());
|
||||
let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
|
||||
let mut missing_methods = Vec::new();
|
||||
for trait_item in trait_items.iter() {
|
||||
match *trait_item {
|
||||
@ -894,37 +888,16 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
impl_m_span: Span,
|
||||
impl_m_body_id: ast::NodeId,
|
||||
trait_m: &ty::Method<'tcx>,
|
||||
impl_trait_ref: &ty::PolyTraitRef<'tcx>) {
|
||||
impl_trait_ref: &ty::TraitRef<'tcx>) {
|
||||
debug!("compare_impl_method(impl_trait_ref={})",
|
||||
impl_trait_ref.repr(tcx));
|
||||
|
||||
let impl_m_body_scope = CodeExtent::from_node_id(impl_m_body_id);
|
||||
|
||||
// The impl's trait ref may bind late-bound regions from the impl.
|
||||
// Liberate them and assign them the scope of the method body.
|
||||
//
|
||||
// An example would be:
|
||||
//
|
||||
// impl<'a> Foo<&'a T> for &'a U { ... }
|
||||
//
|
||||
// Here, the region parameter `'a` is late-bound, so the
|
||||
// trait reference associated with the impl will be
|
||||
//
|
||||
// for<'a> Foo<&'a T>
|
||||
//
|
||||
// liberating will convert this into:
|
||||
//
|
||||
// Foo<&'A T>
|
||||
//
|
||||
// where `'A` is the `ReFree` version of `'a`.
|
||||
let impl_trait_ref = liberate_late_bound_regions(tcx, impl_m_body_scope, impl_trait_ref);
|
||||
|
||||
debug!("impl_trait_ref (liberated) = {}",
|
||||
impl_trait_ref.repr(tcx));
|
||||
|
||||
let infcx = infer::new_infer_ctxt(tcx);
|
||||
|
||||
let trait_to_impl_substs = impl_trait_ref.substs;
|
||||
let trait_to_impl_substs = &impl_trait_ref.substs;
|
||||
|
||||
// Try to give more informative error messages about self typing
|
||||
// mismatches. Note that any mismatch will also be detected
|
||||
@ -1060,7 +1033,6 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
if !check_region_bounds_on_impl_method(tcx,
|
||||
impl_m_span,
|
||||
impl_m,
|
||||
impl_m_body_scope,
|
||||
&trait_m.generics,
|
||||
&impl_m.generics,
|
||||
&trait_to_skol_substs,
|
||||
@ -1099,11 +1071,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
.map(|trait_param_def| &trait_param_def.bounds);
|
||||
let impl_bounds =
|
||||
impl_m.generics.types.get_slice(subst::FnSpace).iter()
|
||||
.map(|impl_param_def|
|
||||
liberate_late_bound_regions(
|
||||
tcx,
|
||||
impl_m_body_scope,
|
||||
&ty::Binder(ty::Binder(impl_param_def.bounds.clone()))).0);
|
||||
.map(|impl_param_def| &impl_param_def.bounds);
|
||||
for (i, (trait_param_bounds, impl_param_bounds)) in
|
||||
trait_bounds.zip(impl_bounds).enumerate()
|
||||
{
|
||||
@ -1164,12 +1132,9 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
// Compute skolemized form of impl and trait method tys. Note
|
||||
// that we must liberate the late-bound regions from the impl.
|
||||
// Compute skolemized form of impl and trait method tys.
|
||||
let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
|
||||
let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
|
||||
let impl_fty = liberate_late_bound_regions(
|
||||
tcx, impl_m_body_scope, &ty::Binder(impl_fty));
|
||||
let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
|
||||
let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
|
||||
|
||||
@ -1231,7 +1196,6 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
fn check_region_bounds_on_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
span: Span,
|
||||
impl_m: &ty::Method<'tcx>,
|
||||
impl_m_body_scope: CodeExtent,
|
||||
trait_generics: &ty::Generics<'tcx>,
|
||||
impl_generics: &ty::Generics<'tcx>,
|
||||
trait_to_skol_substs: &Substs<'tcx>,
|
||||
@ -1281,16 +1245,6 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
let impl_bounds =
|
||||
impl_param.bounds.subst(tcx, impl_to_skol_substs);
|
||||
|
||||
// The bounds may reference late-bound regions from the
|
||||
// impl declaration. In that case, we want to replace
|
||||
// those with the liberated variety so as to match the
|
||||
// versions appearing in the `trait_to_skol_substs`.
|
||||
// There are two-levels of binder to be aware of: the
|
||||
// impl, and the method.
|
||||
let impl_bounds =
|
||||
ty::liberate_late_bound_regions(
|
||||
tcx, impl_m_body_scope, &ty::Binder(ty::Binder(impl_bounds))).0;
|
||||
|
||||
debug!("check_region_bounds_on_impl_method: \
|
||||
trait_param={} \
|
||||
impl_param={} \
|
||||
|
@ -166,11 +166,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
|
||||
|
||||
// Find the impl self type as seen from the "inside" --
|
||||
// that is, with all type parameters converted from bound
|
||||
// to free, and any late-bound regions on the impl
|
||||
// liberated.
|
||||
// to free.
|
||||
let self_ty = ty::node_id_to_type(fcx.tcx(), item.id);
|
||||
let self_ty = self_ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs);
|
||||
let self_ty = liberate_late_bound_regions(fcx.tcx(), item_scope, &ty::Binder(self_ty));
|
||||
|
||||
bounds_checker.check_traits_in_ty(self_ty);
|
||||
|
||||
@ -181,7 +179,6 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
|
||||
Some(t) => { t }
|
||||
};
|
||||
let trait_ref = (*trait_ref).subst(fcx.tcx(), &fcx.inh.param_env.free_substs);
|
||||
let trait_ref = liberate_late_bound_regions(fcx.tcx(), item_scope, &trait_ref);
|
||||
|
||||
// There are special rules that apply to drop.
|
||||
if
|
||||
|
@ -18,8 +18,8 @@
|
||||
|
||||
use metadata::csearch::{each_impl, get_impl_trait};
|
||||
use metadata::csearch;
|
||||
use middle::region;
|
||||
use middle::subst::{mod, Subst};
|
||||
use middle::ty::RegionEscape;
|
||||
use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId};
|
||||
use middle::ty::{ParameterEnvironment, TypeTraitItemId, lookup_item_type};
|
||||
use middle::ty::{Ty, ty_bool, ty_char, ty_closure, ty_enum, ty_err};
|
||||
@ -339,7 +339,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
||||
|
||||
// Record all the trait items.
|
||||
for trait_ref in associated_traits.iter() {
|
||||
self.add_trait_impl(trait_ref.def_id(), impl_def_id);
|
||||
self.add_trait_impl(trait_ref.def_id, impl_def_id);
|
||||
}
|
||||
|
||||
// For any methods that use a default implementation, add them to
|
||||
@ -459,6 +459,9 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
||||
let trait_impls = trait_impls.borrow().clone();
|
||||
|
||||
for &impl_did in trait_impls.iter() {
|
||||
debug!("check_implementations_of_copy: impl_did={}",
|
||||
impl_did.repr(tcx));
|
||||
|
||||
if impl_did.krate != ast::LOCAL_CRATE {
|
||||
debug!("check_implementations_of_copy(): impl not in this \
|
||||
crate");
|
||||
@ -466,20 +469,15 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
||||
}
|
||||
|
||||
let self_type = self.get_self_type_for_implementation(impl_did);
|
||||
debug!("check_implementations_of_copy: self_type={} (bound)",
|
||||
self_type.repr(tcx));
|
||||
|
||||
let span = tcx.map.span(impl_did.node);
|
||||
let param_env = ParameterEnvironment::for_item(tcx,
|
||||
impl_did.node);
|
||||
let param_env = ParameterEnvironment::for_item(tcx, impl_did.node);
|
||||
let self_type = self_type.ty.subst(tcx, ¶m_env.free_substs);
|
||||
assert!(!self_type.has_escaping_regions());
|
||||
|
||||
// the self-type may have late-bound regions bound in the
|
||||
// impl; liberate them.
|
||||
let item_scope = region::CodeExtent::from_node_id(impl_did.node);
|
||||
let self_type =
|
||||
ty::liberate_late_bound_regions(tcx,
|
||||
item_scope,
|
||||
&ty::Binder(self_type));
|
||||
|
||||
debug!("can_type_implement_copy(self_type={})",
|
||||
debug!("check_implementations_of_copy: self_type={} (free)",
|
||||
self_type.repr(tcx));
|
||||
|
||||
match ty::can_type_implement_copy(tcx, self_type, ¶m_env) {
|
||||
|
@ -45,7 +45,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
Some(trait_ref) => {
|
||||
let trait_def = ty::lookup_trait_def(self.tcx, trait_ref.def_id());
|
||||
let trait_def = ty::lookup_trait_def(self.tcx, trait_ref.def_id);
|
||||
match (trait_def.unsafety, unsafety) {
|
||||
(ast::Unsafety::Normal, ast::Unsafety::Unsafe) => {
|
||||
self.tcx.sess.span_err(
|
||||
|
@ -43,8 +43,8 @@ use middle::resolve_lifetime;
|
||||
use middle::subst;
|
||||
use middle::subst::{Substs};
|
||||
use middle::ty::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
|
||||
use middle::ty::{mod, Ty, Polytype};
|
||||
use middle::ty_fold::{mod, TypeFolder};
|
||||
use middle::ty::{mod, RegionEscape, Ty, Polytype};
|
||||
use middle::ty_fold::{mod, TypeFolder, TypeFoldable};
|
||||
use middle::infer;
|
||||
use rscope::*;
|
||||
use {CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
|
||||
@ -226,7 +226,7 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
|
||||
ast::StructVariantKind(ref struct_def) => {
|
||||
let pty = Polytype {
|
||||
generics: ty_generics_for_type(
|
||||
generics: ty_generics_for_type_or_impl(
|
||||
ccx,
|
||||
generics,
|
||||
DontCreateTypeParametersForAssociatedTypes),
|
||||
@ -239,7 +239,7 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
};
|
||||
|
||||
let pty = Polytype {
|
||||
generics: ty_generics_for_type(
|
||||
generics: ty_generics_for_type_or_impl(
|
||||
ccx,
|
||||
generics,
|
||||
DontCreateTypeParametersForAssociatedTypes),
|
||||
@ -1050,7 +1050,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
ref selfty,
|
||||
ref impl_items) => {
|
||||
// Create generics from the generics specified in the impl head.
|
||||
let ty_generics = ty_generics_for_impl(
|
||||
let ty_generics = ty_generics_for_type_or_impl(
|
||||
ccx,
|
||||
generics,
|
||||
CreateTypeParametersForAssociatedTypes);
|
||||
@ -1482,7 +1482,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
|
||||
let pty = {
|
||||
let ty = ccx.to_ty(&ExplicitRscope, &**t);
|
||||
Polytype {
|
||||
generics: ty_generics_for_type(
|
||||
generics: ty_generics_for_type_or_impl(
|
||||
ccx,
|
||||
generics,
|
||||
DontCreateTypeParametersForAssociatedTypes),
|
||||
@ -1495,7 +1495,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
|
||||
}
|
||||
ast::ItemEnum(_, ref generics) => {
|
||||
// Create a new generic polytype.
|
||||
let ty_generics = ty_generics_for_type(
|
||||
let ty_generics = ty_generics_for_type_or_impl(
|
||||
ccx,
|
||||
generics,
|
||||
DontCreateTypeParametersForAssociatedTypes);
|
||||
@ -1513,7 +1513,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
|
||||
tcx.sess.span_bug(it.span, "invoked ty_of_item on trait");
|
||||
}
|
||||
ast::ItemStruct(_, ref generics) => {
|
||||
let ty_generics = ty_generics_for_type(
|
||||
let ty_generics = ty_generics_for_type_or_impl(
|
||||
ccx,
|
||||
generics,
|
||||
DontCreateTypeParametersForAssociatedTypes);
|
||||
@ -1580,11 +1580,11 @@ fn ty_of_trait_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_generics_for_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
generics: &ast::Generics,
|
||||
create_type_parameters_for_associated_types:
|
||||
CreateTypeParametersForAssociatedTypesFlag)
|
||||
-> ty::Generics<'tcx> {
|
||||
fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
generics: &ast::Generics,
|
||||
create_type_parameters_for_associated_types:
|
||||
CreateTypeParametersForAssociatedTypesFlag)
|
||||
-> ty::Generics<'tcx> {
|
||||
ty_generics(ccx,
|
||||
subst::TypeSpace,
|
||||
generics.lifetimes.as_slice(),
|
||||
@ -1664,24 +1664,6 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
generics
|
||||
}
|
||||
|
||||
fn ty_generics_for_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
generics: &ast::Generics,
|
||||
create_type_parameters_for_associated_types:
|
||||
CreateTypeParametersForAssociatedTypesFlag)
|
||||
-> ty::Generics<'tcx>
|
||||
{
|
||||
let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
|
||||
debug!("ty_generics_for_impl: early_lifetimes={}",
|
||||
early_lifetimes);
|
||||
ty_generics(ccx,
|
||||
subst::TypeSpace,
|
||||
early_lifetimes.as_slice(),
|
||||
generics.ty_params.as_slice(),
|
||||
ty::Generics::empty(),
|
||||
&generics.where_clause,
|
||||
create_type_parameters_for_associated_types)
|
||||
}
|
||||
|
||||
fn ty_generics_for_fn_or_method<'tcx,AC>(
|
||||
this: &AC,
|
||||
generics: &ast::Generics,
|
||||
@ -2186,8 +2168,12 @@ pub fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
subst::Substs::new(types, regions)
|
||||
}
|
||||
|
||||
/// Verifies that the explicit self type of a method matches the impl or
|
||||
/// trait.
|
||||
/// Verifies that the explicit self type of a method matches the impl
|
||||
/// or trait. This is a bit weird but basically because right now we
|
||||
/// don't handle the general case, but instead map it to one of
|
||||
/// several pre-defined options using various heuristics, this method
|
||||
/// comes back to check after the fact that explicit type the user
|
||||
/// wrote actually matches what the pre-defined option said.
|
||||
fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
|
||||
crate_context: &CrateCtxt<'a, 'tcx>,
|
||||
rs: &RS,
|
||||
@ -2209,19 +2195,21 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
|
||||
// contain late-bound regions from the method, but not the
|
||||
// trait (since traits only have early-bound region
|
||||
// parameters).
|
||||
assert!(!ty::type_escapes_depth(required_type, 1));
|
||||
assert!(!base_type.has_regions_escaping_depth(1));
|
||||
let required_type_free =
|
||||
ty::liberate_late_bound_regions(
|
||||
crate_context.tcx, body_scope, &ty::Binder(required_type));
|
||||
|
||||
// The "base type" comes from the impl. It may have late-bound
|
||||
// regions from the impl or the method.
|
||||
let base_type_free =
|
||||
ty::liberate_late_bound_regions( // liberate impl regions:
|
||||
liberate_early_bound_regions(
|
||||
crate_context.tcx, body_scope,
|
||||
&ty::liberate_late_bound_regions( // liberate method regions:
|
||||
crate_context.tcx, body_scope,
|
||||
&ty::Binder(ty::Binder(base_type))));
|
||||
&ty::liberate_late_bound_regions(
|
||||
crate_context.tcx, body_scope, &ty::Binder(required_type)));
|
||||
|
||||
// The "base type" comes from the impl. It too may have late-bound
|
||||
// regions from the method.
|
||||
assert!(!base_type.has_regions_escaping_depth(1));
|
||||
let base_type_free =
|
||||
liberate_early_bound_regions(
|
||||
crate_context.tcx, body_scope,
|
||||
&ty::liberate_late_bound_regions(
|
||||
crate_context.tcx, body_scope, &ty::Binder(base_type)));
|
||||
|
||||
debug!("required_type={} required_type_free={} \
|
||||
base_type={} base_type_free={}",
|
||||
@ -2242,4 +2230,30 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
|
||||
}));
|
||||
infcx.resolve_regions_and_report_errors(body_id);
|
||||
}
|
||||
|
||||
fn liberate_early_bound_regions<'tcx,T>(
|
||||
tcx: &ty::ctxt<'tcx>,
|
||||
scope: region::CodeExtent,
|
||||
value: &T)
|
||||
-> T
|
||||
where T : TypeFoldable<'tcx> + Repr<'tcx>
|
||||
{
|
||||
/*!
|
||||
* Convert early-bound regions into free regions; normally this is done by
|
||||
* applying the `free_substs` from the `ParameterEnvironment`, but this particular
|
||||
* method-self-type check is kind of hacky and done very early in the process,
|
||||
* before we really have a `ParameterEnvironment` to check.
|
||||
*/
|
||||
|
||||
ty_fold::fold_regions(tcx, value, |region, _| {
|
||||
match region {
|
||||
ty::ReEarlyBound(id, _, _, name) => {
|
||||
let def_id = local_def(id);
|
||||
ty::ReFree(ty::FreeRegion { scope: scope,
|
||||
bound_region: ty::BrNamed(def_id, name) })
|
||||
}
|
||||
_ => region
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -281,7 +281,7 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
|
||||
// If this is an impl for a #[doc(hidden)] trait, be sure to not inline it.
|
||||
match associated_trait {
|
||||
Some(ref t) => {
|
||||
let trait_attrs = load_attrs(cx, tcx, t.def_id());
|
||||
let trait_attrs = load_attrs(cx, tcx, t.def_id);
|
||||
if trait_attrs.iter().any(|a| is_doc_hidden(a)) {
|
||||
return None
|
||||
}
|
||||
|
40
src/test/compile-fail/hrtb-conflate-regions.rs
Normal file
40
src/test/compile-fail/hrtb-conflate-regions.rs
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2014 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 what an impl with only one bound region `'a` cannot be used to
|
||||
// satisfy a constraint whre there are two bound regions.
|
||||
|
||||
trait Foo<X> {
|
||||
fn foo(&self, x: X) { }
|
||||
}
|
||||
|
||||
fn want_foo2<T>()
|
||||
where T : for<'a,'b> Foo<(&'a int, &'b int)>
|
||||
{
|
||||
}
|
||||
|
||||
fn want_foo1<T>()
|
||||
where T : for<'z> Foo<(&'z int, &'z int)>
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Expressed as a where clause
|
||||
|
||||
struct SomeStruct;
|
||||
|
||||
impl<'a> Foo<(&'a int, &'a int)> for SomeStruct
|
||||
{
|
||||
}
|
||||
|
||||
fn a() { want_foo1::<SomeStruct>(); } // OK -- foo wants just one region
|
||||
fn b() { want_foo2::<SomeStruct>(); } //~ ERROR not implemented
|
||||
|
||||
fn main() { }
|
37
src/test/compile-fail/hrtb-just-for-static.rs
Normal file
37
src/test/compile-fail/hrtb-just-for-static.rs
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2014 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 a case where you have an impl of `Foo<X>` for all `X` that
|
||||
// is being applied to `for<'a> Foo<&'a mut X>`. Issue #19730.
|
||||
|
||||
trait Foo<X> {
|
||||
fn foo(&self, x: X) { }
|
||||
}
|
||||
|
||||
fn want_hrtb<T>()
|
||||
where T : for<'a> Foo<&'a int>
|
||||
{
|
||||
}
|
||||
|
||||
// AnyInt implements Foo<&'a int> for any 'a, so it is a match.
|
||||
struct AnyInt;
|
||||
impl<'a> Foo<&'a int> for AnyInt { }
|
||||
fn give_any() {
|
||||
want_hrtb::<AnyInt>()
|
||||
}
|
||||
|
||||
// StaticInt only implements Foo<&'a int> for 'a, so it is an error.
|
||||
struct StaticInt;
|
||||
impl Foo<&'static int> for StaticInt { }
|
||||
fn give_static() {
|
||||
want_hrtb::<StaticInt>() //~ ERROR `for<'a> Foo<&'a int>` is not implemented
|
||||
}
|
||||
|
||||
fn main() { }
|
66
src/test/compile-fail/hrtb-perfect-forwarding.rs
Normal file
66
src/test/compile-fail/hrtb-perfect-forwarding.rs
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright 2014 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 a case where you have an impl of `Foo<X>` for all `X` that
|
||||
// is being applied to `for<'a> Foo<&'a mut X>`. Issue #19730.
|
||||
|
||||
trait Foo<X> {
|
||||
fn foo(&mut self, x: X) { }
|
||||
}
|
||||
|
||||
trait Bar<X> {
|
||||
fn bar(&mut self, x: X) { }
|
||||
}
|
||||
|
||||
impl<'a,X,F> Foo<X> for &'a mut F
|
||||
where F : Foo<X> + Bar<X>
|
||||
{
|
||||
}
|
||||
|
||||
impl<'a,X,F> Bar<X> for &'a mut F
|
||||
where F : Bar<X>
|
||||
{
|
||||
}
|
||||
|
||||
fn no_hrtb<'b,T>(mut t: T)
|
||||
where T : Bar<&'b int>
|
||||
{
|
||||
// OK -- `T : Bar<&'b int>`, and thus the impl above ensures that
|
||||
// `&mut T : Bar<&'b int>`.
|
||||
no_hrtb(&mut t);
|
||||
}
|
||||
|
||||
fn bar_hrtb<T>(mut t: T)
|
||||
where T : for<'b> Bar<&'b int>
|
||||
{
|
||||
// OK -- `T : for<'b> Bar<&'b int>`, and thus the impl above
|
||||
// ensures that `&mut T : for<'b> Bar<&'b int>`. This is an
|
||||
// example of a "perfect forwarding" impl.
|
||||
bar_hrtb(&mut t);
|
||||
}
|
||||
|
||||
fn foo_hrtb_bar_not<'b,T>(mut t: T)
|
||||
where T : for<'a> Foo<&'a int> + Bar<&'b int>
|
||||
{
|
||||
// Not OK -- The forwarding impl for `Foo` requires that `Bar` also
|
||||
// be implemented. Thus to satisfy `&mut T : for<'a> Foo<&'a
|
||||
// int>`, we require `T : for<'a> Bar<&'a int>`, but the where
|
||||
// clause only specifies `T : Bar<&'b int>`.
|
||||
foo_hrtb_bar_not(&mut t); //~ ERROR `for<'a> Bar<&'a int>` is not implemented for the type `T`
|
||||
}
|
||||
|
||||
fn foo_hrtb_bar_hrtb<T>(mut t: T)
|
||||
where T : for<'a> Foo<&'a int> + for<'b> Bar<&'b int>
|
||||
{
|
||||
// OK -- now we have `T : for<'b> Bar&'b int>`.
|
||||
foo_hrtb_bar_hrtb(&mut t);
|
||||
}
|
||||
|
||||
fn main() { }
|
59
src/test/compile-fail/hrtb-type-outlives.rs
Normal file
59
src/test/compile-fail/hrtb-type-outlives.rs
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2014 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 what happens when a HR obligation is applie to an impl with
|
||||
// "outlives" bounds. Currently we're pretty conservative here; this
|
||||
// will probably improve in time.
|
||||
|
||||
trait Foo<X> {
|
||||
fn foo(&self, x: X) { }
|
||||
}
|
||||
|
||||
fn want_foo<T>()
|
||||
where T : for<'a> Foo<&'a int>
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Expressed as a where clause
|
||||
|
||||
struct SomeStruct<X> {
|
||||
x: X
|
||||
}
|
||||
|
||||
impl<'a,X> Foo<&'a int> for SomeStruct<X>
|
||||
where X : 'a
|
||||
{
|
||||
}
|
||||
|
||||
fn one() {
|
||||
// In fact there is no good reason for this to be an error, but
|
||||
// whatever, I'm mostly concerned it doesn't ICE right now:
|
||||
want_foo::<SomeStruct<uint>>();
|
||||
//~^ ERROR requirement `for<'a> uint : 'a` is not satisfied
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Expressed as shorthand
|
||||
|
||||
struct AnotherStruct<X> {
|
||||
x: X
|
||||
}
|
||||
|
||||
impl<'a,X:'a> Foo<&'a int> for AnotherStruct<X>
|
||||
{
|
||||
}
|
||||
|
||||
fn two() {
|
||||
want_foo::<AnotherStruct<uint>>();
|
||||
//~^ ERROR requirement `for<'a> uint : 'a` is not satisfied
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -11,5 +11,4 @@
|
||||
fn main() {
|
||||
let _x = "test" as &::std::any::Any;
|
||||
//~^ ERROR the trait `core::kinds::Sized` is not implemented for the type `str`
|
||||
//~^^ ERROR the trait `core::kinds::Sized` is not implemented for the type `str`
|
||||
}
|
||||
|
@ -21,10 +21,15 @@ impl<T:Copy> Foo for T {
|
||||
|
||||
fn take_param<T:Foo>(foo: &T) { }
|
||||
|
||||
fn main() {
|
||||
fn a() {
|
||||
let x = box 3i;
|
||||
take_param(&x); //~ ERROR `core::kinds::Copy` is not implemented
|
||||
}
|
||||
|
||||
fn b() {
|
||||
let x = box 3i;
|
||||
let y = &x;
|
||||
let z = &x as &Foo; //~ ERROR `core::kinds::Copy` is not implemented
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -20,9 +20,16 @@ fn call_it<F:Fn(&int)->int>(_: &F, _: int) -> int { 0 }
|
||||
fn call_it_mut<F:FnMut(&int)->int>(_: &mut F, _: int) -> int { 0 }
|
||||
fn call_it_once<F:FnOnce(&int)->int>(_: F, _: int) -> int { 0 }
|
||||
|
||||
fn main() {
|
||||
fn a() {
|
||||
let x = call_it(&square, 22); //~ ERROR not implemented
|
||||
}
|
||||
|
||||
fn b() {
|
||||
let y = call_it_mut(&mut square, 22); //~ ERROR not implemented
|
||||
}
|
||||
|
||||
fn c() {
|
||||
let z = call_it_once(square, 22); //~ ERROR not implemented
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -20,9 +20,17 @@ fn call_it<F:Fn(&int)->int>(_: &F, _: int) -> int { 0 }
|
||||
fn call_it_mut<F:FnMut(&int)->int>(_: &mut F, _: int) -> int { 0 }
|
||||
fn call_it_once<F:FnOnce(&int)->int>(_: F, _: int) -> int { 0 }
|
||||
|
||||
fn main() {
|
||||
fn a() {
|
||||
let x = call_it(&square, 22); //~ ERROR not implemented
|
||||
}
|
||||
|
||||
fn b() {
|
||||
let y = call_it_mut(&mut square, 22); //~ ERROR not implemented
|
||||
}
|
||||
|
||||
fn c() {
|
||||
let z = call_it_once(square, 22); //~ ERROR not implemented
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
||||
|
@ -21,9 +21,16 @@ fn call_it<F:Fn(&int)->int>(_: &F, _: int) -> int { 0 }
|
||||
fn call_it_mut<F:FnMut(&int)->int>(_: &mut F, _: int) -> int { 0 }
|
||||
fn call_it_once<F:FnOnce(&int)->int>(_: F, _: int) -> int { 0 }
|
||||
|
||||
fn main() {
|
||||
fn a() {
|
||||
let x = call_it(&square, 22); //~ ERROR not implemented
|
||||
}
|
||||
|
||||
fn b() {
|
||||
let y = call_it_mut(&mut square, 22); //~ ERROR not implemented
|
||||
}
|
||||
|
||||
fn c() {
|
||||
let z = call_it_once(square, 22); //~ ERROR not implemented
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
Loading…
x
Reference in New Issue
Block a user