Remove opaque type obligation and just register opaque types as they are encountered.
This also registers obligations for the hidden type immediately.
This commit is contained in:
parent
86e1860495
commit
1163aa7e72
60 changed files with 290 additions and 311 deletions
|
@ -22,6 +22,7 @@ use rustc_data_structures::captures::Captures;
|
|||
use rustc_index::vec::Idx;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_middle::arena::ArenaAllocatable;
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::relate::TypeRelation;
|
||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
|
||||
|
@ -499,7 +500,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
|||
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);
|
||||
obligations.extend(self.handle_opaque_type(a, b, true, cause, param_env)?.obligations);
|
||||
}
|
||||
|
||||
Ok(InferOk { value: result_subst, obligations })
|
||||
|
@ -718,13 +719,17 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
|
|||
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(),
|
||||
));
|
||||
fn register_opaque_type(
|
||||
&mut self,
|
||||
a: Ty<'tcx>,
|
||||
b: Ty<'tcx>,
|
||||
a_is_expected: bool,
|
||||
) -> Result<(), TypeError<'tcx>> {
|
||||
self.obligations.extend(
|
||||
self.infcx
|
||||
.handle_opaque_type(a, b, a_is_expected, &self.cause, self.param_env)?
|
||||
.obligations,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,13 +98,17 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
|
|||
(&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.obligations.extend(
|
||||
infcx
|
||||
.handle_opaque_type(
|
||||
a,
|
||||
b,
|
||||
self.a_is_expected(),
|
||||
&self.fields.trace.cause,
|
||||
self.param_env(),
|
||||
)?
|
||||
.obligations,
|
||||
);
|
||||
}
|
||||
|
||||
_ => {
|
||||
|
|
|
@ -111,13 +111,11 @@ where
|
|||
(&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(),
|
||||
)]);
|
||||
this.add_obligations(
|
||||
infcx
|
||||
.handle_opaque_type(a, b, this.a_is_expected(), this.cause(), this.param_env())?
|
||||
.obligations,
|
||||
);
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,12 @@ pub trait TypeRelatingDelegate<'tcx> {
|
|||
);
|
||||
|
||||
fn const_equate(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>);
|
||||
fn register_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool);
|
||||
fn register_opaque_type(
|
||||
&mut self,
|
||||
a: Ty<'tcx>,
|
||||
b: Ty<'tcx>,
|
||||
a_is_expected: bool,
|
||||
) -> Result<(), TypeError<'tcx>>;
|
||||
|
||||
/// Creates a new universe index. Used when instantiating placeholders.
|
||||
fn create_next_universe(&mut self) -> ty::UniverseIndex;
|
||||
|
@ -590,7 +595,7 @@ where
|
|||
(_, &ty::Opaque(..)) => (generalize(a, true)?, b),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
self.delegate.register_opaque_type(a, b, true);
|
||||
self.delegate.register_opaque_type(a, b, true)?;
|
||||
trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
|
||||
Ok(a)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::infer::{InferCtxt, InferOk};
|
||||
use crate::traits::{self, PredicateObligation};
|
||||
use crate::traits;
|
||||
use hir::def_id::{DefId, LocalDefId};
|
||||
use hir::OpaqueTyOrigin;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
|
@ -42,25 +42,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
&self,
|
||||
a: Ty<'tcx>,
|
||||
b: Ty<'tcx>,
|
||||
a_is_expected: bool,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
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
|
||||
let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
|
||||
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,
|
||||
|
@ -76,13 +76,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
"opaque type being used as hidden type",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
Some(self.register_hidden_type(
|
||||
OpaqueTypeKey { def_id, substs },
|
||||
cause.clone(),
|
||||
param_env,
|
||||
b,
|
||||
}
|
||||
Some(self.register_hidden_type(
|
||||
OpaqueTypeKey { def_id, substs },
|
||||
cause.clone(),
|
||||
param_env,
|
||||
b,
|
||||
if self.defining_use_anchor.is_some() {
|
||||
// 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
|
||||
|
@ -117,47 +118,28 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
// 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.kind(), b.kind())
|
||||
),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
self.opaque_type_origin(def_id, cause.span)?
|
||||
} else {
|
||||
self.opaque_ty_origin_unchecked(def_id, cause.span)
|
||||
},
|
||||
))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
if let Some(res) = process(a, b) {
|
||||
res
|
||||
} else if let Some(res) = process(b, a) {
|
||||
res
|
||||
} else {
|
||||
let (opaque_type, hidden_ty) = match (a.kind(), b.kind()) {
|
||||
(ty::Opaque(..), _) => (a, b),
|
||||
(_, ty::Opaque(..)) => (b, a),
|
||||
types => span_bug!(
|
||||
// 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 type obligations only work for opaque types: {:#?}",
|
||||
types
|
||||
"opaque types are never equal to anything but themselves: {:#?}",
|
||||
(a.kind(), b.kind())
|
||||
),
|
||||
};
|
||||
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![] }),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -363,22 +345,6 @@ 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()?;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -146,13 +146,11 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
|
|||
(_, &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(),
|
||||
));
|
||||
self.fields.obligations.extend(
|
||||
infcx
|
||||
.handle_opaque_type(a, b, true, &self.fields.trace.cause, self.param_env())?
|
||||
.obligations,
|
||||
);
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
|
|
|
@ -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