use crate::dep_graph::{DepKind, DepNodeIndex};
use crate::hir::def_id::DefId;
-use crate::infer::{InferCtxt, InferOk, TypeFreshener};
+use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener};
use crate::middle::lang_items;
use crate::mir::interpret::GlobalId;
use crate::ty::fast_reject;
use crate::ty::relate::TypeRelation;
-use crate::ty::subst::{Subst, Substs};
+use crate::ty::subst::{Subst, SubstsRef};
use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
use crate::hir;
_ => return,
}
- let result = self.infcx.probe(|_| {
- self.match_projection_obligation_against_definition_bounds(obligation)
+ let result = self.infcx.probe(|snapshot| {
+ self.match_projection_obligation_against_definition_bounds(
+ obligation,
+ snapshot,
+ )
});
if result {
fn match_projection_obligation_against_definition_bounds(
&mut self,
obligation: &TraitObligation<'tcx>,
+ snapshot: &CombinedSnapshot<'_, 'tcx>,
) -> bool {
let poly_trait_predicate = self.infcx()
.resolve_type_vars_if_possible(&obligation.predicate);
- let (skol_trait_predicate, _) = self.infcx()
+ let (placeholder_trait_predicate, placeholder_map) = self.infcx()
.replace_bound_vars_with_placeholders(&poly_trait_predicate);
debug!(
"match_projection_obligation_against_definition_bounds: \
- skol_trait_predicate={:?}",
- skol_trait_predicate,
+ placeholder_trait_predicate={:?}",
+ placeholder_trait_predicate,
);
- let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty {
+ let (def_id, substs) = match placeholder_trait_predicate.trait_ref.self_ty().sty {
ty::Projection(ref data) => (data.trait_ref(self.tcx()).def_id, data.substs),
ty::Opaque(def_id, substs) => (def_id, substs),
_ => {
obligation.cause.span,
"match_projection_obligation_against_definition_bounds() called \
but self-ty is not a projection: {:?}",
- skol_trait_predicate.trait_ref.self_ty()
+ placeholder_trait_predicate.trait_ref.self_ty()
);
}
};
self.match_projection(
obligation,
bound.clone(),
- skol_trait_predicate.trait_ref.clone(),
+ placeholder_trait_predicate.trait_ref.clone(),
+ &placeholder_map,
+ snapshot,
)
})
});
let result = self.match_projection(
obligation,
bound,
- skol_trait_predicate.trait_ref.clone(),
+ placeholder_trait_predicate.trait_ref.clone(),
+ &placeholder_map,
+ snapshot,
);
assert!(result);
&mut self,
obligation: &TraitObligation<'tcx>,
trait_bound: ty::PolyTraitRef<'tcx>,
- skol_trait_ref: ty::TraitRef<'tcx>,
+ placeholder_trait_ref: ty::TraitRef<'tcx>,
+ placeholder_map: &PlaceholderMap<'tcx>,
+ snapshot: &CombinedSnapshot<'_, 'tcx>,
) -> bool {
- debug_assert!(!skol_trait_ref.has_escaping_bound_vars());
+ debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars());
self.infcx
.at(&obligation.cause, obligation.param_env)
- .sup(ty::Binder::dummy(skol_trait_ref), trait_bound)
+ .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
.is_ok()
+ &&
+ self.infcx.leak_check(false, placeholder_map, snapshot).is_ok()
}
/// Given an obligation like `<SomeTrait for T>`, search the obligations that the caller
if let ty::FnSig {
unsafety: hir::Unsafety::Normal,
abi: Abi::Rust,
- variadic: false,
+ c_variadic: false,
..
} = self_ty.fn_sig(self.tcx()).skip_binder()
{
obligation.predicate.def_id(),
obligation.predicate.skip_binder().trait_ref.self_ty(),
|impl_def_id| {
- self.infcx.probe(|_| {
- if let Ok(_substs) = self.match_impl(impl_def_id, obligation)
+ self.infcx.probe(|snapshot| {
+ if let Ok(_substs) = self.match_impl(impl_def_id, obligation, snapshot)
{
candidates.vec.push(ImplCandidate(impl_def_id));
}
}
fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) {
- self.infcx.in_snapshot(|_| {
+ self.infcx.in_snapshot(|snapshot| {
let result =
- self.match_projection_obligation_against_definition_bounds(obligation);
+ self.match_projection_obligation_against_definition_bounds(
+ obligation,
+ snapshot,
+ );
assert!(result);
})
}
// First, create the substitutions by matching the impl again,
// this time not in a probe.
- self.infcx.in_snapshot(|_| {
- let substs = self.rematch_impl(impl_def_id, obligation);
+ self.infcx.in_snapshot(|snapshot| {
+ let substs = self.rematch_impl(impl_def_id, obligation, snapshot);
debug!("confirm_impl_candidate: substs={:?}", substs);
let cause = obligation.derived_cause(ImplDerivedObligation);
self.vtable_impl(
fn vtable_impl(
&mut self,
impl_def_id: DefId,
- mut substs: Normalized<'tcx, &'tcx Substs<'tcx>>,
+ mut substs: Normalized<'tcx, SubstsRef<'tcx>>,
cause: ObligationCause<'tcx>,
recursion_depth: usize,
param_env: ty::ParamEnv<'tcx>,
tcx.mk_existential_predicates(iter)
});
let source_trait = tcx.mk_dynamic(existential_predicates, r_b);
+
+ // Require that the traits involved in this upcast are **equal**;
+ // only the **lifetime bound** is changed.
+ //
+ // FIXME: This condition is arguably too strong -- it
+ // would suffice for the source trait to be a
+ // *subtype* of the target trait. In particular
+ // changing from something like `for<'a, 'b> Foo<'a,
+ // 'b>` to `for<'a> Foo<'a, 'a>` should be
+ // permitted. And, indeed, in the in commit
+ // 904a0bde93f0348f69914ee90b1f8b6e4e0d7cbc, this
+ // condition was loosened. However, when the leak check was added
+ // back, using subtype here actually guies the coercion code in
+ // such a way that it accepts `old-lub-glb-object.rs`. This is probably
+ // a good thing, but I've modified this to `.eq` because I want
+ // to continue rejecting that test (as we have done for quite some time)
+ // before we are firmly comfortable with what our behavior
+ // should be there. -nikomatsakis
let InferOk { obligations, .. } = self.infcx
.at(&obligation.cause, obligation.param_env)
- .sup(target, source_trait)
+ .eq(target, source_trait) // FIXME -- see below
.map_err(|_| Unimplemented)?;
nested.extend(obligations);
&mut self,
impl_def_id: DefId,
obligation: &TraitObligation<'tcx>,
- ) -> Normalized<'tcx, &'tcx Substs<'tcx>> {
- match self.match_impl(impl_def_id, obligation) {
+ snapshot: &CombinedSnapshot<'_, 'tcx>,
+ ) -> Normalized<'tcx, SubstsRef<'tcx>> {
+ match self.match_impl(impl_def_id, obligation, snapshot) {
Ok(substs) => substs,
Err(()) => {
bug!(
&mut self,
impl_def_id: DefId,
obligation: &TraitObligation<'tcx>,
- ) -> Result<Normalized<'tcx, &'tcx Substs<'tcx>>, ()> {
+ snapshot: &CombinedSnapshot<'_, 'tcx>,
+ ) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
// Before we create the substitutions and everything, first
return Err(());
}
- let (skol_obligation, _) = self.infcx()
+ let (skol_obligation, placeholder_map) = self.infcx()
.replace_bound_vars_with_placeholders(&obligation.predicate);
let skol_obligation_trait_ref = skol_obligation.trait_ref;
.map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?;
nested_obligations.extend(obligations);
+ if let Err(e) = self.infcx.leak_check(false, &placeholder_map, snapshot) {
+ debug!("match_impl: failed leak check due to `{}`", e);
+ return Err(());
+ }
+
debug!("match_impl: success impl_substs={:?}", impl_substs);
Ok(Normalized {
value: impl_substs,
recursion_depth: usize,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId, // of impl or trait
- substs: &Substs<'tcx>, // for impl or trait
+ substs: SubstsRef<'tcx>, // for impl or trait
) -> Vec<PredicateObligation<'tcx>> {
debug!("impl_or_trait_obligations(def_id={:?})", def_id);
let tcx = self.tcx();