Skip to content

Commit

Permalink
Try not to make obligations in handle_opaque_type
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Jun 11, 2024
1 parent 4efb13b commit e4be97c
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 91 deletions.
9 changes: 1 addition & 8 deletions compiler/rustc_borrowck/src/type_check/relate_tys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
"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, &cause, self.param_env())?
.obligations
.into_iter()
.map(Goal::from),
);
self.register_goals(infcx.handle_opaque_type(a, b, self.span(), self.param_env())?);
Ok(())
}

Expand Down
107 changes: 53 additions & 54 deletions compiler/rustc_infer/src/infer/opaque_types/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use super::{DefineOpaqueTypes, InferResult};
use crate::errors::OpaqueHiddenTypeDiag;
use crate::infer::{InferCtxt, InferOk};
use crate::traits::{self, PredicateObligation};
use crate::traits::{self, Obligation};
use hir::def_id::{DefId, LocalDefId};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::Lrc;
use rustc_hir as hir;
use rustc_middle::traits::solve::Goal;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::BottomUpFolder;
Expand All @@ -21,6 +21,8 @@ mod table;
pub type OpaqueTypeMap<'tcx> = FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>;
pub use table::{OpaqueTypeStorage, OpaqueTypeTable};

use super::DefineOpaqueTypes;

/// Information about the opaque types whose values we
/// are inferring in this function (these are the `impl Trait` that
/// appear in the return type).
Expand Down Expand Up @@ -62,11 +64,23 @@ impl<'tcx> InferCtxt<'tcx> {
{
let def_span = self.tcx.def_span(def_id);
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);
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
}
Expand All @@ -80,17 +94,17 @@ impl<'tcx> InferCtxt<'tcx> {
&self,
a: Ty<'tcx>,
b: Ty<'tcx>,
cause: &ObligationCause<'tcx>,
span: Span,
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() {
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => {
let def_id = def_id.expect_local();
if self.intercrate {
// See comment on `insert_hidden_type` for why this is sufficient in coherence
return Some(self.register_hidden_type(
OpaqueTypeKey { def_id, args },
cause.clone(),
span,
param_env,
b,
));
Expand Down Expand Up @@ -143,18 +157,13 @@ impl<'tcx> InferCtxt<'tcx> {
&& self.tcx.is_type_alias_impl_trait(b_def_id)
{
self.tcx.dcx().emit_err(OpaqueHiddenTypeDiag {
span: cause.span,
span,
hidden_type: self.tcx.def_span(b_def_id),
opaque_type: self.tcx.def_span(def_id),
});
}
}
Some(self.register_hidden_type(
OpaqueTypeKey { def_id, args },
cause.clone(),
param_env,
b,
))
Some(self.register_hidden_type(OpaqueTypeKey { def_id, args }, span, param_env, b))
}
_ => None,
};
Expand Down Expand Up @@ -464,24 +473,23 @@ impl<'tcx> InferCtxt<'tcx> {
fn register_hidden_type(
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
cause: ObligationCause<'tcx>,
span: Span,
param_env: ty::ParamEnv<'tcx>,
hidden_ty: Ty<'tcx>,
) -> InferResult<'tcx, ()> {
let mut obligations = Vec::new();
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, TypeError<'tcx>> {
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(
opaque_type_key.def_id.to_def_id(),
opaque_type_key.args,
cause,
param_env,
hidden_ty,
&mut obligations,
&mut goals,
);

Ok(InferOk { value: (), obligations })
Ok(goals)
}

/// Insert a hidden type into the opaque type storage, making sure
Expand All @@ -507,38 +515,35 @@ impl<'tcx> InferCtxt<'tcx> {
pub fn insert_hidden_type(
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
cause: &ObligationCause<'tcx>,
span: Span,
param_env: ty::ParamEnv<'tcx>,
hidden_ty: Ty<'tcx>,
obligations: &mut Vec<PredicateObligation<'tcx>>,
goals: &mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
) -> Result<(), TypeError<'tcx>> {
// 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;
if self.intercrate {
// During intercrate we do not define opaque types but instead always
// force ambiguity unless the hidden type is known to not implement
// our trait.
obligations.push(traits::Obligation::new(
self.tcx,
cause.clone(),
param_env,
ty::PredicateKind::Ambiguous,
))
goals.push(Goal::new(self.tcx, param_env, ty::PredicateKind::Ambiguous))
} else {
let prev = self
.inner
.borrow_mut()
.opaque_types()
.register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span });
if let Some(prev) = prev {
obligations.extend(
self.at(cause, param_env)
goals.extend(
self.at(&ObligationCause::dummy_with_span(span), param_env)
.eq(DefineOpaqueTypes::Yes, prev, hidden_ty)?
.obligations,
.obligations
.into_iter()
// FIXME: Shuttling between obligations and goals is awkward.
.map(Goal::from),
);
}
};
Expand All @@ -550,10 +555,9 @@ impl<'tcx> InferCtxt<'tcx> {
&self,
def_id: DefId,
args: ty::GenericArgsRef<'tcx>,
cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
hidden_ty: Ty<'tcx>,
obligations: &mut Vec<PredicateObligation<'tcx>>,
goals: &mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
) {
let tcx = self.tcx;
// Require that the hidden type is well-formed. We have to
Expand All @@ -567,12 +571,7 @@ impl<'tcx> InferCtxt<'tcx> {
// type during MIR borrowck, causing us to infer the wrong
// lifetime for its member constraints which then results in
// unexpected region errors.
obligations.push(traits::Obligation::new(
tcx,
cause.clone(),
param_env,
ty::ClauseKind::WellFormed(hidden_ty.into()),
));
goals.push(Goal::new(tcx, param_env, ty::ClauseKind::WellFormed(hidden_ty.into())));

let item_bounds = tcx.explicit_item_bounds(def_id);
for (predicate, _) in item_bounds.iter_instantiated_copied(tcx, args) {
Expand All @@ -588,13 +587,18 @@ impl<'tcx> InferCtxt<'tcx> {
&& !tcx.is_impl_trait_in_trait(projection_ty.def_id)
&& !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,
projection_ty,
cause.clone(),
0,
obligations,
)
ty::PredicateKind::Clause(ty::ClauseKind::Projection(
ty::ProjectionPredicate {
projection_term: projection_ty.into(),
term: ty_var.into(),
},
)),
));
ty_var
}
// Replace all other mentions of the same opaque type with the hidden type,
// as the bounds must hold on the hidden type after all.
Expand All @@ -611,12 +615,7 @@ impl<'tcx> InferCtxt<'tcx> {

// Require that the predicate holds for the concrete type.
debug!(?predicate);
obligations.push(traits::Obligation::new(
self.tcx,
cause.clone(),
param_env,
predicate,
));
goals.push(Goal::new(self.tcx, param_env, predicate));
}
}
}
11 changes: 6 additions & 5 deletions compiler/rustc_infer/src/infer/projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ impl<'tcx> InferCtxt<'tcx> {
obligations: &mut Vec<PredicateObligation<'tcx>>,
) -> Ty<'tcx> {
debug_assert!(!self.next_trait_solver());
let def_id = projection_ty.def_id;
let ty_var = self.next_ty_var(self.tcx.def_span(def_id));
let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Projection(
ty::ProjectionPredicate { projection_term: projection_ty.into(), term: ty_var.into() },
)));
let ty_var = self.next_ty_var(self.tcx.def_span(projection_ty.def_id));
let projection =
ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
projection_term: projection_ty.into(),
term: ty_var.into(),
}));
let obligation =
Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection);
obligations.push(obligation);
Expand Down
9 changes: 1 addition & 8 deletions compiler/rustc_infer/src/infer/relate/lattice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use super::combine::PredicateEmittingRelation;
use crate::infer::{DefineOpaqueTypes, InferCtxt};
use crate::traits::ObligationCause;

use rustc_middle::traits::solve::Goal;
use rustc_middle::ty::relate::RelateResult;
use rustc_middle::ty::TyVar;
use rustc_middle::ty::{self, Ty};
Expand Down Expand Up @@ -109,13 +108,7 @@ where
&& def_id.is_local()
&& !this.infcx().next_trait_solver() =>
{
this.register_goals(
infcx
.handle_opaque_type(a, b, this.cause(), this.param_env())?
.obligations
.into_iter()
.map(Goal::from),
);
this.register_goals(infcx.handle_opaque_type(a, b, this.span(), this.param_env())?);
Ok(a)
}

Expand Down
14 changes: 6 additions & 8 deletions compiler/rustc_infer/src/infer/relate/type_relating.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,12 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
&& def_id.is_local()
&& !infcx.next_trait_solver() =>
{
// FIXME: Don't shuttle between Goal and Obligation
self.fields.goals.extend(
infcx
.handle_opaque_type(a, b, &self.fields.trace.cause, self.param_env())?
.obligations
.into_iter()
.map(Goal::from),
);
self.fields.goals.extend(infcx.handle_opaque_type(
a,
b,
self.fields.trace.cause.span,
self.param_env(),
)?);
}

_ => {
Expand Down
15 changes: 7 additions & 8 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -961,15 +961,15 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
param_env: ty::ParamEnv<'tcx>,
hidden_ty: Ty<'tcx>,
) -> Result<(), NoSolution> {
let mut obligations = Vec::new();
let mut goals = Vec::new();
self.infcx.insert_hidden_type(
opaque_type_key,
&ObligationCause::dummy(),
DUMMY_SP,
param_env,
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(())
}

Expand All @@ -980,16 +980,15 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
param_env: ty::ParamEnv<'tcx>,
hidden_ty: Ty<'tcx>,
) {
let mut obligations = Vec::new();
let mut goals = Vec::new();
self.infcx.add_item_bounds_for_hidden_type(
opaque_def_id,
opaque_args,
ObligationCause::dummy(),
param_env,
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
Expand Down

0 comments on commit e4be97c

Please sign in to comment.