Lazily resolve type-alias-impl-trait defining uses

by using an opaque type obligation to bubble up comparisons between opaque types and other types

Also uses proper obligation causes so that the body id works, because out of some reason nll uses body ids for logic instead of just diagnostics.
This commit is contained in:
Oli Scherer 2021-08-20 14:47:12 +00:00 committed by Oli Scherer
parent 8d2b598459
commit 0f6e06b7c0
284 changed files with 2646 additions and 2097 deletions

View file

@ -37,6 +37,7 @@ use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::thir::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef};
@ -697,6 +698,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for chalk")
}
ty::PredicateKind::OpaqueType(a, b) => {
match self.infcx().handle_opaque_type(
a,
b,
&obligation.cause,
obligation.param_env,
) {
Ok(obligations) => {
self.evaluate_predicates_recursively(previous_stack, obligations)
}
Err(_) => Ok(EvaluatedToErr),
}
}
}
});
@ -1337,6 +1351,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
#[instrument(skip(self, param_env, cache_fresh_trait_pred, dep_node), level = "debug")]
fn insert_candidate_cache(
&mut self,
mut param_env: ty::ParamEnv<'tcx>,
@ -1377,6 +1392,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// a projection, look at the bounds of `T::Bar`, see if we can find a
/// `Baz` bound. We return indexes into the list returned by
/// `tcx.item_bounds` for any applicable bounds.
#[instrument(level = "debug", skip(self))]
fn match_projection_obligation_against_definition_bounds(
&mut self,
obligation: &TraitObligation<'tcx>,
@ -1384,10 +1400,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let poly_trait_predicate = self.infcx().resolve_vars_if_possible(obligation.predicate);
let placeholder_trait_predicate =
self.infcx().replace_bound_vars_with_placeholders(poly_trait_predicate);
debug!(
?placeholder_trait_predicate,
"match_projection_obligation_against_definition_bounds"
);
debug!(?placeholder_trait_predicate);
let tcx = self.infcx.tcx;
let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
@ -1438,7 +1451,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
})
.collect();
debug!(?matching_bounds, "match_projection_obligation_against_definition_bounds");
debug!(?matching_bounds);
matching_bounds
}
@ -1468,6 +1481,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
});
self.infcx
.at(&obligation.cause, obligation.param_env)
.define_opaque_types(false)
.sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
.map(|InferOk { obligations: _, value: () }| {
// This method is called within a probe, so we can't have
@ -1523,6 +1537,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.infcx
.at(&obligation.cause, obligation.param_env)
.define_opaque_types(false)
.sup(obligation.predicate, infer_projection)
.map_or(false, |InferOk { obligations, value: () }| {
self.evaluate_predicates_recursively(
@ -2081,11 +2096,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
match self.match_impl(impl_def_id, obligation) {
Ok(substs) => substs,
Err(()) => {
bug!(
"Impl {:?} was matchable against {:?} but now is not",
impl_def_id,
obligation
self.infcx.tcx.sess.delay_span_bug(
obligation.cause.span,
&format!(
"Impl {:?} was matchable against {:?} but now is not",
impl_def_id, obligation
),
);
let value = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
let err = self.tcx().ty_error();
let value = value.fold_with(&mut BottomUpFolder {
tcx: self.tcx(),
ty_op: |_| err,
lt_op: |l| l,
ct_op: |c| c,
});
Normalized { value, obligations: vec![] }
}
}
}
@ -2222,6 +2248,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
self.infcx
.at(&obligation.cause, obligation.param_env)
// We don't want opaque types to just randomly match everything,
// they should be opaque, even in their defining scope.
.define_opaque_types(false)
.sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
.map(|InferOk { obligations, .. }| obligations)
.map_err(|_| ())