Revert "Auto merge of #92007 - oli-obk:lazy_tait2, r=nikomatsakis"
This reverts commite7cc3bddbe
, reversing changes made to734368a200
.
This commit is contained in:
parent
2d8b8f3593
commit
d54195db22
359 changed files with 2448 additions and 3311 deletions
|
@ -34,12 +34,6 @@ pub struct At<'a, 'tcx> {
|
|||
pub infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
pub cause: &'a ObligationCause<'tcx>,
|
||||
pub param_env: ty::ParamEnv<'tcx>,
|
||||
/// Whether we should define opaque types
|
||||
/// or just treat them opaquely.
|
||||
/// Currently only used to prevent predicate
|
||||
/// matching from matching anything against opaque
|
||||
/// types.
|
||||
pub define_opaque_types: bool,
|
||||
}
|
||||
|
||||
pub struct Trace<'a, 'tcx> {
|
||||
|
@ -55,7 +49,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
cause: &'a ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> At<'a, 'tcx> {
|
||||
At { infcx: self, cause, param_env, define_opaque_types: true }
|
||||
At { infcx: self, cause, param_env }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,10 +64,6 @@ pub trait ToTrace<'tcx>: Relate<'tcx> + Copy {
|
|||
}
|
||||
|
||||
impl<'a, 'tcx> At<'a, 'tcx> {
|
||||
pub fn define_opaque_types(self, define_opaque_types: bool) -> Self {
|
||||
Self { define_opaque_types, ..self }
|
||||
}
|
||||
|
||||
/// Hacky routine for equating two impl headers in coherence.
|
||||
pub fn eq_impl_headers(
|
||||
self,
|
||||
|
@ -204,7 +194,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
|
|||
{
|
||||
let Trace { at, trace, a_is_expected } = self;
|
||||
at.infcx.commit_if_ok(|_| {
|
||||
let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types);
|
||||
let mut fields = at.infcx.combine_fields(trace, at.param_env);
|
||||
fields
|
||||
.sub(a_is_expected)
|
||||
.relate(a, b)
|
||||
|
@ -221,7 +211,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
|
|||
{
|
||||
let Trace { at, trace, a_is_expected } = self;
|
||||
at.infcx.commit_if_ok(|_| {
|
||||
let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types);
|
||||
let mut fields = at.infcx.combine_fields(trace, at.param_env);
|
||||
fields
|
||||
.equate(a_is_expected)
|
||||
.relate(a, b)
|
||||
|
@ -236,7 +226,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
|
|||
{
|
||||
let Trace { at, trace, a_is_expected } = self;
|
||||
at.infcx.commit_if_ok(|_| {
|
||||
let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types);
|
||||
let mut fields = at.infcx.combine_fields(trace, at.param_env);
|
||||
fields
|
||||
.lub(a_is_expected)
|
||||
.relate(a, b)
|
||||
|
@ -251,7 +241,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
|
|||
{
|
||||
let Trace { at, trace, a_is_expected } = self;
|
||||
at.infcx.commit_if_ok(|_| {
|
||||
let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types);
|
||||
let mut fields = at.infcx.combine_fields(trace, at.param_env);
|
||||
fields
|
||||
.glb(a_is_expected)
|
||||
.relate(a, b)
|
||||
|
|
|
@ -26,7 +26,6 @@ use rustc_middle::ty::fold::TypeFoldable;
|
|||
use rustc_middle::ty::relate::TypeRelation;
|
||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
|
||||
use rustc_middle::ty::{self, BoundVar, Const, ToPredicate, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
use std::fmt::Debug;
|
||||
use std::iter;
|
||||
|
||||
|
@ -90,7 +89,6 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
|||
var_values: inference_vars,
|
||||
region_constraints: QueryRegionConstraints::default(),
|
||||
certainty: Certainty::Proven, // Ambiguities are OK!
|
||||
opaque_types: vec![],
|
||||
value: answer,
|
||||
})
|
||||
}
|
||||
|
@ -135,27 +133,14 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
|||
let certainty =
|
||||
if ambig_errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous };
|
||||
|
||||
let opaque_types = self.take_opaque_types_for_query_response();
|
||||
|
||||
Ok(QueryResponse {
|
||||
var_values: inference_vars,
|
||||
region_constraints,
|
||||
certainty,
|
||||
value: answer,
|
||||
opaque_types,
|
||||
})
|
||||
}
|
||||
|
||||
fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.opaque_type_storage
|
||||
.take_opaque_types()
|
||||
.into_iter()
|
||||
.map(|(k, v)| (self.tcx.mk_opaque(k.def_id, k.substs), v.hidden_type.ty))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Given the (canonicalized) result to a canonical query,
|
||||
/// instantiates the result so it can be used, plugging in the
|
||||
/// values from the canonical query. (Note that the result may
|
||||
|
@ -238,12 +223,13 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
|||
where
|
||||
R: Debug + TypeFoldable<'tcx>,
|
||||
{
|
||||
let InferOk { value: result_subst, mut obligations } = self
|
||||
.query_response_substitution_guess(cause, param_env, original_values, query_response)?;
|
||||
let result_subst =
|
||||
self.query_response_substitution_guess(cause, original_values, query_response);
|
||||
|
||||
// Compute `QueryOutlivesConstraint` values that unify each of
|
||||
// the original values `v_o` that was canonicalized into a
|
||||
// variable...
|
||||
let mut obligations = vec![];
|
||||
|
||||
for (index, original_value) in original_values.var_values.iter().enumerate() {
|
||||
// ...with the value `v_r` of that variable from the query.
|
||||
|
@ -358,25 +344,20 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
|||
original_values, query_response,
|
||||
);
|
||||
|
||||
let mut value = self.query_response_substitution_guess(
|
||||
cause,
|
||||
param_env,
|
||||
original_values,
|
||||
query_response,
|
||||
)?;
|
||||
let result_subst =
|
||||
self.query_response_substitution_guess(cause, original_values, query_response);
|
||||
|
||||
value.obligations.extend(
|
||||
self.unify_query_response_substitution_guess(
|
||||
let obligations = self
|
||||
.unify_query_response_substitution_guess(
|
||||
cause,
|
||||
param_env,
|
||||
original_values,
|
||||
&value.value,
|
||||
&result_subst,
|
||||
query_response,
|
||||
)?
|
||||
.into_obligations(),
|
||||
);
|
||||
.into_obligations();
|
||||
|
||||
Ok(value)
|
||||
Ok(InferOk { value: result_subst, obligations })
|
||||
}
|
||||
|
||||
/// Given the original values and the (canonicalized) result from
|
||||
|
@ -391,10 +372,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
|||
fn query_response_substitution_guess<R>(
|
||||
&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
original_values: &OriginalQueryValues<'tcx>,
|
||||
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
|
||||
) -> InferResult<'tcx, CanonicalVarValues<'tcx>>
|
||||
) -> CanonicalVarValues<'tcx>
|
||||
where
|
||||
R: Debug + TypeFoldable<'tcx>,
|
||||
{
|
||||
|
@ -494,16 +474,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
|||
.collect(),
|
||||
};
|
||||
|
||||
let mut obligations = vec![];
|
||||
|
||||
// Carry all newly resolved opaque types to the caller's scope
|
||||
for &(a, b) in &query_response.value.opaque_types {
|
||||
let a = substitute_value(self.tcx, &result_subst, a);
|
||||
let b = substitute_value(self.tcx, &result_subst, b);
|
||||
obligations.extend(self.handle_opaque_type(a, b, cause, param_env)?.obligations);
|
||||
}
|
||||
|
||||
Ok(InferOk { value: result_subst, obligations })
|
||||
result_subst
|
||||
}
|
||||
|
||||
/// Given a "guess" at the values for the canonical variables in
|
||||
|
@ -660,10 +631,6 @@ struct QueryTypeRelatingDelegate<'a, 'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
|
||||
fn span(&self) -> Span {
|
||||
self.cause.span
|
||||
}
|
||||
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.param_env
|
||||
}
|
||||
|
@ -719,14 +686,4 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
|
|||
fn forbid_inference_vars() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn register_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool) {
|
||||
self.obligations.push(self.infcx.opaque_ty_obligation(
|
||||
a,
|
||||
b,
|
||||
a_is_expected,
|
||||
self.param_env,
|
||||
self.cause.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,12 +51,6 @@ pub struct CombineFields<'infcx, 'tcx> {
|
|||
pub cause: Option<ty::relate::Cause>,
|
||||
pub param_env: ty::ParamEnv<'tcx>,
|
||||
pub obligations: PredicateObligations<'tcx>,
|
||||
/// Whether we should define opaque types
|
||||
/// or just treat them opaquely.
|
||||
/// Currently only used to prevent predicate
|
||||
/// matching from matching anything against opaque
|
||||
/// types.
|
||||
pub define_opaque_types: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -328,7 +322,6 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
/// will first instantiate `b_vid` with a *generalized* version
|
||||
/// of `a_ty`. Generalization introduces other inference
|
||||
/// variables wherever subtyping could occur.
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub fn instantiate(
|
||||
&mut self,
|
||||
a_ty: Ty<'tcx>,
|
||||
|
@ -341,6 +334,8 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
// Get the actual variable that b_vid has been inferred to
|
||||
debug_assert!(self.infcx.inner.borrow_mut().type_variables().probe(b_vid).is_unknown());
|
||||
|
||||
debug!("instantiate(a_ty={:?} dir={:?} b_vid={:?})", a_ty, dir, b_vid);
|
||||
|
||||
// Generalize type of `a_ty` appropriately depending on the
|
||||
// direction. As an example, assume:
|
||||
//
|
||||
|
@ -353,7 +348,10 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
// variables. (Down below, we will relate `a_ty <: b_ty`,
|
||||
// adding constraints like `'x: '?2` and `?1 <: ?3`.)
|
||||
let Generalization { ty: b_ty, needs_wf } = self.generalize(a_ty, b_vid, dir)?;
|
||||
debug!(?b_ty);
|
||||
debug!(
|
||||
"instantiate(a_ty={:?}, dir={:?}, b_vid={:?}, generalized b_ty={:?})",
|
||||
a_ty, dir, b_vid, b_ty
|
||||
);
|
||||
self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
|
||||
|
||||
if needs_wf {
|
||||
|
@ -394,13 +392,13 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
/// Preconditions:
|
||||
///
|
||||
/// - `for_vid` is a "root vid"
|
||||
#[instrument(skip(self), level = "trace")]
|
||||
fn generalize(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
for_vid: ty::TyVid,
|
||||
dir: RelationDir,
|
||||
) -> RelateResult<'tcx, Generalization<'tcx>> {
|
||||
debug!("generalize(ty={:?}, for_vid={:?}, dir={:?}", ty, for_vid, dir);
|
||||
// Determine the ambient variance within which `ty` appears.
|
||||
// The surrounding equation is:
|
||||
//
|
||||
|
@ -414,7 +412,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
RelationDir::SupertypeOf => ty::Contravariant,
|
||||
};
|
||||
|
||||
trace!(?ambient_variance);
|
||||
debug!("generalize: ambient_variance = {:?}", ambient_variance);
|
||||
|
||||
let for_universe = match self.infcx.inner.borrow_mut().type_variables().probe(for_vid) {
|
||||
v @ TypeVariableValue::Known { .. } => {
|
||||
|
@ -423,8 +421,8 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
TypeVariableValue::Unknown { universe } => universe,
|
||||
};
|
||||
|
||||
trace!(?for_universe);
|
||||
trace!(?self.trace);
|
||||
debug!("generalize: for_universe = {:?}", for_universe);
|
||||
debug!("generalize: trace = {:?}", self.trace);
|
||||
|
||||
let mut generalize = Generalizer {
|
||||
infcx: self.infcx,
|
||||
|
@ -441,12 +439,12 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
let ty = match generalize.relate(ty, ty) {
|
||||
Ok(ty) => ty,
|
||||
Err(e) => {
|
||||
debug!(?e, "failure");
|
||||
debug!("generalize: failure {:?}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
let needs_wf = generalize.needs_wf;
|
||||
trace!(?ty, ?needs_wf, "success");
|
||||
debug!("generalize: success {{ {:?}, {:?} }}", ty, needs_wf);
|
||||
Ok(Generalization { ty, needs_wf })
|
||||
}
|
||||
|
||||
|
|
|
@ -66,19 +66,18 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
|
|||
self.relate(a, b)
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
debug!("{}.tys({:?}, {:?})", self.tag(), a, b);
|
||||
if a == b {
|
||||
return Ok(a);
|
||||
}
|
||||
|
||||
trace!(a = ?a.kind(), b = ?b.kind());
|
||||
|
||||
let infcx = self.fields.infcx;
|
||||
|
||||
let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a);
|
||||
let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b);
|
||||
|
||||
debug!("{}.tys: replacements ({:?}, {:?})", self.tag(), a, b);
|
||||
|
||||
match (a.kind(), b.kind()) {
|
||||
(&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => {
|
||||
infcx.inner.borrow_mut().type_variables().equate(a_id, b_id);
|
||||
|
@ -92,21 +91,6 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
|
|||
self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?;
|
||||
}
|
||||
|
||||
(&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
|
||||
self.fields.infcx.super_combine_tys(self, a, b)?;
|
||||
}
|
||||
(&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
|
||||
if self.fields.define_opaque_types && did.is_local() =>
|
||||
{
|
||||
self.fields.obligations.push(infcx.opaque_ty_obligation(
|
||||
a,
|
||||
b,
|
||||
self.a_is_expected(),
|
||||
self.param_env(),
|
||||
self.fields.trace.cause.clone(),
|
||||
));
|
||||
}
|
||||
|
||||
_ => {
|
||||
self.fields.infcx.super_combine_tys(self, a, b)?;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use super::InferCtxt;
|
|||
use super::Subtype;
|
||||
|
||||
use crate::infer::combine::ConstEquateRelation;
|
||||
use crate::traits::{ObligationCause, PredicateObligation};
|
||||
use crate::traits::ObligationCause;
|
||||
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
|
||||
|
@ -111,20 +111,12 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx,
|
|||
&self.fields.trace.cause
|
||||
}
|
||||
|
||||
fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) {
|
||||
self.fields.obligations.extend(obligations)
|
||||
}
|
||||
|
||||
fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
|
||||
let mut sub = self.fields.sub(self.a_is_expected);
|
||||
sub.relate(v, a)?;
|
||||
sub.relate(v, b)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn define_opaque_types(&self) -> bool {
|
||||
self.fields.define_opaque_types
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ConstEquateRelation<'tcx> for Glb<'_, '_, 'tcx> {
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use super::InferCtxt;
|
||||
|
||||
use crate::traits::{ObligationCause, PredicateObligation};
|
||||
use crate::traits::ObligationCause;
|
||||
use rustc_middle::ty::relate::{RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::TyVar;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
|
@ -32,10 +32,6 @@ pub trait LatticeDir<'f, 'tcx>: TypeRelation<'tcx> {
|
|||
|
||||
fn cause(&self) -> &ObligationCause<'tcx>;
|
||||
|
||||
fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>);
|
||||
|
||||
fn define_opaque_types(&self) -> bool;
|
||||
|
||||
// Relates the type `v` to `a` and `b` such that `v` represents
|
||||
// the LUB/GLB of `a` and `b` as appropriate.
|
||||
//
|
||||
|
@ -45,7 +41,6 @@ pub trait LatticeDir<'f, 'tcx>: TypeRelation<'tcx> {
|
|||
fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>;
|
||||
}
|
||||
|
||||
#[instrument(skip(this), level = "debug")]
|
||||
pub fn super_lattice_tys<'a, 'tcx: 'a, L>(
|
||||
this: &mut L,
|
||||
a: Ty<'tcx>,
|
||||
|
@ -54,17 +49,15 @@ pub fn super_lattice_tys<'a, 'tcx: 'a, L>(
|
|||
where
|
||||
L: LatticeDir<'a, 'tcx>,
|
||||
{
|
||||
debug!("{}", this.tag());
|
||||
debug!("{}.lattice_tys({:?}, {:?})", this.tag(), a, b);
|
||||
|
||||
if a == b {
|
||||
return Ok(a);
|
||||
}
|
||||
|
||||
let infcx = this.infcx();
|
||||
|
||||
let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a);
|
||||
let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b);
|
||||
|
||||
match (a.kind(), b.kind()) {
|
||||
// If one side is known to be a variable and one is not,
|
||||
// create a variable (`v`) to represent the LUB. Make sure to
|
||||
|
@ -101,22 +94,6 @@ where
|
|||
Ok(v)
|
||||
}
|
||||
|
||||
(&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
|
||||
infcx.super_combine_tys(this, a, b)
|
||||
}
|
||||
(&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
|
||||
if this.define_opaque_types() && did.is_local() =>
|
||||
{
|
||||
this.add_obligations(vec![infcx.opaque_ty_obligation(
|
||||
a,
|
||||
b,
|
||||
this.a_is_expected(),
|
||||
this.param_env(),
|
||||
this.cause().clone(),
|
||||
)]);
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
_ => infcx.super_combine_tys(this, a, b),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use super::InferCtxt;
|
|||
use super::Subtype;
|
||||
|
||||
use crate::infer::combine::ConstEquateRelation;
|
||||
use crate::traits::{ObligationCause, PredicateObligation};
|
||||
use crate::traits::ObligationCause;
|
||||
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
|
||||
|
@ -117,18 +117,10 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx,
|
|||
&self.fields.trace.cause
|
||||
}
|
||||
|
||||
fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) {
|
||||
self.fields.obligations.extend(obligations)
|
||||
}
|
||||
|
||||
fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
|
||||
let mut sub = self.fields.sub(self.a_is_expected);
|
||||
sub.relate(a, v)?;
|
||||
sub.relate(b, v)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn define_opaque_types(&self) -> bool {
|
||||
self.fields.define_opaque_types
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ pub use self::RegionVariableOrigin::*;
|
|||
pub use self::SubregionOrigin::*;
|
||||
pub use self::ValuePairs::*;
|
||||
|
||||
use self::opaque_types::OpaqueTypeStorage;
|
||||
use self::opaque_types::OpaqueTypeMap;
|
||||
pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog};
|
||||
|
||||
use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine};
|
||||
|
@ -192,8 +192,18 @@ pub struct InferCtxtInner<'tcx> {
|
|||
|
||||
undo_log: InferCtxtUndoLogs<'tcx>,
|
||||
|
||||
/// Caches for opaque type inference.
|
||||
pub opaque_type_storage: OpaqueTypeStorage<'tcx>,
|
||||
// Opaque types found in explicit return types and their
|
||||
// associated fresh inference variable. Writeback resolves these
|
||||
// variables to get the concrete type, which can be used to
|
||||
// 'de-opaque' OpaqueTypeDecl outside of type inference.
|
||||
pub opaque_types: OpaqueTypeMap<'tcx>,
|
||||
|
||||
/// A map from inference variables created from opaque
|
||||
/// type instantiations (`ty::Infer`) to the actual opaque
|
||||
/// type (`ty::Opaque`). Used during fallback to map unconstrained
|
||||
/// opaque type inference variables to their corresponding
|
||||
/// opaque type.
|
||||
pub opaque_types_vars: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> InferCtxtInner<'tcx> {
|
||||
|
@ -207,7 +217,8 @@ impl<'tcx> InferCtxtInner<'tcx> {
|
|||
float_unification_storage: ut::UnificationTableStorage::new(),
|
||||
region_constraint_storage: Some(RegionConstraintStorage::new()),
|
||||
region_obligations: vec![],
|
||||
opaque_type_storage: Default::default(),
|
||||
opaque_types: Default::default(),
|
||||
opaque_types_vars: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,11 +237,6 @@ impl<'tcx> InferCtxtInner<'tcx> {
|
|||
self.type_variable_storage.with_log(&mut self.undo_log)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> {
|
||||
self.opaque_type_storage.with_log(&mut self.undo_log)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn int_unification_table(
|
||||
&mut self,
|
||||
|
@ -291,10 +297,6 @@ pub struct InferCtxt<'a, 'tcx> {
|
|||
/// to the outside until the end up in an `InferCtxt` for typeck or borrowck.
|
||||
pub defining_use_anchor: Option<LocalDefId>,
|
||||
|
||||
/// Used by WF-checking to not have to figure out hidden types itself, but
|
||||
/// to just invoke type_of to get the already computed hidden type from typeck.
|
||||
pub reveal_defining_opaque_types: bool,
|
||||
|
||||
/// During type-checking/inference of a body, `in_progress_typeck_results`
|
||||
/// contains a reference to the typeck results being built up, which are
|
||||
/// used for reading closure kinds/signatures as they are inferred,
|
||||
|
@ -563,7 +565,6 @@ pub struct InferCtxtBuilder<'tcx> {
|
|||
tcx: TyCtxt<'tcx>,
|
||||
fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
|
||||
defining_use_anchor: Option<LocalDefId>,
|
||||
reveal_defining_opaque_types: bool,
|
||||
}
|
||||
|
||||
pub trait TyCtxtInferExt<'tcx> {
|
||||
|
@ -572,12 +573,7 @@ pub trait TyCtxtInferExt<'tcx> {
|
|||
|
||||
impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
|
||||
fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
|
||||
InferCtxtBuilder {
|
||||
tcx: self,
|
||||
defining_use_anchor: None,
|
||||
fresh_typeck_results: None,
|
||||
reveal_defining_opaque_types: false,
|
||||
}
|
||||
InferCtxtBuilder { tcx: self, defining_use_anchor: None, fresh_typeck_results: None }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -601,13 +597,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
|||
self
|
||||
}
|
||||
|
||||
/// WF-checking doesn't need to recompute opaque types and can instead use
|
||||
/// the type_of query to get them from typeck.
|
||||
pub fn reveal_defining_opaque_types(mut self) -> Self {
|
||||
self.reveal_defining_opaque_types = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Given a canonical value `C` as a starting point, create an
|
||||
/// inference context that contains each of the bound values
|
||||
/// within instantiated as a fresh variable. The `f` closure is
|
||||
|
@ -632,17 +621,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
|||
}
|
||||
|
||||
pub fn enter<R>(&mut self, f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>) -> R) -> R {
|
||||
let InferCtxtBuilder {
|
||||
tcx,
|
||||
defining_use_anchor,
|
||||
reveal_defining_opaque_types,
|
||||
ref fresh_typeck_results,
|
||||
} = *self;
|
||||
let InferCtxtBuilder { tcx, defining_use_anchor, ref fresh_typeck_results } = *self;
|
||||
let in_progress_typeck_results = fresh_typeck_results.as_ref();
|
||||
f(InferCtxt {
|
||||
tcx,
|
||||
defining_use_anchor,
|
||||
reveal_defining_opaque_types,
|
||||
in_progress_typeck_results,
|
||||
inner: RefCell::new(InferCtxtInner::new()),
|
||||
lexical_region_resolutions: RefCell::new(None),
|
||||
|
@ -764,7 +747,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
&'a self,
|
||||
trace: TypeTrace<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
define_opaque_types: bool,
|
||||
) -> CombineFields<'a, 'tcx> {
|
||||
CombineFields {
|
||||
infcx: self,
|
||||
|
@ -772,7 +754,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
cause: None,
|
||||
param_env,
|
||||
obligations: PredicateObligations::new(),
|
||||
define_opaque_types,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1088,20 +1069,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
self.tcx.mk_ty_var(self.next_ty_var_id(origin))
|
||||
}
|
||||
|
||||
pub fn next_ty_var_id_in_universe(
|
||||
&self,
|
||||
origin: TypeVariableOrigin,
|
||||
universe: ty::UniverseIndex,
|
||||
) -> TyVid {
|
||||
self.inner.borrow_mut().type_variables().new_var(universe, origin)
|
||||
}
|
||||
|
||||
pub fn next_ty_var_in_universe(
|
||||
&self,
|
||||
origin: TypeVariableOrigin,
|
||||
universe: ty::UniverseIndex,
|
||||
) -> Ty<'tcx> {
|
||||
let vid = self.next_ty_var_id_in_universe(origin, universe);
|
||||
let vid = self.inner.borrow_mut().type_variables().new_var(universe, origin);
|
||||
self.tcx.mk_ty_var(vid)
|
||||
}
|
||||
|
||||
|
|
|
@ -24,13 +24,11 @@
|
|||
use crate::infer::combine::ConstEquateRelation;
|
||||
use crate::infer::InferCtxt;
|
||||
use crate::infer::{ConstVarValue, ConstVariableValue};
|
||||
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::fold::{TypeFoldable, TypeVisitor};
|
||||
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
use std::fmt::Debug;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
|
@ -77,7 +75,6 @@ where
|
|||
|
||||
pub trait TypeRelatingDelegate<'tcx> {
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx>;
|
||||
fn span(&self) -> Span;
|
||||
|
||||
/// Push a constraint `sup: sub` -- this constraint must be
|
||||
/// satisfied for the two types to be related. `sub` and `sup` may
|
||||
|
@ -90,8 +87,6 @@ pub trait TypeRelatingDelegate<'tcx> {
|
|||
info: ty::VarianceDiagInfo<'tcx>,
|
||||
);
|
||||
|
||||
fn register_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool);
|
||||
|
||||
fn const_equate(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>);
|
||||
|
||||
/// Creates a new universe index. Used when instantiating placeholders.
|
||||
|
@ -282,6 +277,7 @@ where
|
|||
projection_ty: ty::ProjectionTy<'tcx>,
|
||||
value_ty: Ty<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
||||
match *value_ty.kind() {
|
||||
|
@ -290,8 +286,6 @@ where
|
|||
kind: TypeVariableOriginKind::MiscVariable,
|
||||
span: DUMMY_SP,
|
||||
});
|
||||
// FIXME(lazy-normalization): This will always ICE, because the recursive
|
||||
// call will end up in the _ arm below.
|
||||
self.relate_projection_ty(projection_ty, var);
|
||||
self.relate_projection_ty(other_projection_ty, var);
|
||||
var
|
||||
|
@ -537,8 +531,6 @@ where
|
|||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn tys(&mut self, a: Ty<'tcx>, mut b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
let infcx = self.infcx;
|
||||
|
||||
let a = self.infcx.shallow_resolve(a);
|
||||
|
||||
if !D::forbid_inference_vars() {
|
||||
|
@ -567,35 +559,6 @@ where
|
|||
|
||||
(&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
|
||||
|
||||
(&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
|
||||
self.infcx.super_combine_tys(self, a, b)
|
||||
}
|
||||
(&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) if did.is_local() => {
|
||||
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
|
||||
let mut generalize = |ty, ty_is_expected| {
|
||||
let var = infcx.next_ty_var_id_in_universe(
|
||||
TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::MiscVariable,
|
||||
span: self.delegate.span(),
|
||||
},
|
||||
ty::UniverseIndex::ROOT,
|
||||
);
|
||||
if ty_is_expected {
|
||||
self.relate_ty_var((ty, var))
|
||||
} else {
|
||||
self.relate_ty_var((var, ty))
|
||||
}
|
||||
};
|
||||
let (a, b) = match (a.kind(), b.kind()) {
|
||||
(&ty::Opaque(..), _) => (a, generalize(b, false)?),
|
||||
(_, &ty::Opaque(..)) => (generalize(a, true)?, b),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
self.delegate.register_opaque_type(a, b, true);
|
||||
trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
(&ty::Projection(projection_ty), _)
|
||||
if D::normalization() == NormalizationStrategy::Lazy =>
|
||||
{
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use crate::infer::{InferCtxt, InferOk};
|
||||
use crate::traits::{self, PredicateObligation};
|
||||
use hir::def_id::{DefId, LocalDefId};
|
||||
use hir::OpaqueTyOrigin;
|
||||
use crate::traits;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::vec_map::VecMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
use rustc_middle::ty::subst::{GenericArgKind, Subst};
|
||||
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitor};
|
||||
|
@ -15,28 +14,14 @@ use std::ops::ControlFlow;
|
|||
|
||||
pub type OpaqueTypeMap<'tcx> = VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>;
|
||||
|
||||
mod table;
|
||||
|
||||
pub use table::{OpaqueTypeStorage, OpaqueTypeTable};
|
||||
|
||||
use super::InferResult;
|
||||
|
||||
/// Information about the opaque types whose values we
|
||||
/// are inferring in this function (these are the `impl Trait` that
|
||||
/// appear in the return type).
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct OpaqueTypeDecl<'tcx> {
|
||||
/// The hidden types that have been inferred for this opaque type.
|
||||
/// There can be multiple, but they are all `lub`ed together at the end
|
||||
/// to obtain the canonical hidden type.
|
||||
pub hidden_type: OpaqueHiddenType<'tcx>,
|
||||
/// The opaque type (`ty::Opaque`) for this declaration.
|
||||
pub opaque_type: Ty<'tcx>,
|
||||
|
||||
/// The origin of the opaque type.
|
||||
pub origin: hir::OpaqueTyOrigin,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, TypeFoldable)]
|
||||
pub struct OpaqueHiddenType<'tcx> {
|
||||
/// The span of this particular definition of the opaque type. So
|
||||
/// for example:
|
||||
///
|
||||
|
@ -50,7 +35,7 @@ pub struct OpaqueHiddenType<'tcx> {
|
|||
/// In cases where the fn returns `(impl Trait, impl Trait)` or
|
||||
/// other such combinations, the result is currently
|
||||
/// over-approximated, but better than nothing.
|
||||
pub span: Span,
|
||||
pub definition_span: Span,
|
||||
|
||||
/// The type variable that represents the value of the opaque type
|
||||
/// that we require. In other words, after we compile this function,
|
||||
|
@ -64,132 +49,54 @@ pub struct OpaqueHiddenType<'tcx> {
|
|||
/// those that are arguments to `Foo` in the constraint above. (In
|
||||
/// other words, `?C` should not include `'b`, even though it's a
|
||||
/// lifetime parameter on `foo`.)
|
||||
pub ty: Ty<'tcx>,
|
||||
pub concrete_ty: Ty<'tcx>,
|
||||
|
||||
/// The origin of the opaque type.
|
||||
pub origin: hir::OpaqueTyOrigin,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
pub fn handle_opaque_type(
|
||||
/// Replaces all opaque types in `value` with fresh inference variables
|
||||
/// and creates appropriate obligations. For example, given the input:
|
||||
///
|
||||
/// impl Iterator<Item = impl Debug>
|
||||
///
|
||||
/// this method would create two type variables, `?0` and `?1`. It would
|
||||
/// return the type `?0` but also the obligations:
|
||||
///
|
||||
/// ?0: Iterator<Item = ?1>
|
||||
/// ?1: Debug
|
||||
///
|
||||
/// Moreover, it returns an `OpaqueTypeMap` that would map `?0` to
|
||||
/// info about the `impl Iterator<..>` type and `?1` to info about
|
||||
/// the `impl Debug` type.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `parent_def_id` -- the `DefId` of the function in which the opaque type
|
||||
/// is defined
|
||||
/// - `body_id` -- the body-id with which the resulting obligations should
|
||||
/// be associated
|
||||
/// - `param_env` -- the in-scope parameter environment to be used for
|
||||
/// obligations
|
||||
/// - `value` -- the value within which we are instantiating opaque types
|
||||
/// - `value_span` -- the span where the value came from, used in error reporting
|
||||
pub fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
|
||||
&self,
|
||||
a: Ty<'tcx>,
|
||||
b: Ty<'tcx>,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
body_id: hir::HirId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> InferResult<'tcx, ()> {
|
||||
if a.references_error() || b.references_error() {
|
||||
return Ok(InferOk { value: (), obligations: vec![] });
|
||||
}
|
||||
if self.defining_use_anchor.is_some() {
|
||||
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
|
||||
ty::Opaque(def_id, substs) => {
|
||||
if let ty::Opaque(did2, _) = *b.kind() {
|
||||
// We could accept this, but there are various ways to handle this situation, and we don't
|
||||
// want to make a decision on it right now. Likely this case is so super rare anyway, that
|
||||
// no one encounters it in practice.
|
||||
// It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`,
|
||||
// where it is of no concern, so we only check for TAITs.
|
||||
if let Some(OpaqueTyOrigin::TyAlias) =
|
||||
self.opaque_type_origin(did2, cause.span)
|
||||
{
|
||||
self.tcx
|
||||
.sess
|
||||
.struct_span_err(
|
||||
cause.span,
|
||||
"opaque type's hidden type cannot be another opaque type from the same scope",
|
||||
)
|
||||
.span_label(cause.span, "one of the two opaque types used here has to be outside its defining scope")
|
||||
.span_note(
|
||||
self.tcx.def_span(def_id),
|
||||
"opaque type whose hidden type is being assigned",
|
||||
)
|
||||
.span_note(
|
||||
self.tcx.def_span(did2),
|
||||
"opaque type being used as hidden type",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
Some(self.register_hidden_type(
|
||||
OpaqueTypeKey { def_id, substs },
|
||||
cause.clone(),
|
||||
param_env,
|
||||
b,
|
||||
// Check that this is `impl Trait` type is
|
||||
// declared by `parent_def_id` -- i.e., one whose
|
||||
// value we are inferring. At present, this is
|
||||
// always true during the first phase of
|
||||
// type-check, but not always true later on during
|
||||
// NLL. Once we support named opaque types more fully,
|
||||
// this same scenario will be able to arise during all phases.
|
||||
//
|
||||
// Here is an example using type alias `impl Trait`
|
||||
// that indicates the distinction we are checking for:
|
||||
//
|
||||
// ```rust
|
||||
// mod a {
|
||||
// pub type Foo = impl Iterator;
|
||||
// pub fn make_foo() -> Foo { .. }
|
||||
// }
|
||||
//
|
||||
// mod b {
|
||||
// fn foo() -> a::Foo { a::make_foo() }
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Here, the return type of `foo` references an
|
||||
// `Opaque` indeed, but not one whose value is
|
||||
// presently being inferred. You can get into a
|
||||
// similar situation with closure return types
|
||||
// today:
|
||||
//
|
||||
// ```rust
|
||||
// fn foo() -> impl Iterator { .. }
|
||||
// fn bar() {
|
||||
// let x = || foo(); // returns the Opaque assoc with `foo`
|
||||
// }
|
||||
// ```
|
||||
self.opaque_type_origin(def_id, cause.span)?,
|
||||
))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
if let Some(res) = process(a, b) {
|
||||
res
|
||||
} else if let Some(res) = process(b, a) {
|
||||
res
|
||||
} else {
|
||||
// Rerun equality check, but this time error out due to
|
||||
// different types.
|
||||
match self.at(cause, param_env).define_opaque_types(false).eq(a, b) {
|
||||
Ok(_) => span_bug!(
|
||||
cause.span,
|
||||
"opaque types are never equal to anything but themselves: {:#?}",
|
||||
(a, b)
|
||||
),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let (opaque_type, hidden_ty) = match (a.kind(), b.kind()) {
|
||||
(ty::Opaque(..), _) => (a, b),
|
||||
(_, ty::Opaque(..)) => (b, a),
|
||||
types => span_bug!(
|
||||
cause.span,
|
||||
"opaque type obligations only work for opaque types: {:#?}",
|
||||
types
|
||||
),
|
||||
};
|
||||
let key = opaque_type.expect_opaque_type();
|
||||
let origin = self.opaque_ty_origin_unchecked(key.def_id, cause.span);
|
||||
let prev = self.inner.borrow_mut().opaque_types().register(
|
||||
key,
|
||||
OpaqueHiddenType { ty: hidden_ty, span: cause.span },
|
||||
origin,
|
||||
);
|
||||
match prev {
|
||||
Some(prev) => self.at(cause, param_env).eq(prev, hidden_ty),
|
||||
None => Ok(InferOk { value: (), obligations: vec![] }),
|
||||
}
|
||||
}
|
||||
value: T,
|
||||
value_span: Span,
|
||||
) -> InferOk<'tcx, T> {
|
||||
debug!(
|
||||
"instantiate_opaque_types(value={:?}, body_id={:?}, \
|
||||
param_env={:?}, value_span={:?})",
|
||||
value, body_id, param_env, value_span,
|
||||
);
|
||||
let mut instantiator =
|
||||
Instantiator { infcx: self, body_id, param_env, value_span, obligations: vec![] };
|
||||
let value = instantiator.instantiate_opaque_types_in_map(value);
|
||||
InferOk { value, obligations: instantiator.obligations }
|
||||
}
|
||||
|
||||
/// Given the map `opaque_types` containing the opaque
|
||||
|
@ -324,23 +231,51 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
/// but this is not necessary, because the opaque type we
|
||||
/// create will be allowed to reference `T`. So we only generate a
|
||||
/// constraint that `'0: 'a`.
|
||||
///
|
||||
/// # The `free_region_relations` parameter
|
||||
///
|
||||
/// The `free_region_relations` argument is used to find the
|
||||
/// "minimum" of the regions supplied to a given opaque type.
|
||||
/// It must be a relation that can answer whether `'a <= 'b`,
|
||||
/// where `'a` and `'b` are regions that appear in the "substs"
|
||||
/// for the opaque type references (the `<'a>` in `Foo1<'a>`).
|
||||
///
|
||||
/// Note that we do not impose the constraints based on the
|
||||
/// generic regions from the `Foo1` definition (e.g., `'x`). This
|
||||
/// is because the constraints we are imposing here is basically
|
||||
/// the concern of the one generating the constraining type C1,
|
||||
/// which is the current function. It also means that we can
|
||||
/// take "implied bounds" into account in some cases:
|
||||
///
|
||||
/// ```text
|
||||
/// trait SomeTrait<'a, 'b> { }
|
||||
/// fn foo<'a, 'b>(_: &'a &'b u32) -> impl SomeTrait<'a, 'b> { .. }
|
||||
/// ```
|
||||
///
|
||||
/// Here, the fact that `'b: 'a` is known only because of the
|
||||
/// implied bounds from the `&'a &'b u32` parameter, and is not
|
||||
/// "inherent" to the opaque type definition.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `opaque_types` -- the map produced by `instantiate_opaque_types`
|
||||
/// - `free_region_relations` -- something that can be used to relate
|
||||
/// the free regions (`'a`) that appear in the impl trait.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub fn register_member_constraints(
|
||||
pub fn constrain_opaque_type(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||
concrete_ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
opaque_defn: &OpaqueTypeDecl<'tcx>,
|
||||
) {
|
||||
let def_id = opaque_type_key.def_id;
|
||||
|
||||
let tcx = self.tcx;
|
||||
|
||||
let concrete_ty = self.resolve_vars_if_possible(concrete_ty);
|
||||
let concrete_ty = self.resolve_vars_if_possible(opaque_defn.concrete_ty);
|
||||
|
||||
debug!(?concrete_ty);
|
||||
|
||||
let first_own_region = match self.opaque_ty_origin_unchecked(def_id, span) {
|
||||
let first_own_region = match opaque_defn.origin {
|
||||
hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {
|
||||
// We lower
|
||||
//
|
||||
|
@ -384,7 +319,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
op: |r| {
|
||||
self.member_constraint(
|
||||
opaque_type_key.def_id,
|
||||
span,
|
||||
opaque_defn.definition_span,
|
||||
concrete_ty,
|
||||
r,
|
||||
&choice_regions,
|
||||
|
@ -393,34 +328,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn opaque_ty_obligation(
|
||||
&self,
|
||||
a: Ty<'tcx>,
|
||||
b: Ty<'tcx>,
|
||||
a_is_expected: bool,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
) -> PredicateObligation<'tcx> {
|
||||
let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
|
||||
PredicateObligation::new(
|
||||
cause,
|
||||
param_env,
|
||||
self.tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::OpaqueType(a, b))),
|
||||
)
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "trace")]
|
||||
pub fn opaque_type_origin(&self, opaque_def_id: DefId, span: Span) -> Option<OpaqueTyOrigin> {
|
||||
let def_id = opaque_def_id.as_local()?;
|
||||
let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<hir::OpaqueTyOrigin> {
|
||||
let tcx = self.tcx;
|
||||
let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let parent_def_id = self.defining_use_anchor?;
|
||||
let item_kind = &self.tcx.hir().expect_item(def_id).kind;
|
||||
|
||||
let item_kind = &tcx.hir().expect_item(def_id).kind;
|
||||
let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item_kind else {
|
||||
span_bug!(
|
||||
span,
|
||||
"weird opaque type: {:#?}, {:#?}",
|
||||
opaque_def_id,
|
||||
tcx.def_span(def_id),
|
||||
"weird opaque type: {:#?}",
|
||||
item_kind
|
||||
)
|
||||
};
|
||||
|
@ -431,29 +347,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id,
|
||||
// Named `type Foo = impl Bar;`
|
||||
hir::OpaqueTyOrigin::TyAlias => {
|
||||
may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id)
|
||||
may_define_opaque_type(tcx, parent_def_id, opaque_hir_id)
|
||||
}
|
||||
};
|
||||
trace!(?origin);
|
||||
in_definition_scope.then_some(*origin)
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "trace")]
|
||||
fn opaque_ty_origin_unchecked(&self, opaque_def_id: DefId, span: Span) -> OpaqueTyOrigin {
|
||||
let def_id = opaque_def_id.as_local().unwrap();
|
||||
let origin = match self.tcx.hir().expect_item(def_id).kind {
|
||||
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => origin,
|
||||
ref itemkind => {
|
||||
span_bug!(span, "weird opaque type: {:?}, {:#?}", opaque_def_id, itemkind)
|
||||
}
|
||||
};
|
||||
trace!(?origin);
|
||||
origin
|
||||
}
|
||||
|
||||
pub fn opaque_types(&self) -> OpaqueTypeMap<'tcx> {
|
||||
self.inner.borrow().opaque_type_storage.opaque_types()
|
||||
}
|
||||
}
|
||||
|
||||
// Visitor that requires that (almost) all regions in the type visited outlive
|
||||
|
@ -528,93 +426,180 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub enum UseKind {
|
||||
DefiningUse,
|
||||
OpaqueUse,
|
||||
struct Instantiator<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
body_id: hir::HirId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
value_span: Span,
|
||||
obligations: Vec<traits::PredicateObligation<'tcx>>,
|
||||
}
|
||||
|
||||
impl UseKind {
|
||||
pub fn is_defining(self) -> bool {
|
||||
match self {
|
||||
UseKind::DefiningUse => true,
|
||||
UseKind::OpaqueUse => false,
|
||||
}
|
||||
impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
||||
fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
|
||||
let tcx = self.infcx.tcx;
|
||||
value.fold_with(&mut BottomUpFolder {
|
||||
tcx,
|
||||
ty_op: |ty| {
|
||||
if ty.references_error() {
|
||||
return tcx.ty_error();
|
||||
} else if let ty::Opaque(def_id, substs) = ty.kind() {
|
||||
// Check that this is `impl Trait` type is
|
||||
// declared by `parent_def_id` -- i.e., one whose
|
||||
// value we are inferring. At present, this is
|
||||
// always true during the first phase of
|
||||
// type-check, but not always true later on during
|
||||
// NLL. Once we support named opaque types more fully,
|
||||
// this same scenario will be able to arise during all phases.
|
||||
//
|
||||
// Here is an example using type alias `impl Trait`
|
||||
// that indicates the distinction we are checking for:
|
||||
//
|
||||
// ```rust
|
||||
// mod a {
|
||||
// pub type Foo = impl Iterator;
|
||||
// pub fn make_foo() -> Foo { .. }
|
||||
// }
|
||||
//
|
||||
// mod b {
|
||||
// fn foo() -> a::Foo { a::make_foo() }
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Here, the return type of `foo` references an
|
||||
// `Opaque` indeed, but not one whose value is
|
||||
// presently being inferred. You can get into a
|
||||
// similar situation with closure return types
|
||||
// today:
|
||||
//
|
||||
// ```rust
|
||||
// fn foo() -> impl Iterator { .. }
|
||||
// fn bar() {
|
||||
// let x = || foo(); // returns the Opaque assoc with `foo`
|
||||
// }
|
||||
// ```
|
||||
if let Some(def_id) = def_id.as_local() {
|
||||
if let Some(origin) = self.infcx.opaque_type_origin(def_id) {
|
||||
let opaque_type_key =
|
||||
OpaqueTypeKey { def_id: def_id.to_def_id(), substs };
|
||||
return self.fold_opaque_ty(ty, opaque_type_key, origin);
|
||||
}
|
||||
|
||||
debug!(
|
||||
"instantiate_opaque_types_in_map: \
|
||||
encountered opaque outside its definition scope \
|
||||
def_id={:?}",
|
||||
def_id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ty
|
||||
},
|
||||
lt_op: |lt| lt,
|
||||
ct_op: |ct| ct,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn register_hidden_type(
|
||||
&self,
|
||||
fn fold_opaque_ty(
|
||||
&mut self,
|
||||
ty: Ty<'tcx>,
|
||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
hidden_ty: Ty<'tcx>,
|
||||
origin: hir::OpaqueTyOrigin,
|
||||
) -> InferResult<'tcx, ()> {
|
||||
let tcx = self.tcx;
|
||||
) -> Ty<'tcx> {
|
||||
let infcx = self.infcx;
|
||||
let tcx = infcx.tcx;
|
||||
let OpaqueTypeKey { def_id, substs } = opaque_type_key;
|
||||
|
||||
// Use the same type variable if the exact same opaque type appears more
|
||||
// than once in the return type (e.g., if it's passed to a type alias).
|
||||
if let Some(opaque_defn) = infcx.inner.borrow().opaque_types.get(&opaque_type_key) {
|
||||
debug!("re-using cached concrete type {:?}", opaque_defn.concrete_ty.kind());
|
||||
return opaque_defn.concrete_ty;
|
||||
}
|
||||
|
||||
let ty_var = infcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeInference,
|
||||
span: self.value_span,
|
||||
});
|
||||
|
||||
// Ideally, we'd get the span where *this specific `ty` came
|
||||
// from*, but right now we just use the span from the overall
|
||||
// value being folded. In simple cases like `-> impl Foo`,
|
||||
// these are the same span, but not in cases like `-> (impl
|
||||
// Foo, impl Bar)`.
|
||||
let span = cause.span;
|
||||
let definition_span = self.value_span;
|
||||
|
||||
let mut obligations = vec![];
|
||||
let prev = self.inner.borrow_mut().opaque_types().register(
|
||||
OpaqueTypeKey { def_id, substs },
|
||||
OpaqueHiddenType { ty: hidden_ty, span },
|
||||
origin,
|
||||
);
|
||||
if let Some(prev) = prev {
|
||||
obligations = self.at(&cause, param_env).eq(prev, hidden_ty)?.obligations;
|
||||
{
|
||||
let mut infcx = self.infcx.inner.borrow_mut();
|
||||
infcx.opaque_types.insert(
|
||||
OpaqueTypeKey { def_id, substs },
|
||||
OpaqueTypeDecl { opaque_type: ty, definition_span, concrete_ty: ty_var, origin },
|
||||
);
|
||||
infcx.opaque_types_vars.insert(ty_var, ty);
|
||||
}
|
||||
|
||||
debug!("generated new type inference var {:?}", ty_var.kind());
|
||||
|
||||
let item_bounds = tcx.explicit_item_bounds(def_id);
|
||||
|
||||
self.obligations.reserve(item_bounds.len());
|
||||
for (predicate, _) in item_bounds {
|
||||
debug!(?predicate);
|
||||
let predicate = predicate.subst(tcx, substs);
|
||||
debug!(?predicate);
|
||||
|
||||
let predicate = predicate.fold_with(&mut BottomUpFolder {
|
||||
tcx,
|
||||
ty_op: |ty| match *ty.kind() {
|
||||
// We can't normalize associated types from `rustc_infer`,
|
||||
// but we can eagerly register inference variables for them.
|
||||
ty::Projection(projection_ty) if !projection_ty.has_escaping_bound_vars() => {
|
||||
self.infer_projection(
|
||||
param_env,
|
||||
projection_ty,
|
||||
cause.clone(),
|
||||
0,
|
||||
&mut obligations,
|
||||
)
|
||||
}
|
||||
// Replace all other mentions of the same opaque type with the hidden type,
|
||||
// as the bounds must hold on the hidden type after all.
|
||||
ty::Opaque(def_id2, substs2) if def_id == def_id2 && substs == substs2 => {
|
||||
hidden_ty
|
||||
ty_var
|
||||
}
|
||||
// Instantiate nested instances of `impl Trait`.
|
||||
ty::Opaque(..) => self.instantiate_opaque_types_in_map(ty),
|
||||
_ => ty,
|
||||
},
|
||||
lt_op: |lt| lt,
|
||||
ct_op: |ct| ct,
|
||||
});
|
||||
|
||||
// We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them.
|
||||
let predicate = predicate.fold_with(&mut BottomUpFolder {
|
||||
tcx,
|
||||
ty_op: |ty| match ty.kind() {
|
||||
ty::Projection(projection_ty) if !projection_ty.has_escaping_bound_vars() => {
|
||||
infcx.infer_projection(
|
||||
self.param_env,
|
||||
*projection_ty,
|
||||
traits::ObligationCause::misc(self.value_span, self.body_id),
|
||||
0,
|
||||
&mut self.obligations,
|
||||
)
|
||||
}
|
||||
_ => ty,
|
||||
},
|
||||
lt_op: |lt| lt,
|
||||
ct_op: |ct| ct,
|
||||
});
|
||||
debug!(?predicate);
|
||||
|
||||
if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
|
||||
if projection.term.references_error() {
|
||||
// No point on adding these obligations since there's a type error involved.
|
||||
return Ok(InferOk { value: (), obligations: vec![] });
|
||||
return tcx.ty_error();
|
||||
}
|
||||
trace!("{:#?}", projection.term);
|
||||
}
|
||||
|
||||
let cause =
|
||||
traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType);
|
||||
|
||||
// Require that the predicate holds for the concrete type.
|
||||
debug!(?predicate);
|
||||
obligations.push(traits::Obligation::new(cause.clone(), param_env, predicate));
|
||||
self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate));
|
||||
}
|
||||
Ok(InferOk { value: (), obligations })
|
||||
|
||||
ty_var
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
use rustc_data_structures::undo_log::UndoLogs;
|
||||
use rustc_hir::OpaqueTyOrigin;
|
||||
use rustc_middle::ty::{self, OpaqueTypeKey, Ty};
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
||||
use crate::infer::{InferCtxtUndoLogs, UndoLog};
|
||||
|
||||
use super::{OpaqueHiddenType, OpaqueTypeDecl, OpaqueTypeMap};
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct OpaqueTypeStorage<'tcx> {
|
||||
// Opaque types found in explicit return types and their
|
||||
// associated fresh inference variable. Writeback resolves these
|
||||
// variables to get the concrete type, which can be used to
|
||||
// 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions.
|
||||
pub opaque_types: OpaqueTypeMap<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> OpaqueTypeStorage<'tcx> {
|
||||
#[instrument(level = "debug")]
|
||||
pub(crate) fn remove(&mut self, key: OpaqueTypeKey<'tcx>, idx: Option<OpaqueHiddenType<'tcx>>) {
|
||||
if let Some(idx) = idx {
|
||||
self.opaque_types.get_mut(&key).unwrap().hidden_type = idx;
|
||||
} else {
|
||||
match self.opaque_types.remove(&key) {
|
||||
None => bug!("reverted opaque type inference that was never registered: {:?}", key),
|
||||
Some(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_decl(&self, key: &OpaqueTypeKey<'tcx>) -> Option<&OpaqueTypeDecl<'tcx>> {
|
||||
self.opaque_types.get(key)
|
||||
}
|
||||
|
||||
pub fn opaque_types(&self) -> OpaqueTypeMap<'tcx> {
|
||||
self.opaque_types.clone()
|
||||
}
|
||||
|
||||
#[instrument(level = "debug")]
|
||||
pub fn take_opaque_types(&mut self) -> OpaqueTypeMap<'tcx> {
|
||||
std::mem::take(&mut self.opaque_types)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn with_log<'a>(
|
||||
&'a mut self,
|
||||
undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
|
||||
) -> OpaqueTypeTable<'a, 'tcx> {
|
||||
OpaqueTypeTable { storage: self, undo_log }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Drop for OpaqueTypeStorage<'tcx> {
|
||||
fn drop(&mut self) {
|
||||
if !self.opaque_types.is_empty() {
|
||||
ty::tls::with(|tcx| {
|
||||
tcx.sess.delay_span_bug(DUMMY_SP, &format!("{:?}", self.opaque_types))
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OpaqueTypeTable<'a, 'tcx> {
|
||||
storage: &'a mut OpaqueTypeStorage<'tcx>,
|
||||
|
||||
undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub fn register(
|
||||
&mut self,
|
||||
key: OpaqueTypeKey<'tcx>,
|
||||
hidden_type: OpaqueHiddenType<'tcx>,
|
||||
origin: OpaqueTyOrigin,
|
||||
) -> Option<Ty<'tcx>> {
|
||||
if let Some(decl) = self.storage.opaque_types.get_mut(&key) {
|
||||
let prev = std::mem::replace(&mut decl.hidden_type, hidden_type);
|
||||
self.undo_log.push(UndoLog::OpaqueTypes(key, Some(prev)));
|
||||
return Some(prev.ty);
|
||||
}
|
||||
let decl = OpaqueTypeDecl { hidden_type, origin };
|
||||
self.storage.opaque_types.insert(key, decl);
|
||||
self.undo_log.push(UndoLog::OpaqueTypes(key, None));
|
||||
None
|
||||
}
|
||||
}
|
|
@ -28,7 +28,6 @@ pub fn explicit_outlives_bounds<'tcx>(
|
|||
| ty::PredicateKind::TypeOutlives(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::OpaqueType(..)
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
|
||||
ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
|
||||
Some(OutlivesBound::RegionSubRegion(r_b, r_a))
|
||||
|
|
|
@ -153,7 +153,6 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
|||
/// This function may have to perform normalizations, and hence it
|
||||
/// returns an `InferOk` with subobligations that must be
|
||||
/// processed.
|
||||
#[instrument(level = "debug", skip(self, region_bound_pairs_map))]
|
||||
pub fn process_registered_region_obligations(
|
||||
&self,
|
||||
region_bound_pairs_map: &FxHashMap<hir::HirId, RegionBoundPairs<'tcx>>,
|
||||
|
@ -165,6 +164,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
|||
"cannot process registered region obligations in a snapshot"
|
||||
);
|
||||
|
||||
debug!(?param_env, "process_registered_region_obligations()");
|
||||
|
||||
let my_region_obligations = self.take_registered_region_obligations();
|
||||
|
||||
for (body_id, RegionObligation { sup_type, sub_region, origin }) in my_region_obligations {
|
||||
|
|
|
@ -2,7 +2,6 @@ use super::combine::{CombineFields, RelationDir};
|
|||
use super::SubregionOrigin;
|
||||
|
||||
use crate::infer::combine::ConstEquateRelation;
|
||||
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use crate::traits::Obligation;
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
|
||||
|
@ -75,8 +74,9 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
debug!("{}.tys({:?}, {:?})", self.tag(), a, b);
|
||||
|
||||
if a == b {
|
||||
return Ok(a);
|
||||
}
|
||||
|
@ -84,7 +84,6 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
|
|||
let infcx = self.fields.infcx;
|
||||
let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a);
|
||||
let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b);
|
||||
|
||||
match (a.kind(), b.kind()) {
|
||||
(&ty::Infer(TyVar(_)), &ty::Infer(TyVar(_))) => {
|
||||
// Shouldn't have any LBR here, so we can safely put
|
||||
|
@ -122,40 +121,6 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
|
|||
Ok(self.tcx().ty_error())
|
||||
}
|
||||
|
||||
(&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
|
||||
self.fields.infcx.super_combine_tys(self, a, b)?;
|
||||
Ok(a)
|
||||
}
|
||||
(&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
|
||||
if self.fields.define_opaque_types && did.is_local() =>
|
||||
{
|
||||
let mut generalize = |ty, ty_is_expected| {
|
||||
let var = infcx.next_ty_var_id_in_universe(
|
||||
TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::MiscVariable,
|
||||
span: self.fields.trace.cause.span,
|
||||
},
|
||||
ty::UniverseIndex::ROOT,
|
||||
);
|
||||
self.fields.instantiate(ty, RelationDir::SubtypeOf, var, ty_is_expected)?;
|
||||
Ok(infcx.tcx.mk_ty_var(var))
|
||||
};
|
||||
let (a, b) = if self.a_is_expected { (a, b) } else { (b, a) };
|
||||
let (a, b) = match (a.kind(), b.kind()) {
|
||||
(&ty::Opaque(..), _) => (a, generalize(b, true)?),
|
||||
(_, &ty::Opaque(..)) => (generalize(a, false)?, b),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
self.fields.obligations.push(infcx.opaque_ty_obligation(
|
||||
a,
|
||||
b,
|
||||
true,
|
||||
self.param_env(),
|
||||
self.fields.trace.cause.clone(),
|
||||
));
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
_ => {
|
||||
self.fields.infcx.super_combine_tys(self, a, b)?;
|
||||
Ok(a)
|
||||
|
|
|
@ -4,15 +4,13 @@ use rustc_data_structures::snapshot_vec as sv;
|
|||
use rustc_data_structures::undo_log::{Rollback, UndoLogs};
|
||||
use rustc_data_structures::unify as ut;
|
||||
use rustc_middle::infer::unify_key::RegionVidKey;
|
||||
use rustc_middle::ty::{self, OpaqueTypeKey};
|
||||
use rustc_middle::ty;
|
||||
|
||||
use crate::{
|
||||
infer::{region_constraints, type_variable, InferCtxtInner},
|
||||
traits,
|
||||
};
|
||||
|
||||
use super::opaque_types::OpaqueHiddenType;
|
||||
|
||||
pub struct Snapshot<'tcx> {
|
||||
pub(crate) undo_len: usize,
|
||||
_marker: PhantomData<&'tcx ()>,
|
||||
|
@ -20,7 +18,6 @@ pub struct Snapshot<'tcx> {
|
|||
|
||||
/// Records the "undo" data for a single operation that affects some form of inference variable.
|
||||
pub(crate) enum UndoLog<'tcx> {
|
||||
OpaqueTypes(OpaqueTypeKey<'tcx>, Option<OpaqueHiddenType<'tcx>>),
|
||||
TypeVariables(type_variable::UndoLog<'tcx>),
|
||||
ConstUnificationTable(sv::UndoLog<ut::Delegate<ty::ConstVid<'tcx>>>),
|
||||
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
|
||||
|
@ -67,7 +64,6 @@ impl_from! {
|
|||
impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
|
||||
fn reverse(&mut self, undo: UndoLog<'tcx>) {
|
||||
match undo {
|
||||
UndoLog::OpaqueTypes(key, idx) => self.opaque_type_storage.remove(key, idx),
|
||||
UndoLog::TypeVariables(undo) => self.type_variable_storage.reverse(undo),
|
||||
UndoLog::ConstUnificationTable(undo) => self.const_unification_storage.reverse(undo),
|
||||
UndoLog::IntUnificationTable(undo) => self.int_unification_storage.reverse(undo),
|
||||
|
|
|
@ -167,9 +167,6 @@ impl<'tcx> Elaborator<'tcx> {
|
|||
// Currently, we do not elaborate WF predicates,
|
||||
// although we easily could.
|
||||
}
|
||||
ty::PredicateKind::OpaqueType(..) => {
|
||||
todo!("{:#?}", obligation)
|
||||
}
|
||||
ty::PredicateKind::ObjectSafe(..) => {
|
||||
// Currently, we do not elaborate object-safe
|
||||
// predicates.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue