Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove leftover mentions of skol and int from the compiler #73055

Merged
merged 3 commits into from
Jun 20, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions src/librustc_infer/infer/higher_ranked/mod.rs
Original file line number Diff line number Diff line change
@@ -63,14 +63,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
/// placeholder region. This is the first step of checking subtyping
/// when higher-ranked things are involved.
///
/// **Important:** you must call this function from within a snapshot.
/// Moreover, before committing the snapshot, you must eventually call
/// either `plug_leaks` or `pop_placeholders` to remove the placeholder
/// regions. If you rollback the snapshot (or are using a probe), then
/// the pop occurs as part of the rollback, so an explicit call is not
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matthewjasper I removed the outdated note here, even if the new one doesn't completely explain what needs to be done, I would still like to land this as is now.

/// needed (but is also permitted).
///
/// For more information about how placeholders and HRTBs work, see
/// **Important:** You have to be careful to not leak these placeholders,
/// for more information about how placeholders and HRTBs work, see
/// the [rustc dev guide].
///
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
2 changes: 1 addition & 1 deletion src/librustc_infer/infer/region_constraints/leak_check.rs
Original file line number Diff line number Diff line change
@@ -128,7 +128,7 @@ impl<'tcx> TaintSet<'tcx> {
verifys[i].origin.span(),
"we never add verifications while doing higher-ranked things",
),
&Purged | &AddCombination(..) | &AddVar(..) => {}
&AddCombination(..) | &AddVar(..) => {}
}
}
}
67 changes: 0 additions & 67 deletions src/librustc_infer/infer/region_constraints/mod.rs
Original file line number Diff line number Diff line change
@@ -289,14 +289,6 @@ pub(crate) enum UndoLog<'tcx> {

/// We added a GLB/LUB "combination variable".
AddCombination(CombineMapType, TwoRegions<'tcx>),

/// During skolemization, we sometimes purge entries from the undo
/// log in a kind of minisnapshot (unlike other snapshots, this
/// purging actually takes place *on success*). In that case, we
/// replace the corresponding entry with `Noop` so as to avoid the
/// need to do a bunch of swapping. (We can't use `swap_remove` as
/// the order of the vector is important.)
Purged,
}

#[derive(Copy, Clone, PartialEq)]
@@ -357,9 +349,6 @@ impl<'tcx> RegionConstraintStorage<'tcx> {

fn rollback_undo_entry(&mut self, undo_entry: UndoLog<'tcx>) {
match undo_entry {
Purged => {
// nothing to do here
}
AddVar(vid) => {
self.var_infos.pop().unwrap();
assert_eq!(self.var_infos.len(), vid.index() as usize);
@@ -488,62 +477,6 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
self.var_infos[vid].origin
}

/// Removes all the edges to/from the placeholder regions that are
/// in `skols`. This is used after a higher-ranked operation
/// completes to remove all trace of the placeholder regions
/// created in that time.
pub fn pop_placeholders(&mut self, placeholders: &FxHashSet<ty::Region<'tcx>>) {
debug!("pop_placeholders(placeholders={:?})", placeholders);

assert!(UndoLogs::<super::UndoLog<'_>>::in_snapshot(&self.undo_log));

let constraints_to_kill: Vec<usize> = self
.undo_log
.iter()
.enumerate()
.rev()
.filter(|&(_, undo_entry)| match undo_entry {
super::UndoLog::RegionConstraintCollector(undo_entry) => {
kill_constraint(placeholders, undo_entry)
}
_ => false,
})
.map(|(index, _)| index)
.collect();

for index in constraints_to_kill {
let undo_entry = match &mut self.undo_log[index] {
super::UndoLog::RegionConstraintCollector(undo_entry) => {
mem::replace(undo_entry, Purged)
}
_ => unreachable!(),
};
self.rollback_undo_entry(undo_entry);
}

return;

fn kill_constraint<'tcx>(
placeholders: &FxHashSet<ty::Region<'tcx>>,
undo_entry: &UndoLog<'tcx>,
) -> bool {
match undo_entry {
&AddConstraint(Constraint::VarSubVar(..)) => false,
&AddConstraint(Constraint::RegSubVar(a, _)) => placeholders.contains(&a),
&AddConstraint(Constraint::VarSubReg(_, b)) => placeholders.contains(&b),
&AddConstraint(Constraint::RegSubReg(a, b)) => {
placeholders.contains(&a) || placeholders.contains(&b)
}
&AddGiven(..) => false,
&AddVerify(_) => false,
&AddCombination(_, ref two_regions) => {
placeholders.contains(&two_regions.a) || placeholders.contains(&two_regions.b)
}
&AddVar(..) | &Purged => false,
}
}
}

fn add_constraint(&mut self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) {
// cannot add constraints once regions are resolved
debug!("RegionConstraintCollector: add_constraint({:?})", constraint);
4 changes: 0 additions & 4 deletions src/librustc_infer/infer/undo_log.rs
Original file line number Diff line number Diff line change
@@ -198,10 +198,6 @@ impl<'tcx> InferCtxtUndoLogs<'tcx> {
assert!(self.logs.len() >= snapshot.undo_len);
assert!(self.num_open_snapshots > 0);
}

pub(crate) fn iter(&self) -> std::slice::Iter<'_, UndoLog<'tcx>> {
self.logs.iter()
}
}

impl<'tcx> std::ops::Index<usize> for InferCtxtUndoLogs<'tcx> {
4 changes: 2 additions & 2 deletions src/librustc_infer/traits/mod.rs
Original file line number Diff line number Diff line change
@@ -29,10 +29,10 @@ crate use self::util::elaborate_predicates;

pub use rustc_middle::traits::*;

/// An `Obligation` represents some trait reference (e.g., `int: Eq`) for
/// An `Obligation` represents some trait reference (e.g., `i32: Eq`) for
/// which the "impl_source" must be found. The process of finding a "impl_source" is
/// called "resolving" the `Obligation`. This process consists of
/// either identifying an `impl` (e.g., `impl Eq for int`) that
/// either identifying an `impl` (e.g., `impl Eq for i32`) that
/// satisfies the obligation, or else finding a bound that is in
/// scope. The eventual result is usually a `Selection` (defined below).
#[derive(Clone, PartialEq, Eq, Hash)]
4 changes: 2 additions & 2 deletions src/librustc_infer/traits/util.rs
Original file line number Diff line number Diff line change
@@ -63,11 +63,11 @@ impl PredicateSet<'tcx> {
fn insert(&mut self, pred: ty::Predicate<'tcx>) -> bool {
// We have to be careful here because we want
//
// for<'a> Foo<&'a int>
// for<'a> Foo<&'a i32>
//
// and
//
// for<'b> Foo<&'b int>
// for<'b> Foo<&'b i32>
//
// to be considered equivalent. So normalize all late-bound
// regions before we throw things into the underlying set.
28 changes: 15 additions & 13 deletions src/librustc_middle/traits/mod.rs
Original file line number Diff line number Diff line change
@@ -393,23 +393,25 @@ pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
/// ```
/// impl<T:Clone> Clone<T> for Option<T> { ... } // Impl_1
/// impl<T:Clone> Clone<T> for Box<T> { ... } // Impl_2
/// impl Clone for int { ... } // Impl_3
/// impl Clone for i32 { ... } // Impl_3
///
/// fn foo<T:Clone>(concrete: Option<Box<int>>,
/// param: T,
/// mixed: Option<T>) {
/// fn foo<T: Clone>(concrete: Option<Box<i32>>, param: T, mixed: Option<T>) {
/// // Case A: Vtable points at a specific impl. Only possible when
/// // type is concretely known. If the impl itself has bounded
/// // type parameters, Vtable will carry resolutions for those as well:
/// concrete.clone(); // Vtable(Impl_1, [Vtable(Impl_2, [Vtable(Impl_3)])])
///
/// // Case A: ImplSource points at a specific impl. Only possible when
/// // type is concretely known. If the impl itself has bounded
/// // type parameters, ImplSource will carry resolutions for those as well:
/// concrete.clone(); // ImplSource(Impl_1, [ImplSource(Impl_2, [ImplSource(Impl_3)])])
/// // Case A: ImplSource points at a specific impl. Only possible when
/// // type is concretely known. If the impl itself has bounded
/// // type parameters, ImplSource will carry resolutions for those as well:
/// concrete.clone(); // ImplSource(Impl_1, [ImplSource(Impl_2, [ImplSource(Impl_3)])])
///
/// // Case B: ImplSource must be provided by caller. This applies when
/// // type is a type parameter.
/// param.clone(); // ImplSourceParam
/// // Case B: ImplSource must be provided by caller. This applies when
/// // type is a type parameter.
/// param.clone(); // ImplSourceParam
///
/// // Case C: A mix of cases A and B.
/// mixed.clone(); // ImplSource(Impl_1, [ImplSourceParam])
/// // Case C: A mix of cases A and B.
/// mixed.clone(); // ImplSource(Impl_1, [ImplSourceParam])
/// }
/// ```
///
12 changes: 6 additions & 6 deletions src/librustc_middle/ty/subst.rs
Original file line number Diff line number Diff line change
@@ -599,12 +599,12 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
///
/// ```
/// type Func<A> = fn(A);
/// type MetaFunc = for<'a> fn(Func<&'a int>)
/// type MetaFunc = for<'a> fn(Func<&'a i32>)
/// ```
///
/// The type `MetaFunc`, when fully expanded, will be
///
/// for<'a> fn(fn(&'a int))
/// for<'a> fn(fn(&'a i32))
/// ^~ ^~ ^~~
/// | | |
/// | | DebruijnIndex of 2
@@ -613,26 +613,26 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
/// Here the `'a` lifetime is bound in the outer function, but appears as an argument of the
/// inner one. Therefore, that appearance will have a DebruijnIndex of 2, because we must skip
/// over the inner binder (remember that we count De Bruijn indices from 1). However, in the
/// definition of `MetaFunc`, the binder is not visible, so the type `&'a int` will have a
/// definition of `MetaFunc`, the binder is not visible, so the type `&'a i32` will have a
/// De Bruijn index of 1. It's only during the substitution that we can see we must increase the
/// depth by 1 to account for the binder that we passed through.
///
/// As a second example, consider this twist:
///
/// ```
/// type FuncTuple<A> = (A,fn(A));
/// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a int>)
/// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a i32>)
/// ```
///
/// Here the final type will be:
///
/// for<'a> fn((&'a int, fn(&'a int)))
/// for<'a> fn((&'a i32, fn(&'a i32)))
/// ^~~ ^~~
/// | |
/// DebruijnIndex of 1 |
/// DebruijnIndex of 2
///
/// As indicated in the diagram, here the same type `&'a int` is substituted once, but in the
/// As indicated in the diagram, here the same type `&'a i32` is substituted once, but in the
/// first case we do not increase the De Bruijn index and in the second case we do. The reason
/// is that only in the second case have we passed through a fn binder.
fn shift_vars_through_binders<T: TypeFoldable<'tcx>>(&self, val: T) -> T {
6 changes: 3 additions & 3 deletions src/librustc_middle/ty/walk.rs
Original file line number Diff line number Diff line change
@@ -22,13 +22,13 @@ impl<'tcx> TypeWalker<'tcx> {
/// Skips the subtree corresponding to the last type
/// returned by `next()`.
///
/// Example: Imagine you are walking `Foo<Bar<int>, usize>`.
/// Example: Imagine you are walking `Foo<Bar<i32>, usize>`.
///
/// ```
/// let mut iter: TypeWalker = ...;
/// iter.next(); // yields Foo
/// iter.next(); // yields Bar<int>
/// iter.skip_current_subtree(); // skips int
/// iter.next(); // yields Bar<i32>
/// iter.skip_current_subtree(); // skips i32
/// iter.next(); // yields usize
/// ```
pub fn skip_current_subtree(&mut self) {
2 changes: 1 addition & 1 deletion src/librustc_trait_selection/traits/project.rs
Original file line number Diff line number Diff line change
@@ -361,7 +361,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
// handle normalization within binders because
// otherwise we wind up a need to normalize when doing
// trait matching (since you can have a trait
// obligation like `for<'a> T::B : Fn(&'a int)`), but
// obligation like `for<'a> T::B: Fn(&'a i32)`), but
// we can't normalize with bound regions in scope. So
// far now we just ignore binders but only normalize
// if all bound regions are gone (and then we still
2 changes: 1 addition & 1 deletion src/librustc_trait_selection/traits/query/normalize.rs
Original file line number Diff line number Diff line change
@@ -145,7 +145,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
// handle normalization within binders because
// otherwise we wind up a need to normalize when doing
// trait matching (since you can have a trait
// obligation like `for<'a> T::B : Fn(&'a int)`), but
// obligation like `for<'a> T::B: Fn(&'a i32)`), but
// we can't normalize with bound regions in scope. So
// far now we just ignore binders but only normalize
// if all bound regions are gone (and then we still
8 changes: 4 additions & 4 deletions src/librustc_trait_selection/traits/select/confirmation.rs
Original file line number Diff line number Diff line change
@@ -553,14 +553,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
///
/// Here is an example. Imagine we have a closure expression
/// and we desugared it so that the type of the expression is
/// `Closure`, and `Closure` expects an int as argument. Then it
/// `Closure`, and `Closure` expects `i32` as argument. Then it
/// is "as if" the compiler generated this impl:
///
/// impl Fn(int) for Closure { ... }
/// impl Fn(i32) for Closure { ... }
///
/// Now imagine our obligation is `Fn(usize) for Closure`. So far
/// Now imagine our obligation is `Closure: Fn(usize)`. So far
/// we have matched the self type `Closure`. At this point we'll
/// compare the `int` to `usize` and generate an error.
/// compare the `i32` to `usize` and generate an error.
///
/// Note that this checking occurs *after* the impl has selected,
/// because these output type parameters should not affect the
31 changes: 15 additions & 16 deletions src/librustc_trait_selection/traits/select/mod.rs
Original file line number Diff line number Diff line change
@@ -1754,38 +1754,37 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> Vec<PredicateObligation<'tcx>> {
// Because the types were potentially derived from
// higher-ranked obligations they may reference late-bound
// regions. For example, `for<'a> Foo<&'a int> : Copy` would
// yield a type like `for<'a> &'a int`. In general, we
// regions. For example, `for<'a> Foo<&'a i32> : Copy` would
// yield a type like `for<'a> &'a i32`. In general, we
// maintain the invariant that we never manipulate bound
// regions, so we have to process these bound regions somehow.
//
// The strategy is to:
//
// 1. Instantiate those regions to placeholder regions (e.g.,
// `for<'a> &'a int` becomes `&0 int`.
// 2. Produce something like `&'0 int : Copy`
// 3. Re-bind the regions back to `for<'a> &'a int : Copy`
// `for<'a> &'a i32` becomes `&0 i32`.
// 2. Produce something like `&'0 i32 : Copy`
// 3. Re-bind the regions back to `for<'a> &'a i32 : Copy`

types
.skip_binder()
.skip_binder() // binder moved -\
.iter()
.flat_map(|ty| {
// binder moved -\
let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/

self.infcx.commit_unconditionally(|_| {
let (skol_ty, _) = self.infcx.replace_bound_vars_with_placeholders(&ty);
let (placeholder_ty, _) = self.infcx.replace_bound_vars_with_placeholders(&ty);
let Normalized { value: normalized_ty, mut obligations } =
ensure_sufficient_stack(|| {
project::normalize_with_depth(
self,
param_env,
cause.clone(),
recursion_depth,
&skol_ty,
&placeholder_ty,
)
});
let skol_obligation = predicate_for_trait_def(
let placeholder_obligation = predicate_for_trait_def(
self.tcx(),
param_env,
cause.clone(),
@@ -1794,7 +1793,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
normalized_ty,
&[],
);
obligations.push(skol_obligation);
obligations.push(placeholder_obligation);
obligations
})
})
@@ -1844,9 +1843,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return Err(());
}

let (skol_obligation, placeholder_map) =
let (placeholder_obligation, placeholder_map) =
self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate);
let skol_obligation_trait_ref = skol_obligation.trait_ref;
let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;

let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);

@@ -1865,14 +1864,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

debug!(
"match_impl(impl_def_id={:?}, obligation={:?}, \
impl_trait_ref={:?}, skol_obligation_trait_ref={:?})",
impl_def_id, obligation, impl_trait_ref, skol_obligation_trait_ref
impl_trait_ref={:?}, placeholder_obligation_trait_ref={:?})",
impl_def_id, obligation, impl_trait_ref, placeholder_obligation_trait_ref
);

let InferOk { obligations, .. } = self
.infcx
.at(&obligation.cause, obligation.param_env)
.eq(skol_obligation_trait_ref, impl_trait_ref)
.eq(placeholder_obligation_trait_ref, impl_trait_ref)
.map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?;
nested_obligations.extend(obligations);

2 changes: 1 addition & 1 deletion src/librustc_trait_selection/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
@@ -130,7 +130,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,

// We determine whether there's a subset relationship by:
//
// - skolemizing impl1,
// - replacing bound vars with placeholders in impl1,
// - assuming the where clauses for impl1,
// - instantiating impl2 with fresh inference variables,
// - unifying,
4 changes: 2 additions & 2 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
@@ -1394,13 +1394,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// That is, consider this case:
//
// ```
// trait SubTrait: SuperTrait<int> { }
// trait SubTrait: SuperTrait<i32> { }
// trait SuperTrait<A> { type T; }
//
// ... B: SubTrait<T = foo> ...
// ```
//
// We want to produce `<B as SuperTrait<int>>::T == foo`.
// We want to produce `<B as SuperTrait<i32>>::T == foo`.

// Find any late-bound regions declared in `ty` that are not
// declared in the trait-ref. These are not well-formed.
32 changes: 16 additions & 16 deletions src/librustc_typeck/check/compare_method.rs
Original file line number Diff line number Diff line change
@@ -91,14 +91,14 @@ fn compare_predicate_entailment<'tcx>(

// This code is best explained by example. Consider a trait:
//
// trait Trait<'t,T> {
// fn method<'a,M>(t: &'t T, m: &'a M) -> Self;
// trait Trait<'t, T> {
// fn method<'a, M>(t: &'t T, m: &'a M) -> Self;
// }
//
// And an impl:
//
// impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
// fn method<'b,N>(t: &'j &'i U, m: &'b N) -> Foo;
// fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo;
// }
//
// We wish to decide if those two method types are compatible.
@@ -116,9 +116,9 @@ fn compare_predicate_entailment<'tcx>(
// regions (Note: but only early-bound regions, i.e., those
// declared on the impl or used in type parameter bounds).
//
// impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
// impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 }
//
// Now we can apply skol_substs to the type of the impl method
// Now we can apply placeholder_substs to the type of the impl method
// to yield a new function type in terms of our fresh, placeholder
// types:
//
@@ -127,11 +127,11 @@ fn compare_predicate_entailment<'tcx>(
// We now want to extract and substitute the type of the *trait*
// method and compare it. To do so, we must create a compound
// substitution by combining trait_to_impl_substs and
// impl_to_skol_substs, and also adding a mapping for the method
// impl_to_placeholder_substs, and also adding a mapping for the method
// type parameters. We extend the mapping to also include
// the method parameters.
//
// trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
// trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 }
//
// Applying this to the trait method type yields:
//
@@ -145,20 +145,20 @@ fn compare_predicate_entailment<'tcx>(
// satisfied by the implementation's method.
//
// We do this by creating a parameter environment which contains a
// substitution corresponding to impl_to_skol_substs. We then build
// trait_to_skol_substs and use it to convert the predicates contained
// substitution corresponding to impl_to_placeholder_substs. We then build
// trait_to_placeholder_substs and use it to convert the predicates contained
// in the trait_m.generics to the placeholder form.
//
// Finally we register each of these predicates as an obligation in
// a fresh FulfillmentCtxt, and invoke select_all_or_error.

// Create mapping from impl to placeholder.
let impl_to_skol_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);
let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);

// Create mapping from trait to placeholder.
let trait_to_skol_substs =
impl_to_skol_substs.rebase_onto(tcx, impl_m.container.id(), trait_to_impl_substs);
debug!("compare_impl_method: trait_to_skol_substs={:?}", trait_to_skol_substs);
let trait_to_placeholder_substs =
impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container.id(), trait_to_impl_substs);
debug!("compare_impl_method: trait_to_placeholder_substs={:?}", trait_to_placeholder_substs);

let impl_m_generics = tcx.generics_of(impl_m.def_id);
let trait_m_generics = tcx.generics_of(trait_m.def_id);
@@ -194,7 +194,7 @@ fn compare_predicate_entailment<'tcx>(
// if all constraints hold.
hybrid_preds
.predicates
.extend(trait_m_predicates.instantiate_own(tcx, trait_to_skol_substs).predicates);
.extend(trait_m_predicates.instantiate_own(tcx, trait_to_placeholder_substs).predicates);

// Construct trait parameter environment and then shift it into the placeholder viewpoint.
// The key step here is to update the caller_bounds's predicates to be
@@ -220,7 +220,7 @@ fn compare_predicate_entailment<'tcx>(

let mut selcx = traits::SelectionContext::new(&infcx);

let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_skol_substs);
let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
let (impl_m_own_bounds, _) = infcx.replace_bound_vars_with_fresh_vars(
impl_m_span,
infer::HigherRankedType,
@@ -261,7 +261,7 @@ fn compare_predicate_entailment<'tcx>(
debug!("compare_impl_method: impl_fty={:?}", impl_fty);

let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, &tcx.fn_sig(trait_m.def_id));
let trait_sig = trait_sig.subst(tcx, trait_to_skol_substs);
let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs);
let trait_sig =
inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, &trait_sig);
let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig));
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/method/probe.rs
Original file line number Diff line number Diff line change
@@ -1468,7 +1468,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
///
/// ```
/// trait Foo { ... }
/// impl Foo for Vec<int> { ... }
/// impl Foo for Vec<i32> { ... }
/// impl Foo for Vec<usize> { ... }
/// ```
///
14 changes: 7 additions & 7 deletions src/librustc_typeck/check/pat.rs
Original file line number Diff line number Diff line change
@@ -212,15 +212,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// errors in some cases, such as this one:
//
// ```
// fn foo<'x>(x: &'x int) {
// fn foo<'x>(x: &'x i32) {
// let a = 1;
// let mut z = x;
// z = &a;
// }
// ```
//
// The reason we might get an error is that `z` might be
// assigned a type like `&'x int`, and then we would have
// assigned a type like `&'x i32`, and then we would have
// a problem when we try to assign `&a` to `z`, because
// the lifetime of `&a` (i.e., the enclosing block) is
// shorter than `'x`.
@@ -229,11 +229,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// expected type here is whatever type the user wrote, not
// the initializer's type. In this case the user wrote
// nothing, so we are going to create a type variable `Z`.
// Then we will assign the type of the initializer (`&'x
// int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
// will instantiate `Z` as a type `&'0 int` where `'0` is
// a fresh region variable, with the constraint that `'x :
// '0`. So basically we're all set.
// Then we will assign the type of the initializer (`&'x i32`)
// as a subtype of `Z`: `&'x i32 <: Z`. And hence we
// will instantiate `Z` as a type `&'0 i32` where `'0` is
// a fresh region variable, with the constraint that `'x : '0`.
// So basically we're all set.
//
// Note that there are two tests to check that this remains true
// (`regions-reassign-{match,let}-bound-pointer.rs`).