1
Fork 0

Rollup merge of #92006 - oli-obk:welcome_opaque_types_into_the_fold, r=nikomatsakis

Welcome opaque types into the fold

r? ```@nikomatsakis``` because idk who else to bug on the type_op changes

The commits have explanations in them. The TLDR is that

* 5c46002273 stops the "recurse and replace" scheme that replaces opaque types with their canonical inference var by just doing that ahead of time
* bdeeb07bf6 does not affect anything on master afaict, but since opaque types generate obligations when instantiated, and lazy TAIT instantiates opaque types *everywhere*, we need to properly handle obligations here instead of just hoping no problematic obligations ever come up.
This commit is contained in:
Matthias Krüger 2022-01-13 08:11:19 +01:00 committed by GitHub
commit b45a819bef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 61 additions and 80 deletions

View file

@ -4,7 +4,9 @@ use crate::infer::canonical::{
use crate::infer::{InferCtxt, InferOk};
use crate::traits::query::Fallible;
use crate::traits::ObligationCause;
use rustc_infer::infer::canonical::Canonical;
use rustc_infer::infer::canonical::{Canonical, Certainty};
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::PredicateObligations;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
use std::fmt;
@ -17,7 +19,6 @@ pub mod implied_outlives_bounds;
pub mod normalize;
pub mod outlives;
pub mod prove_predicate;
use self::prove_predicate::ProvePredicate;
pub mod subtype;
pub use rustc_middle::traits::query::type_op::*;
@ -80,9 +81,14 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
query_key: ParamEnvAnd<'tcx, Self>,
infcx: &InferCtxt<'_, 'tcx>,
output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
) -> Fallible<(Self::QueryResponse, Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>)> {
) -> Fallible<(
Self::QueryResponse,
Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>,
PredicateObligations<'tcx>,
Certainty,
)> {
if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
return Ok((result, None));
return Ok((result, None, vec![], Certainty::Proven));
}
// FIXME(#33684) -- We need to use
@ -104,20 +110,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
output_query_region_constraints,
)?;
// Typically, instantiating NLL query results does not
// create obligations. However, in some cases there
// are unresolved type variables, and unify them *can*
// create obligations. In that case, we have to go
// fulfill them. We do this via a (recursive) query.
for obligation in obligations {
let ((), _) = ProvePredicate::fully_perform_into(
obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
infcx,
output_query_region_constraints,
)?;
}
Ok((value, Some(canonical_self)))
Ok((value, Some(canonical_self), obligations, canonical_result.value.certainty))
}
}
@ -129,9 +122,39 @@ where
fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
let mut region_constraints = QueryRegionConstraints::default();
let (output, canonicalized_query) =
let (output, canonicalized_query, mut obligations, _) =
Q::fully_perform_into(self, infcx, &mut region_constraints)?;
// Typically, instantiating NLL query results does not
// create obligations. However, in some cases there
// are unresolved type variables, and unify them *can*
// create obligations. In that case, we have to go
// fulfill them. We do this via a (recursive) query.
while !obligations.is_empty() {
trace!("{:#?}", obligations);
let mut progress = false;
for obligation in std::mem::take(&mut obligations) {
let obligation = infcx.resolve_vars_if_possible(obligation);
match ProvePredicate::fully_perform_into(
obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
infcx,
&mut region_constraints,
) {
Ok(((), _, new, certainty)) => {
obligations.extend(new);
progress = true;
if let Certainty::Ambiguous = certainty {
obligations.push(obligation);
}
}
Err(_) => obligations.push(obligation),
}
}
if !progress {
return Err(NoSolution);
}
}
// Promote the final query-region-constraints into a
// (optional) ref-counted vector:
let region_constraints =