Auto merge of #120544 - BoxyUwU:enter_forall, r=lcnr
Introduce `enter_forall` to supercede `instantiate_binder_with_placeholders`
r? `@lcnr`
Long term we'd like to experiment with decrementing the universe count after "exiting" binders so that we do not end up creating infer vars in non-root universes even when they logically reside in the root universe. The fact that we dont do this currently results in a number of issues in the new trait solver where we consider goals to be ambiguous because otherwise it would require lowering the universe of an infer var. i.e. the goal `?x.0 eq <T as Trait<?y.1>>::Assoc` where the alias is rigid would not be able to instantiate `?x` with the alias as there would be a universe error.
This PR is the first-ish sort of step towards being able to implement this as eventually we would want to decrement the universe in `enter_forall`. Unfortunately its Difficult to actually implement decrementing universes nicely so this is a separate step which moves us closer to the long term goal ✨
This commit is contained in:
@@ -971,7 +971,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
|
||||
|
||||
let Goal { param_env, predicate } = goal.goal();
|
||||
|
||||
// For bound predicates we simply call `infcx.instantiate_binder_with_placeholders`
|
||||
// For bound predicates we simply call `infcx.enter_forall`
|
||||
// and then prove the resulting predicate as a nested goal.
|
||||
let trait_ref = match predicate.kind().no_bound_vars() {
|
||||
Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr))) => tr.trait_ref,
|
||||
|
||||
@@ -21,51 +21,62 @@ pub fn recompute_applicable_impls<'tcx>(
|
||||
|
||||
let impl_may_apply = |impl_def_id| {
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
let placeholder_obligation =
|
||||
infcx.instantiate_binder_with_placeholders(obligation.predicate);
|
||||
let obligation_trait_ref =
|
||||
ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
|
||||
infcx.enter_forall(obligation.predicate, |placeholder_obligation| {
|
||||
let obligation_trait_ref = ocx.normalize(
|
||||
&ObligationCause::dummy(),
|
||||
param_env,
|
||||
placeholder_obligation.trait_ref,
|
||||
);
|
||||
|
||||
let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
|
||||
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args);
|
||||
let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref);
|
||||
let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
|
||||
let impl_trait_ref =
|
||||
tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args);
|
||||
let impl_trait_ref =
|
||||
ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref);
|
||||
|
||||
if let Err(_) =
|
||||
ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if let Err(_) =
|
||||
ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_args);
|
||||
ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| {
|
||||
Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
|
||||
}));
|
||||
let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_args);
|
||||
ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| {
|
||||
Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
|
||||
}));
|
||||
|
||||
ocx.select_where_possible().is_empty()
|
||||
ocx.select_where_possible().is_empty()
|
||||
})
|
||||
};
|
||||
|
||||
let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| {
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
let placeholder_obligation =
|
||||
infcx.instantiate_binder_with_placeholders(obligation.predicate);
|
||||
let obligation_trait_ref =
|
||||
ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
|
||||
infcx.enter_forall(obligation.predicate, |placeholder_obligation| {
|
||||
let obligation_trait_ref = ocx.normalize(
|
||||
&ObligationCause::dummy(),
|
||||
param_env,
|
||||
placeholder_obligation.trait_ref,
|
||||
);
|
||||
|
||||
let param_env_predicate = infcx.instantiate_binder_with_fresh_vars(
|
||||
DUMMY_SP,
|
||||
BoundRegionConversionTime::HigherRankedType,
|
||||
poly_trait_predicate,
|
||||
);
|
||||
let param_env_trait_ref =
|
||||
ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref);
|
||||
let param_env_predicate = infcx.instantiate_binder_with_fresh_vars(
|
||||
DUMMY_SP,
|
||||
BoundRegionConversionTime::HigherRankedType,
|
||||
poly_trait_predicate,
|
||||
);
|
||||
let param_env_trait_ref =
|
||||
ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref);
|
||||
|
||||
if let Err(_) =
|
||||
ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, param_env_trait_ref)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if let Err(_) = ocx.eq(
|
||||
&ObligationCause::dummy(),
|
||||
param_env,
|
||||
obligation_trait_ref,
|
||||
param_env_trait_ref,
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ocx.select_where_possible().is_empty()
|
||||
ocx.select_where_possible().is_empty()
|
||||
})
|
||||
};
|
||||
|
||||
let mut ambiguities = Vec::new();
|
||||
|
||||
@@ -64,39 +64,44 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
) -> Option<(DefId, GenericArgsRef<'tcx>)> {
|
||||
let tcx = self.tcx;
|
||||
let param_env = obligation.param_env;
|
||||
let trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
|
||||
let trait_self_ty = trait_ref.self_ty();
|
||||
self.enter_forall(trait_ref, |trait_ref| {
|
||||
let trait_self_ty = trait_ref.self_ty();
|
||||
|
||||
let mut self_match_impls = vec![];
|
||||
let mut fuzzy_match_impls = vec![];
|
||||
let mut self_match_impls = vec![];
|
||||
let mut fuzzy_match_impls = vec![];
|
||||
|
||||
self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| {
|
||||
let impl_args = self.fresh_args_for_item(obligation.cause.span, def_id);
|
||||
let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args);
|
||||
self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| {
|
||||
let impl_args = self.fresh_args_for_item(obligation.cause.span, def_id);
|
||||
let impl_trait_ref =
|
||||
tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args);
|
||||
|
||||
let impl_self_ty = impl_trait_ref.self_ty();
|
||||
let impl_self_ty = impl_trait_ref.self_ty();
|
||||
|
||||
if self.can_eq(param_env, trait_self_ty, impl_self_ty) {
|
||||
self_match_impls.push((def_id, impl_args));
|
||||
if self.can_eq(param_env, trait_self_ty, impl_self_ty) {
|
||||
self_match_impls.push((def_id, impl_args));
|
||||
|
||||
if iter::zip(trait_ref.args.types().skip(1), impl_trait_ref.args.types().skip(1))
|
||||
if iter::zip(
|
||||
trait_ref.args.types().skip(1),
|
||||
impl_trait_ref.args.types().skip(1),
|
||||
)
|
||||
.all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some())
|
||||
{
|
||||
fuzzy_match_impls.push((def_id, impl_args));
|
||||
{
|
||||
fuzzy_match_impls.push((def_id, impl_args));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let impl_def_id_and_args = if self_match_impls.len() == 1 {
|
||||
self_match_impls[0]
|
||||
} else if fuzzy_match_impls.len() == 1 {
|
||||
fuzzy_match_impls[0]
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
let impl_def_id_and_args = if self_match_impls.len() == 1 {
|
||||
self_match_impls[0]
|
||||
} else if fuzzy_match_impls.len() == 1 {
|
||||
fuzzy_match_impls[0]
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
|
||||
tcx.has_attr(impl_def_id_and_args.0, sym::rustc_on_unimplemented)
|
||||
.then_some(impl_def_id_and_args)
|
||||
tcx.has_attr(impl_def_id_and_args.0, sym::rustc_on_unimplemented)
|
||||
.then_some(impl_def_id_and_args)
|
||||
})
|
||||
}
|
||||
|
||||
/// Used to set on_unimplemented's `ItemContext`
|
||||
|
||||
@@ -1248,52 +1248,55 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) -> bool {
|
||||
let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
|
||||
let ty = self.instantiate_binder_with_placeholders(self_ty);
|
||||
let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else {
|
||||
return false;
|
||||
};
|
||||
let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false };
|
||||
let ty::Param(param) = inner_ty.kind() else { return false };
|
||||
let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } =
|
||||
obligation.cause.code()
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
let arg_node = self.tcx.hir_node(*arg_hir_id);
|
||||
let Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) = arg_node else { return false };
|
||||
self.enter_forall(self_ty, |ty: Ty<'_>| {
|
||||
let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else {
|
||||
return false;
|
||||
};
|
||||
let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false };
|
||||
let ty::Param(param) = inner_ty.kind() else { return false };
|
||||
let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } =
|
||||
obligation.cause.code()
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
let arg_node = self.tcx.hir_node(*arg_hir_id);
|
||||
let Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) = arg_node else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None);
|
||||
let has_clone = |ty| {
|
||||
self.type_implements_trait(clone_trait, [ty], obligation.param_env)
|
||||
.must_apply_modulo_regions()
|
||||
};
|
||||
let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None);
|
||||
let has_clone = |ty| {
|
||||
self.type_implements_trait(clone_trait, [ty], obligation.param_env)
|
||||
.must_apply_modulo_regions()
|
||||
};
|
||||
|
||||
let new_obligation = self.mk_trait_obligation_with_new_self_ty(
|
||||
obligation.param_env,
|
||||
trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)),
|
||||
);
|
||||
|
||||
if self.predicate_may_hold(&new_obligation) && has_clone(ty) {
|
||||
if !has_clone(param.to_ty(self.tcx)) {
|
||||
suggest_constraining_type_param(
|
||||
self.tcx,
|
||||
generics,
|
||||
err,
|
||||
param.name.as_str(),
|
||||
"Clone",
|
||||
Some(clone_trait),
|
||||
None,
|
||||
);
|
||||
}
|
||||
err.span_suggestion_verbose(
|
||||
obligation.cause.span.shrink_to_hi(),
|
||||
"consider using clone here",
|
||||
".clone()",
|
||||
Applicability::MaybeIncorrect,
|
||||
let new_obligation = self.mk_trait_obligation_with_new_self_ty(
|
||||
obligation.param_env,
|
||||
trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
false
|
||||
|
||||
if self.predicate_may_hold(&new_obligation) && has_clone(ty) {
|
||||
if !has_clone(param.to_ty(self.tcx)) {
|
||||
suggest_constraining_type_param(
|
||||
self.tcx,
|
||||
generics,
|
||||
err,
|
||||
param.name.as_str(),
|
||||
"Clone",
|
||||
Some(clone_trait),
|
||||
None,
|
||||
);
|
||||
}
|
||||
err.span_suggestion_verbose(
|
||||
obligation.cause.span.shrink_to_hi(),
|
||||
"consider using clone here",
|
||||
".clone()".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
false
|
||||
})
|
||||
}
|
||||
|
||||
/// Extracts information about a callable type for diagnostics. This is a
|
||||
@@ -4038,26 +4041,27 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
if let Some(where_pred) = where_pred.as_trait_clause()
|
||||
&& let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred()
|
||||
{
|
||||
let where_pred = self.instantiate_binder_with_placeholders(where_pred);
|
||||
let failed_pred = self.instantiate_binder_with_fresh_vars(
|
||||
expr.span,
|
||||
BoundRegionConversionTime::FnCall,
|
||||
failed_pred,
|
||||
);
|
||||
self.enter_forall(where_pred, |where_pred| {
|
||||
let failed_pred = self.instantiate_binder_with_fresh_vars(
|
||||
expr.span,
|
||||
BoundRegionConversionTime::FnCall,
|
||||
failed_pred,
|
||||
);
|
||||
|
||||
let zipped = iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args);
|
||||
for (expected, actual) in zipped {
|
||||
self.probe(|_| {
|
||||
match self.at(&ObligationCause::misc(expr.span, body_id), param_env).eq(
|
||||
DefineOpaqueTypes::No,
|
||||
expected,
|
||||
actual,
|
||||
) {
|
||||
Ok(_) => (), // We ignore nested obligations here for now.
|
||||
Err(err) => type_diffs.push(err),
|
||||
}
|
||||
})
|
||||
}
|
||||
let zipped =
|
||||
iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args);
|
||||
for (expected, actual) in zipped {
|
||||
self.probe(|_| {
|
||||
match self
|
||||
.at(&ObligationCause::misc(expr.span, body_id), param_env)
|
||||
.eq(DefineOpaqueTypes::No, expected, actual)
|
||||
{
|
||||
Ok(_) => (), // We ignore nested obligations here for now.
|
||||
Err(err) => type_diffs.push(err),
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
} else if let Some(where_pred) = where_pred.as_projection_clause()
|
||||
&& let Some(failed_pred) = failed_pred.to_opt_poly_projection_pred()
|
||||
&& let Some(found) = failed_pred.skip_binder().term.ty()
|
||||
@@ -4614,14 +4618,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
{
|
||||
self.probe(|_| {
|
||||
let ocx = ObligationCtxt::new(self);
|
||||
let pred = self.instantiate_binder_with_placeholders(pred);
|
||||
let pred = ocx.normalize(&ObligationCause::dummy(), param_env, pred);
|
||||
ocx.register_obligation(Obligation::new(
|
||||
self.tcx,
|
||||
ObligationCause::dummy(),
|
||||
param_env,
|
||||
pred,
|
||||
));
|
||||
self.enter_forall(pred, |pred| {
|
||||
let pred = ocx.normalize(&ObligationCause::dummy(), param_env, pred);
|
||||
ocx.register_obligation(Obligation::new(
|
||||
self.tcx,
|
||||
ObligationCause::dummy(),
|
||||
param_env,
|
||||
pred,
|
||||
));
|
||||
});
|
||||
if !ocx.select_where_possible().is_empty() {
|
||||
// encountered errors.
|
||||
return;
|
||||
@@ -4768,13 +4773,13 @@ fn hint_missing_borrow<'tcx>(
|
||||
}
|
||||
|
||||
let found_args = match found.kind() {
|
||||
ty::FnPtr(f) => infcx.instantiate_binder_with_placeholders(*f).inputs().iter(),
|
||||
ty::FnPtr(f) => infcx.enter_forall(*f, |f| f.inputs().iter()),
|
||||
kind => {
|
||||
span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind)
|
||||
}
|
||||
};
|
||||
let expected_args = match expected.kind() {
|
||||
ty::FnPtr(f) => infcx.instantiate_binder_with_placeholders(*f).inputs().iter(),
|
||||
ty::FnPtr(f) => infcx.enter_forall(*f, |f| f.inputs().iter()),
|
||||
kind => {
|
||||
span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind)
|
||||
}
|
||||
|
||||
@@ -1305,12 +1305,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
let mut pred = obligation.predicate.to_opt_poly_trait_pred();
|
||||
while let Some((next_code, next_pred)) = code.parent() {
|
||||
if let Some(pred) = pred {
|
||||
let pred = self.instantiate_binder_with_placeholders(pred);
|
||||
diag.note(format!(
|
||||
"`{}` must implement `{}`, but it does not",
|
||||
pred.self_ty(),
|
||||
pred.print_modifiers_and_trait_path()
|
||||
));
|
||||
self.enter_forall(pred, |pred| {
|
||||
diag.note(format!(
|
||||
"`{}` must implement `{}`, but it does not",
|
||||
pred.self_ty(),
|
||||
pred.print_modifiers_and_trait_path()
|
||||
));
|
||||
})
|
||||
}
|
||||
code = next_code;
|
||||
pred = next_pred;
|
||||
@@ -2015,70 +2016,78 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
if let [single] = &impl_candidates {
|
||||
if self.probe(|_| {
|
||||
let ocx = ObligationCtxt::new(self);
|
||||
let obligation_trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
|
||||
let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id);
|
||||
let impl_trait_ref = ocx.normalize(
|
||||
&ObligationCause::dummy(),
|
||||
param_env,
|
||||
ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args),
|
||||
);
|
||||
|
||||
ocx.register_obligations(
|
||||
self.tcx
|
||||
.predicates_of(single.impl_def_id)
|
||||
.instantiate(self.tcx, impl_args)
|
||||
.into_iter()
|
||||
.map(|(clause, _)| {
|
||||
Obligation::new(self.tcx, ObligationCause::dummy(), param_env, clause)
|
||||
}),
|
||||
);
|
||||
if !ocx.select_where_possible().is_empty() {
|
||||
return false;
|
||||
}
|
||||
self.enter_forall(trait_ref, |obligation_trait_ref| {
|
||||
let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id);
|
||||
let impl_trait_ref = ocx.normalize(
|
||||
&ObligationCause::dummy(),
|
||||
param_env,
|
||||
ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args),
|
||||
);
|
||||
|
||||
let mut terrs = vec![];
|
||||
for (obligation_arg, impl_arg) in
|
||||
std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args)
|
||||
{
|
||||
if let Err(terr) =
|
||||
ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg)
|
||||
{
|
||||
terrs.push(terr);
|
||||
}
|
||||
ocx.register_obligations(
|
||||
self.tcx
|
||||
.predicates_of(single.impl_def_id)
|
||||
.instantiate(self.tcx, impl_args)
|
||||
.into_iter()
|
||||
.map(|(clause, _)| {
|
||||
Obligation::new(
|
||||
self.tcx,
|
||||
ObligationCause::dummy(),
|
||||
param_env,
|
||||
clause,
|
||||
)
|
||||
}),
|
||||
);
|
||||
if !ocx.select_where_possible().is_empty() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Literally nothing unified, just give up.
|
||||
if terrs.len() == impl_trait_ref.args.len() {
|
||||
return false;
|
||||
}
|
||||
let mut terrs = vec![];
|
||||
for (obligation_arg, impl_arg) in
|
||||
std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args)
|
||||
{
|
||||
if let Err(terr) =
|
||||
ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg)
|
||||
{
|
||||
terrs.push(terr);
|
||||
}
|
||||
if !ocx.select_where_possible().is_empty() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
let cand =
|
||||
self.resolve_vars_if_possible(impl_trait_ref).fold_with(&mut BottomUpFolder {
|
||||
tcx: self.tcx,
|
||||
ty_op: |ty| ty,
|
||||
lt_op: |lt| lt,
|
||||
ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()),
|
||||
});
|
||||
err.highlighted_help(vec![
|
||||
StringPart::normal(format!("the trait `{}` ", cand.print_trait_sugared())),
|
||||
StringPart::highlighted("is"),
|
||||
StringPart::normal(" implemented for `"),
|
||||
StringPart::highlighted(cand.self_ty().to_string()),
|
||||
StringPart::normal("`"),
|
||||
]);
|
||||
// Literally nothing unified, just give up.
|
||||
if terrs.len() == impl_trait_ref.args.len() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if let [TypeError::Sorts(exp_found)] = &terrs[..] {
|
||||
let exp_found = self.resolve_vars_if_possible(*exp_found);
|
||||
err.help(format!(
|
||||
"for that trait implementation, expected `{}`, found `{}`",
|
||||
exp_found.expected, exp_found.found
|
||||
));
|
||||
}
|
||||
let cand = self.resolve_vars_if_possible(impl_trait_ref).fold_with(
|
||||
&mut BottomUpFolder {
|
||||
tcx: self.tcx,
|
||||
ty_op: |ty| ty,
|
||||
lt_op: |lt| lt,
|
||||
ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()),
|
||||
},
|
||||
);
|
||||
err.highlighted_help(vec![
|
||||
StringPart::normal(format!("the trait `{}` ", cand.print_trait_sugared())),
|
||||
StringPart::highlighted("is"),
|
||||
StringPart::normal(" implemented for `"),
|
||||
StringPart::highlighted(cand.self_ty().to_string()),
|
||||
StringPart::normal("`"),
|
||||
]);
|
||||
|
||||
true
|
||||
if let [TypeError::Sorts(exp_found)] = &terrs[..] {
|
||||
let exp_found = self.resolve_vars_if_possible(*exp_found);
|
||||
err.help(format!(
|
||||
"for that trait implementation, expected `{}`, found `{}`",
|
||||
exp_found.expected, exp_found.found
|
||||
));
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
}) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -358,8 +358,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||
| ty::PredicateKind::Coerce(_)
|
||||
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
|
||||
| ty::PredicateKind::ConstEquate(..) => {
|
||||
let pred =
|
||||
ty::Binder::dummy(infcx.instantiate_binder_with_placeholders(binder));
|
||||
let pred = ty::Binder::dummy(infcx.enter_forall_and_leak_universe(binder));
|
||||
ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)]))
|
||||
}
|
||||
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
|
||||
|
||||
@@ -250,8 +250,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
|
||||
let infcx = selcx.infcx;
|
||||
let r = infcx.commit_if_ok(|_snapshot| {
|
||||
let old_universe = infcx.universe();
|
||||
let placeholder_predicate =
|
||||
infcx.instantiate_binder_with_placeholders(obligation.predicate);
|
||||
let placeholder_predicate = infcx.enter_forall_and_leak_universe(obligation.predicate);
|
||||
let new_universe = infcx.universe();
|
||||
|
||||
let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate);
|
||||
|
||||
@@ -728,64 +728,63 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
|
||||
self.infcx.probe(|_snapshot| {
|
||||
let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
|
||||
let placeholder_trait_predicate =
|
||||
self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate);
|
||||
|
||||
let self_ty = placeholder_trait_predicate.self_ty();
|
||||
let principal_trait_ref = match self_ty.kind() {
|
||||
ty::Dynamic(data, ..) => {
|
||||
if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
|
||||
debug!(
|
||||
"assemble_candidates_from_object_ty: matched builtin bound, \
|
||||
self.infcx.enter_forall(poly_trait_predicate, |placeholder_trait_predicate| {
|
||||
let self_ty = placeholder_trait_predicate.self_ty();
|
||||
let principal_trait_ref = match self_ty.kind() {
|
||||
ty::Dynamic(data, ..) => {
|
||||
if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
|
||||
debug!(
|
||||
"assemble_candidates_from_object_ty: matched builtin bound, \
|
||||
pushing candidate"
|
||||
);
|
||||
candidates.vec.push(BuiltinObjectCandidate);
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(principal) = data.principal() {
|
||||
if !self.infcx.tcx.features().object_safe_for_dispatch {
|
||||
principal.with_self_ty(self.tcx(), self_ty)
|
||||
} else if self.tcx().check_is_object_safe(principal.def_id()) {
|
||||
principal.with_self_ty(self.tcx(), self_ty)
|
||||
} else {
|
||||
);
|
||||
candidates.vec.push(BuiltinObjectCandidate);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Only auto trait bounds exist.
|
||||
|
||||
if let Some(principal) = data.principal() {
|
||||
if !self.infcx.tcx.features().object_safe_for_dispatch {
|
||||
principal.with_self_ty(self.tcx(), self_ty)
|
||||
} else if self.tcx().check_is_object_safe(principal.def_id()) {
|
||||
principal.with_self_ty(self.tcx(), self_ty)
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Only auto trait bounds exist.
|
||||
return;
|
||||
}
|
||||
}
|
||||
ty::Infer(ty::TyVar(_)) => {
|
||||
debug!("assemble_candidates_from_object_ty: ambiguous");
|
||||
candidates.ambiguous = true; // could wind up being an object type
|
||||
return;
|
||||
}
|
||||
}
|
||||
ty::Infer(ty::TyVar(_)) => {
|
||||
debug!("assemble_candidates_from_object_ty: ambiguous");
|
||||
candidates.ambiguous = true; // could wind up being an object type
|
||||
return;
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
_ => return,
|
||||
};
|
||||
|
||||
debug!(?principal_trait_ref, "assemble_candidates_from_object_ty");
|
||||
debug!(?principal_trait_ref, "assemble_candidates_from_object_ty");
|
||||
|
||||
// Count only those upcast versions that match the trait-ref
|
||||
// we are looking for. Specifically, do not only check for the
|
||||
// correct trait, but also the correct type parameters.
|
||||
// For example, we may be trying to upcast `Foo` to `Bar<i32>`,
|
||||
// but `Foo` is declared as `trait Foo: Bar<u32>`.
|
||||
let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref)
|
||||
.enumerate()
|
||||
.filter(|&(_, upcast_trait_ref)| {
|
||||
self.infcx.probe(|_| {
|
||||
self.match_normalize_trait_ref(
|
||||
obligation,
|
||||
upcast_trait_ref,
|
||||
placeholder_trait_predicate.trait_ref,
|
||||
)
|
||||
.is_ok()
|
||||
// Count only those upcast versions that match the trait-ref
|
||||
// we are looking for. Specifically, do not only check for the
|
||||
// correct trait, but also the correct type parameters.
|
||||
// For example, we may be trying to upcast `Foo` to `Bar<i32>`,
|
||||
// but `Foo` is declared as `trait Foo: Bar<u32>`.
|
||||
let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref)
|
||||
.enumerate()
|
||||
.filter(|&(_, upcast_trait_ref)| {
|
||||
self.infcx.probe(|_| {
|
||||
self.match_normalize_trait_ref(
|
||||
obligation,
|
||||
upcast_trait_ref,
|
||||
placeholder_trait_predicate.trait_ref,
|
||||
)
|
||||
.is_ok()
|
||||
})
|
||||
})
|
||||
})
|
||||
.map(|(idx, _)| ObjectCandidate(idx));
|
||||
.map(|(idx, _)| ObjectCandidate(idx));
|
||||
|
||||
candidates.vec.extend(candidate_supertraits);
|
||||
candidates.vec.extend(candidate_supertraits);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
|
||||
let trait_predicate = self.infcx.shallow_resolve(obligation.predicate);
|
||||
let placeholder_trait_predicate =
|
||||
self.infcx.instantiate_binder_with_placeholders(trait_predicate).trait_ref;
|
||||
self.infcx.enter_forall_and_leak_universe(trait_predicate).trait_ref;
|
||||
let placeholder_self_ty = placeholder_trait_predicate.self_ty();
|
||||
let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
|
||||
let (def_id, args) = match *placeholder_self_ty.kind() {
|
||||
@@ -402,7 +402,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
let cause = obligation.derived_cause(BuiltinDerivedObligation);
|
||||
|
||||
let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
|
||||
let trait_ref = self.infcx.instantiate_binder_with_placeholders(poly_trait_ref);
|
||||
let trait_ref = self.infcx.enter_forall_and_leak_universe(poly_trait_ref);
|
||||
let trait_obligations: Vec<PredicateObligation<'_>> = self.impl_or_trait_obligations(
|
||||
&cause,
|
||||
obligation.recursion_depth + 1,
|
||||
@@ -493,7 +493,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
let tcx = self.tcx();
|
||||
debug!(?obligation, ?index, "confirm_object_candidate");
|
||||
|
||||
let trait_predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
|
||||
let trait_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
|
||||
let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty());
|
||||
let obligation_trait_ref = ty::Binder::dummy(trait_predicate.trait_ref);
|
||||
let ty::Dynamic(data, ..) = *self_ty.kind() else {
|
||||
@@ -691,7 +691,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
let cause = obligation.derived_cause(BuiltinDerivedObligation);
|
||||
|
||||
// Confirm the `type Output: Sized;` bound that is present on `FnOnce`
|
||||
let output_ty = self.infcx.instantiate_binder_with_placeholders(sig.output());
|
||||
let output_ty = self.infcx.enter_forall_and_leak_universe(sig.output());
|
||||
let output_ty = normalize_with_depth_to(
|
||||
self,
|
||||
obligation.param_env,
|
||||
@@ -712,7 +712,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
) -> Vec<PredicateObligation<'tcx>> {
|
||||
debug!(?obligation, "confirm_trait_alias_candidate");
|
||||
|
||||
let predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
|
||||
let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
|
||||
let trait_ref = predicate.trait_ref;
|
||||
let trait_def_id = trait_ref.def_id;
|
||||
let args = trait_ref.args;
|
||||
|
||||
@@ -1606,7 +1606,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
) -> smallvec::SmallVec<[usize; 2]> {
|
||||
let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
|
||||
let placeholder_trait_predicate =
|
||||
self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate);
|
||||
self.infcx.enter_forall_and_leak_universe(poly_trait_predicate);
|
||||
debug!(?placeholder_trait_predicate);
|
||||
|
||||
let tcx = self.infcx.tcx;
|
||||
@@ -2386,7 +2386,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
.flat_map(|ty| {
|
||||
let ty: ty::Binder<'tcx, Ty<'tcx>> = types.rebind(*ty); // <----/
|
||||
|
||||
let placeholder_ty = self.infcx.instantiate_binder_with_placeholders(ty);
|
||||
let placeholder_ty = self.infcx.enter_forall_and_leak_universe(ty);
|
||||
let Normalized { value: normalized_ty, mut obligations } =
|
||||
ensure_sufficient_stack(|| {
|
||||
project::normalize_with_depth(
|
||||
@@ -2472,7 +2472,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
obligation: &PolyTraitObligation<'tcx>,
|
||||
) -> Result<Normalized<'tcx, GenericArgsRef<'tcx>>, ()> {
|
||||
let placeholder_obligation =
|
||||
self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
|
||||
self.infcx.enter_forall_and_leak_universe(obligation.predicate);
|
||||
let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;
|
||||
|
||||
let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id);
|
||||
|
||||
Reference in New Issue
Block a user