Try not to make obligations in handle_opaque_type
This commit is contained in:
parent
4efb13b0c2
commit
e4be97cfe7
@ -154,14 +154,7 @@ fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>
|
|||||||
"expected at least one opaque type in `relate_opaques`, got {a} and {b}."
|
"expected at least one opaque type in `relate_opaques`, got {a} and {b}."
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let cause = ObligationCause::dummy_with_span(self.span());
|
self.register_goals(infcx.handle_opaque_type(a, b, self.span(), self.param_env())?);
|
||||||
self.register_goals(
|
|
||||||
infcx
|
|
||||||
.handle_opaque_type(a, b, &cause, self.param_env())?
|
|
||||||
.obligations
|
|
||||||
.into_iter()
|
|
||||||
.map(Goal::from),
|
|
||||||
);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use super::{DefineOpaqueTypes, InferResult};
|
|
||||||
use crate::errors::OpaqueHiddenTypeDiag;
|
use crate::errors::OpaqueHiddenTypeDiag;
|
||||||
use crate::infer::{InferCtxt, InferOk};
|
use crate::infer::{InferCtxt, InferOk};
|
||||||
use crate::traits::{self, PredicateObligation};
|
use crate::traits::{self, Obligation};
|
||||||
use hir::def_id::{DefId, LocalDefId};
|
use hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_middle::traits::solve::Goal;
|
||||||
use rustc_middle::traits::ObligationCause;
|
use rustc_middle::traits::ObligationCause;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::fold::BottomUpFolder;
|
use rustc_middle::ty::fold::BottomUpFolder;
|
||||||
@ -21,6 +21,8 @@
|
|||||||
pub type OpaqueTypeMap<'tcx> = FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>;
|
pub type OpaqueTypeMap<'tcx> = FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>;
|
||||||
pub use table::{OpaqueTypeStorage, OpaqueTypeTable};
|
pub use table::{OpaqueTypeStorage, OpaqueTypeTable};
|
||||||
|
|
||||||
|
use super::DefineOpaqueTypes;
|
||||||
|
|
||||||
/// Information about the opaque types whose values we
|
/// Information about the opaque types whose values we
|
||||||
/// are inferring in this function (these are the `impl Trait` that
|
/// are inferring in this function (these are the `impl Trait` that
|
||||||
/// appear in the return type).
|
/// appear in the return type).
|
||||||
@ -62,11 +64,23 @@ pub fn replace_opaque_types_with_inference_vars<T: TypeFoldable<TyCtxt<'tcx>>>(
|
|||||||
{
|
{
|
||||||
let def_span = self.tcx.def_span(def_id);
|
let def_span = self.tcx.def_span(def_id);
|
||||||
let span = if span.contains(def_span) { def_span } else { span };
|
let span = if span.contains(def_span) { def_span } else { span };
|
||||||
let code = traits::ObligationCauseCode::OpaqueReturnType(None);
|
|
||||||
let cause = ObligationCause::new(span, body_id, code);
|
|
||||||
let ty_var = self.next_ty_var(span);
|
let ty_var = self.next_ty_var(span);
|
||||||
obligations.extend(
|
obligations.extend(
|
||||||
self.handle_opaque_type(ty, ty_var, &cause, param_env).unwrap().obligations,
|
self.handle_opaque_type(ty, ty_var, span, param_env)
|
||||||
|
.unwrap()
|
||||||
|
.into_iter()
|
||||||
|
.map(|goal| {
|
||||||
|
Obligation::new(
|
||||||
|
self.tcx,
|
||||||
|
ObligationCause::new(
|
||||||
|
span,
|
||||||
|
body_id,
|
||||||
|
traits::ObligationCauseCode::OpaqueReturnType(None),
|
||||||
|
),
|
||||||
|
goal.param_env,
|
||||||
|
goal.predicate,
|
||||||
|
)
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
ty_var
|
ty_var
|
||||||
}
|
}
|
||||||
@ -80,9 +94,9 @@ pub fn handle_opaque_type(
|
|||||||
&self,
|
&self,
|
||||||
a: Ty<'tcx>,
|
a: Ty<'tcx>,
|
||||||
b: Ty<'tcx>,
|
b: Ty<'tcx>,
|
||||||
cause: &ObligationCause<'tcx>,
|
span: Span,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> InferResult<'tcx, ()> {
|
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, TypeError<'tcx>> {
|
||||||
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
|
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
|
||||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => {
|
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => {
|
||||||
let def_id = def_id.expect_local();
|
let def_id = def_id.expect_local();
|
||||||
@ -90,7 +104,7 @@ pub fn handle_opaque_type(
|
|||||||
// See comment on `insert_hidden_type` for why this is sufficient in coherence
|
// See comment on `insert_hidden_type` for why this is sufficient in coherence
|
||||||
return Some(self.register_hidden_type(
|
return Some(self.register_hidden_type(
|
||||||
OpaqueTypeKey { def_id, args },
|
OpaqueTypeKey { def_id, args },
|
||||||
cause.clone(),
|
span,
|
||||||
param_env,
|
param_env,
|
||||||
b,
|
b,
|
||||||
));
|
));
|
||||||
@ -143,18 +157,13 @@ pub fn handle_opaque_type(
|
|||||||
&& self.tcx.is_type_alias_impl_trait(b_def_id)
|
&& self.tcx.is_type_alias_impl_trait(b_def_id)
|
||||||
{
|
{
|
||||||
self.tcx.dcx().emit_err(OpaqueHiddenTypeDiag {
|
self.tcx.dcx().emit_err(OpaqueHiddenTypeDiag {
|
||||||
span: cause.span,
|
span,
|
||||||
hidden_type: self.tcx.def_span(b_def_id),
|
hidden_type: self.tcx.def_span(b_def_id),
|
||||||
opaque_type: self.tcx.def_span(def_id),
|
opaque_type: self.tcx.def_span(def_id),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(self.register_hidden_type(
|
Some(self.register_hidden_type(OpaqueTypeKey { def_id, args }, span, param_env, b))
|
||||||
OpaqueTypeKey { def_id, args },
|
|
||||||
cause.clone(),
|
|
||||||
param_env,
|
|
||||||
b,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
@ -464,24 +473,23 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
fn register_hidden_type(
|
fn register_hidden_type(
|
||||||
&self,
|
&self,
|
||||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||||
cause: ObligationCause<'tcx>,
|
span: Span,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
hidden_ty: Ty<'tcx>,
|
hidden_ty: Ty<'tcx>,
|
||||||
) -> InferResult<'tcx, ()> {
|
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, TypeError<'tcx>> {
|
||||||
let mut obligations = Vec::new();
|
let mut goals = Vec::new();
|
||||||
|
|
||||||
self.insert_hidden_type(opaque_type_key, &cause, param_env, hidden_ty, &mut obligations)?;
|
self.insert_hidden_type(opaque_type_key, span, param_env, hidden_ty, &mut goals)?;
|
||||||
|
|
||||||
self.add_item_bounds_for_hidden_type(
|
self.add_item_bounds_for_hidden_type(
|
||||||
opaque_type_key.def_id.to_def_id(),
|
opaque_type_key.def_id.to_def_id(),
|
||||||
opaque_type_key.args,
|
opaque_type_key.args,
|
||||||
cause,
|
|
||||||
param_env,
|
param_env,
|
||||||
hidden_ty,
|
hidden_ty,
|
||||||
&mut obligations,
|
&mut goals,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(InferOk { value: (), obligations })
|
Ok(goals)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a hidden type into the opaque type storage, making sure
|
/// Insert a hidden type into the opaque type storage, making sure
|
||||||
@ -507,27 +515,21 @@ pub fn inject_new_hidden_type_unchecked(
|
|||||||
pub fn insert_hidden_type(
|
pub fn insert_hidden_type(
|
||||||
&self,
|
&self,
|
||||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||||
cause: &ObligationCause<'tcx>,
|
span: Span,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
hidden_ty: Ty<'tcx>,
|
hidden_ty: Ty<'tcx>,
|
||||||
obligations: &mut Vec<PredicateObligation<'tcx>>,
|
goals: &mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
|
||||||
) -> Result<(), TypeError<'tcx>> {
|
) -> Result<(), TypeError<'tcx>> {
|
||||||
// Ideally, we'd get the span where *this specific `ty` came
|
// Ideally, we'd get the span where *this specific `ty` came
|
||||||
// from*, but right now we just use the span from the overall
|
// from*, but right now we just use the span from the overall
|
||||||
// value being folded. In simple cases like `-> impl Foo`,
|
// value being folded. In simple cases like `-> impl Foo`,
|
||||||
// these are the same span, but not in cases like `-> (impl
|
// these are the same span, but not in cases like `-> (impl
|
||||||
// Foo, impl Bar)`.
|
// Foo, impl Bar)`.
|
||||||
let span = cause.span;
|
|
||||||
if self.intercrate {
|
if self.intercrate {
|
||||||
// During intercrate we do not define opaque types but instead always
|
// During intercrate we do not define opaque types but instead always
|
||||||
// force ambiguity unless the hidden type is known to not implement
|
// force ambiguity unless the hidden type is known to not implement
|
||||||
// our trait.
|
// our trait.
|
||||||
obligations.push(traits::Obligation::new(
|
goals.push(Goal::new(self.tcx, param_env, ty::PredicateKind::Ambiguous))
|
||||||
self.tcx,
|
|
||||||
cause.clone(),
|
|
||||||
param_env,
|
|
||||||
ty::PredicateKind::Ambiguous,
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
let prev = self
|
let prev = self
|
||||||
.inner
|
.inner
|
||||||
@ -535,10 +537,13 @@ pub fn insert_hidden_type(
|
|||||||
.opaque_types()
|
.opaque_types()
|
||||||
.register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span });
|
.register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span });
|
||||||
if let Some(prev) = prev {
|
if let Some(prev) = prev {
|
||||||
obligations.extend(
|
goals.extend(
|
||||||
self.at(cause, param_env)
|
self.at(&ObligationCause::dummy_with_span(span), param_env)
|
||||||
.eq(DefineOpaqueTypes::Yes, prev, hidden_ty)?
|
.eq(DefineOpaqueTypes::Yes, prev, hidden_ty)?
|
||||||
.obligations,
|
.obligations
|
||||||
|
.into_iter()
|
||||||
|
// FIXME: Shuttling between obligations and goals is awkward.
|
||||||
|
.map(Goal::from),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -550,10 +555,9 @@ pub fn add_item_bounds_for_hidden_type(
|
|||||||
&self,
|
&self,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
args: ty::GenericArgsRef<'tcx>,
|
args: ty::GenericArgsRef<'tcx>,
|
||||||
cause: ObligationCause<'tcx>,
|
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
hidden_ty: Ty<'tcx>,
|
hidden_ty: Ty<'tcx>,
|
||||||
obligations: &mut Vec<PredicateObligation<'tcx>>,
|
goals: &mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
|
||||||
) {
|
) {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
// Require that the hidden type is well-formed. We have to
|
// Require that the hidden type is well-formed. We have to
|
||||||
@ -567,12 +571,7 @@ pub fn add_item_bounds_for_hidden_type(
|
|||||||
// type during MIR borrowck, causing us to infer the wrong
|
// type during MIR borrowck, causing us to infer the wrong
|
||||||
// lifetime for its member constraints which then results in
|
// lifetime for its member constraints which then results in
|
||||||
// unexpected region errors.
|
// unexpected region errors.
|
||||||
obligations.push(traits::Obligation::new(
|
goals.push(Goal::new(tcx, param_env, ty::ClauseKind::WellFormed(hidden_ty.into())));
|
||||||
tcx,
|
|
||||||
cause.clone(),
|
|
||||||
param_env,
|
|
||||||
ty::ClauseKind::WellFormed(hidden_ty.into()),
|
|
||||||
));
|
|
||||||
|
|
||||||
let item_bounds = tcx.explicit_item_bounds(def_id);
|
let item_bounds = tcx.explicit_item_bounds(def_id);
|
||||||
for (predicate, _) in item_bounds.iter_instantiated_copied(tcx, args) {
|
for (predicate, _) in item_bounds.iter_instantiated_copied(tcx, args) {
|
||||||
@ -588,13 +587,18 @@ pub fn add_item_bounds_for_hidden_type(
|
|||||||
&& !tcx.is_impl_trait_in_trait(projection_ty.def_id)
|
&& !tcx.is_impl_trait_in_trait(projection_ty.def_id)
|
||||||
&& !self.next_trait_solver() =>
|
&& !self.next_trait_solver() =>
|
||||||
{
|
{
|
||||||
self.projection_ty_to_infer(
|
let ty_var = self.next_ty_var(self.tcx.def_span(projection_ty.def_id));
|
||||||
|
goals.push(Goal::new(
|
||||||
|
self.tcx,
|
||||||
param_env,
|
param_env,
|
||||||
projection_ty,
|
ty::PredicateKind::Clause(ty::ClauseKind::Projection(
|
||||||
cause.clone(),
|
ty::ProjectionPredicate {
|
||||||
0,
|
projection_term: projection_ty.into(),
|
||||||
obligations,
|
term: ty_var.into(),
|
||||||
)
|
},
|
||||||
|
)),
|
||||||
|
));
|
||||||
|
ty_var
|
||||||
}
|
}
|
||||||
// Replace all other mentions of the same opaque type with the hidden type,
|
// Replace all other mentions of the same opaque type with the hidden type,
|
||||||
// as the bounds must hold on the hidden type after all.
|
// as the bounds must hold on the hidden type after all.
|
||||||
@ -611,12 +615,7 @@ pub fn add_item_bounds_for_hidden_type(
|
|||||||
|
|
||||||
// Require that the predicate holds for the concrete type.
|
// Require that the predicate holds for the concrete type.
|
||||||
debug!(?predicate);
|
debug!(?predicate);
|
||||||
obligations.push(traits::Obligation::new(
|
goals.push(Goal::new(self.tcx, param_env, predicate));
|
||||||
self.tcx,
|
|
||||||
cause.clone(),
|
|
||||||
param_env,
|
|
||||||
predicate,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,11 +21,12 @@ pub fn projection_ty_to_infer(
|
|||||||
obligations: &mut Vec<PredicateObligation<'tcx>>,
|
obligations: &mut Vec<PredicateObligation<'tcx>>,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
debug_assert!(!self.next_trait_solver());
|
debug_assert!(!self.next_trait_solver());
|
||||||
let def_id = projection_ty.def_id;
|
let ty_var = self.next_ty_var(self.tcx.def_span(projection_ty.def_id));
|
||||||
let ty_var = self.next_ty_var(self.tcx.def_span(def_id));
|
let projection =
|
||||||
let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Projection(
|
ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
|
||||||
ty::ProjectionPredicate { projection_term: projection_ty.into(), term: ty_var.into() },
|
projection_term: projection_ty.into(),
|
||||||
)));
|
term: ty_var.into(),
|
||||||
|
}));
|
||||||
let obligation =
|
let obligation =
|
||||||
Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection);
|
Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection);
|
||||||
obligations.push(obligation);
|
obligations.push(obligation);
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
use crate::infer::{DefineOpaqueTypes, InferCtxt};
|
use crate::infer::{DefineOpaqueTypes, InferCtxt};
|
||||||
use crate::traits::ObligationCause;
|
use crate::traits::ObligationCause;
|
||||||
|
|
||||||
use rustc_middle::traits::solve::Goal;
|
|
||||||
use rustc_middle::ty::relate::RelateResult;
|
use rustc_middle::ty::relate::RelateResult;
|
||||||
use rustc_middle::ty::TyVar;
|
use rustc_middle::ty::TyVar;
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
@ -109,13 +108,7 @@ pub fn super_lattice_tys<'a, 'tcx: 'a, L>(
|
|||||||
&& def_id.is_local()
|
&& def_id.is_local()
|
||||||
&& !this.infcx().next_trait_solver() =>
|
&& !this.infcx().next_trait_solver() =>
|
||||||
{
|
{
|
||||||
this.register_goals(
|
this.register_goals(infcx.handle_opaque_type(a, b, this.span(), this.param_env())?);
|
||||||
infcx
|
|
||||||
.handle_opaque_type(a, b, this.cause(), this.param_env())?
|
|
||||||
.obligations
|
|
||||||
.into_iter()
|
|
||||||
.map(Goal::from),
|
|
||||||
);
|
|
||||||
Ok(a)
|
Ok(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,14 +150,12 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
|||||||
&& def_id.is_local()
|
&& def_id.is_local()
|
||||||
&& !infcx.next_trait_solver() =>
|
&& !infcx.next_trait_solver() =>
|
||||||
{
|
{
|
||||||
// FIXME: Don't shuttle between Goal and Obligation
|
self.fields.goals.extend(infcx.handle_opaque_type(
|
||||||
self.fields.goals.extend(
|
a,
|
||||||
infcx
|
b,
|
||||||
.handle_opaque_type(a, b, &self.fields.trace.cause, self.param_env())?
|
self.fields.trace.cause.span,
|
||||||
.obligations
|
self.param_env(),
|
||||||
.into_iter()
|
)?);
|
||||||
.map(Goal::from),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -961,15 +961,15 @@ pub(super) fn insert_hidden_type(
|
|||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
hidden_ty: Ty<'tcx>,
|
hidden_ty: Ty<'tcx>,
|
||||||
) -> Result<(), NoSolution> {
|
) -> Result<(), NoSolution> {
|
||||||
let mut obligations = Vec::new();
|
let mut goals = Vec::new();
|
||||||
self.infcx.insert_hidden_type(
|
self.infcx.insert_hidden_type(
|
||||||
opaque_type_key,
|
opaque_type_key,
|
||||||
&ObligationCause::dummy(),
|
DUMMY_SP,
|
||||||
param_env,
|
param_env,
|
||||||
hidden_ty,
|
hidden_ty,
|
||||||
&mut obligations,
|
&mut goals,
|
||||||
)?;
|
)?;
|
||||||
self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into()));
|
self.add_goals(GoalSource::Misc, goals);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -980,16 +980,15 @@ pub(super) fn add_item_bounds_for_hidden_type(
|
|||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
hidden_ty: Ty<'tcx>,
|
hidden_ty: Ty<'tcx>,
|
||||||
) {
|
) {
|
||||||
let mut obligations = Vec::new();
|
let mut goals = Vec::new();
|
||||||
self.infcx.add_item_bounds_for_hidden_type(
|
self.infcx.add_item_bounds_for_hidden_type(
|
||||||
opaque_def_id,
|
opaque_def_id,
|
||||||
opaque_args,
|
opaque_args,
|
||||||
ObligationCause::dummy(),
|
|
||||||
param_env,
|
param_env,
|
||||||
hidden_ty,
|
hidden_ty,
|
||||||
&mut obligations,
|
&mut goals,
|
||||||
);
|
);
|
||||||
self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into()));
|
self.add_goals(GoalSource::Misc, goals);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do something for each opaque/hidden pair defined with `def_id` in the
|
// Do something for each opaque/hidden pair defined with `def_id` in the
|
||||||
|
Loading…
Reference in New Issue
Block a user