Auto merge of #122077 - oli-obk:eager_opaque_checks4, r=lcnr
Pass list of defineable opaque types into canonical queries This eliminates `DefiningAnchor::Bubble` for good and brings the old solver closer to the new one wrt cycles and nested obligations. At that point the difference between `DefiningAnchor::Bind([])` and `DefiningAnchor::Error` was academic. We only used the difference for some sanity checks, which actually had to be worked around in places, so I just removed `DefiningAnchor` entirely and just stored the list of opaques that may be defined. fixes #108498 fixes https://github.com/rust-lang/rust/issues/116877 * [x] run crater - https://github.com/rust-lang/rust/pull/122077#issuecomment-2013293931
This commit is contained in:
commit
b234e44944
59 changed files with 469 additions and 387 deletions
|
@ -1,5 +1,5 @@
|
|||
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
use crate::traits::{self, DefiningAnchor, ObligationCtxt, SelectionContext};
|
||||
use crate::traits::{self, ObligationCtxt, SelectionContext};
|
||||
|
||||
use crate::traits::TraitEngineExt as _;
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
@ -132,9 +132,8 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
|||
R: Debug + TypeFoldable<TyCtxt<'tcx>>,
|
||||
Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
|
||||
{
|
||||
let (infcx, key, canonical_inference_vars) = self
|
||||
.with_opaque_type_inference(DefiningAnchor::Bubble)
|
||||
.build_with_canonical(DUMMY_SP, canonical_key);
|
||||
let (infcx, key, canonical_inference_vars) =
|
||||
self.build_with_canonical(DUMMY_SP, canonical_key);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let value = operation(&ocx, key)?;
|
||||
ocx.make_canonicalized_query_response(canonical_inference_vars, value)
|
||||
|
|
|
@ -68,7 +68,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
&mut orig_values,
|
||||
QueryInput {
|
||||
goal,
|
||||
anchor: self.infcx.defining_use_anchor,
|
||||
predefined_opaques_in_body: self
|
||||
.tcx()
|
||||
.mk_predefined_opaques_in_body(PredefinedOpaquesData { opaque_types }),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::infer::at::ToTrace;
|
||||
use rustc_infer::infer::canonical::CanonicalVarValues;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
|
@ -230,7 +230,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
|||
.infer_ctxt()
|
||||
.intercrate(intercrate)
|
||||
.with_next_trait_solver(true)
|
||||
.with_opaque_type_inference(canonical_input.value.anchor)
|
||||
.build_with_canonical(DUMMY_SP, &canonical_input);
|
||||
|
||||
let mut ecx = EvalCtxt {
|
||||
|
@ -936,8 +935,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn can_define_opaque_ty(&self, def_id: LocalDefId) -> bool {
|
||||
self.infcx.opaque_type_origin(def_id).is_some()
|
||||
pub(super) fn can_define_opaque_ty(&self, def_id: impl Into<DefId>) -> bool {
|
||||
self.infcx.can_define_opaque_ty(def_id)
|
||||
}
|
||||
|
||||
pub(super) fn insert_hidden_type(
|
||||
|
|
|
@ -316,5 +316,6 @@ fn response_no_constraints_raw<'tcx>(
|
|||
external_constraints: tcx.mk_external_constraints(ExternalConstraintsData::default()),
|
||||
certainty,
|
||||
},
|
||||
defining_opaque_types: Default::default(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,10 +155,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
|||
if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
|
||||
if matches!(goal.param_env.reveal(), Reveal::All)
|
||||
|| matches!(ecx.solver_mode(), SolverMode::Coherence)
|
||||
|| opaque_ty
|
||||
.def_id
|
||||
.as_local()
|
||||
.is_some_and(|def_id| ecx.can_define_opaque_ty(def_id))
|
||||
|| ecx.can_define_opaque_ty(opaque_ty.def_id)
|
||||
{
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
|
|
@ -159,53 +159,70 @@ where
|
|||
.0);
|
||||
}
|
||||
|
||||
let mut error_info = None;
|
||||
let mut region_constraints = QueryRegionConstraints::default();
|
||||
let (output, error_info, mut obligations, _) =
|
||||
Q::fully_perform_into(self, infcx, &mut region_constraints, span).map_err(|_| {
|
||||
infcx.dcx().span_delayed_bug(span, format!("error performing {self:?}"))
|
||||
})?;
|
||||
|
||||
// Typically, instantiating NLL query results does not
|
||||
// create obligations. However, in some cases there
|
||||
// are unresolved type variables, and unify them *can*
|
||||
// create obligations. In that case, we have to go
|
||||
// fulfill them. We do this via a (recursive) query.
|
||||
while !obligations.is_empty() {
|
||||
trace!("{:#?}", obligations);
|
||||
let mut progress = false;
|
||||
for obligation in std::mem::take(&mut obligations) {
|
||||
let obligation = infcx.resolve_vars_if_possible(obligation);
|
||||
match ProvePredicate::fully_perform_into(
|
||||
obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
|
||||
infcx,
|
||||
&mut region_constraints,
|
||||
span,
|
||||
) {
|
||||
Ok(((), _, new, certainty)) => {
|
||||
obligations.extend(new);
|
||||
progress = true;
|
||||
if let Certainty::Ambiguous = certainty {
|
||||
obligations.push(obligation);
|
||||
// HACK(type_alias_impl_trait): When moving an opaque type to hidden type mapping from the query to the current inferctxt,
|
||||
// we sometimes end up with `Opaque<'a> = Opaque<'b>` instead of an actual hidden type. In that case we don't register a
|
||||
// hidden type but just equate the lifetimes. Thus we need to scrape the region constraints even though we're also manually
|
||||
// collecting region constraints via `region_constraints`.
|
||||
let (mut output, _) = scrape_region_constraints(
|
||||
infcx,
|
||||
|_ocx| {
|
||||
let (output, ei, mut obligations, _) =
|
||||
Q::fully_perform_into(self, infcx, &mut region_constraints, span)?;
|
||||
error_info = ei;
|
||||
|
||||
// Typically, instantiating NLL query results does not
|
||||
// create obligations. However, in some cases there
|
||||
// are unresolved type variables, and unify them *can*
|
||||
// create obligations. In that case, we have to go
|
||||
// fulfill them. We do this via a (recursive) query.
|
||||
while !obligations.is_empty() {
|
||||
trace!("{:#?}", obligations);
|
||||
let mut progress = false;
|
||||
for obligation in std::mem::take(&mut obligations) {
|
||||
let obligation = infcx.resolve_vars_if_possible(obligation);
|
||||
match ProvePredicate::fully_perform_into(
|
||||
obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
|
||||
infcx,
|
||||
&mut region_constraints,
|
||||
span,
|
||||
) {
|
||||
Ok(((), _, new, certainty)) => {
|
||||
obligations.extend(new);
|
||||
progress = true;
|
||||
if let Certainty::Ambiguous = certainty {
|
||||
obligations.push(obligation);
|
||||
}
|
||||
}
|
||||
Err(_) => obligations.push(obligation),
|
||||
}
|
||||
}
|
||||
Err(_) => obligations.push(obligation),
|
||||
if !progress {
|
||||
infcx.dcx().span_bug(
|
||||
span,
|
||||
format!("ambiguity processing {obligations:?} from {self:?}"),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if !progress {
|
||||
infcx
|
||||
.dcx()
|
||||
.span_bug(span, format!("ambiguity processing {obligations:?} from {self:?}"));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(TypeOpOutput {
|
||||
output,
|
||||
constraints: if region_constraints.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(infcx.tcx.arena.alloc(region_constraints))
|
||||
Ok(output)
|
||||
},
|
||||
error_info,
|
||||
})
|
||||
"fully_perform",
|
||||
span,
|
||||
)?;
|
||||
output.error_info = error_info;
|
||||
if let Some(constraints) = output.constraints {
|
||||
region_constraints
|
||||
.member_constraints
|
||||
.extend(constraints.member_constraints.iter().cloned());
|
||||
region_constraints.outlives.extend(constraints.outlives.iter().cloned());
|
||||
}
|
||||
output.constraints = if region_constraints.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(infcx.tcx.arena.alloc(region_constraints))
|
||||
};
|
||||
Ok(output)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue