support calls on opaque types :<

This commit is contained in:
lcnr
2025-09-11 13:08:36 +02:00
parent d1ed52b1f5
commit f4e19c6878
28 changed files with 734 additions and 124 deletions

View File

@@ -204,7 +204,7 @@ where
//
// Only goals proven via the trait solver should be region dependent.
Certainty::Yes => {}
Certainty::Maybe(_) => {
Certainty::Maybe { .. } => {
self.obligations.register(obligation, None);
}
}
@@ -258,7 +258,7 @@ where
infcx.push_hir_typeck_potentially_region_dependent_goal(obligation);
}
}
Certainty::Maybe(_) => self.obligations.register(obligation, stalled_on),
Certainty::Maybe { .. } => self.obligations.register(obligation, stalled_on),
}
}

View File

@@ -95,15 +95,17 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>(
root_obligation.cause.span,
None,
) {
Ok(GoalEvaluation { certainty: Certainty::Maybe(MaybeCause::Ambiguity), .. }) => {
(FulfillmentErrorCode::Ambiguity { overflow: None }, true)
}
Ok(GoalEvaluation {
certainty: Certainty::Maybe { cause: MaybeCause::Ambiguity, .. },
..
}) => (FulfillmentErrorCode::Ambiguity { overflow: None }, true),
Ok(GoalEvaluation {
certainty:
Certainty::Maybe(MaybeCause::Overflow {
suggest_increasing_limit,
keep_constraints: _,
}),
Certainty::Maybe {
cause:
MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: _ },
..
},
..
}) => (
FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) },
@@ -266,7 +268,8 @@ impl<'tcx> BestObligation<'tcx> {
);
// Skip nested goals that aren't the *reason* for our goal's failure.
match (self.consider_ambiguities, nested_goal.result()) {
(true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) | (false, Err(_)) => {}
(true, Ok(Certainty::Maybe { cause: MaybeCause::Ambiguity, .. }))
| (false, Err(_)) => {}
_ => continue,
}
@@ -407,7 +410,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
let tcx = goal.infcx().tcx;
// Skip goals that aren't the *reason* for our goal's failure.
match (self.consider_ambiguities, goal.result()) {
(true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) | (false, Err(_)) => {}
(true, Ok(Certainty::Maybe { cause: MaybeCause::Ambiguity, .. })) | (false, Err(_)) => {
}
_ => return ControlFlow::Continue(()),
}

View File

@@ -332,7 +332,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => {
assert_matches!(
shallow_certainty.replace(c),
None | Some(Certainty::Maybe(MaybeCause::Ambiguity))
None | Some(Certainty::Maybe { cause: MaybeCause::Ambiguity, .. })
);
}
inspect::ProbeStep::NestedProbe(ref probe) => {

View File

@@ -62,7 +62,7 @@ impl<'tcx> inspect::ProofTreeVisitor<'tcx> for Select {
// Don't winnow until `Certainty::Yes` -- we don't need to winnow until
// codegen, and only on the good path.
if matches!(goal.result().unwrap(), Certainty::Maybe(..)) {
if matches!(goal.result().unwrap(), Certainty::Maybe { .. }) {
return ControlFlow::Break(Ok(None));
}
@@ -95,7 +95,7 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>(
) -> bool {
// Don't winnow until `Certainty::Yes` -- we don't need to winnow until
// codegen, and only on the good path.
if matches!(other.result().unwrap(), Certainty::Maybe(..)) {
if matches!(other.result().unwrap(), Certainty::Maybe { .. }) {
return false;
}
@@ -143,13 +143,13 @@ fn to_selection<'tcx>(
span: Span,
cand: inspect::InspectCandidate<'_, 'tcx>,
) -> Option<Selection<'tcx>> {
if let Certainty::Maybe(..) = cand.shallow_certainty() {
if let Certainty::Maybe { .. } = cand.shallow_certainty() {
return None;
}
let nested = match cand.result().expect("expected positive result") {
Certainty::Yes => thin_vec![],
Certainty::Maybe(_) => cand
Certainty::Maybe { .. } => cand
.instantiate_nested_goals(span)
.into_iter()
.map(|nested| {

View File

@@ -682,7 +682,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
// was irrelevant.
match goal.result() {
Ok(Certainty::Yes) | Err(NoSolution) => return,
Ok(Certainty::Maybe(_)) => {}
Ok(Certainty::Maybe { .. }) => {}
}
// For bound predicates we simply call `infcx.enter_forall`

View File

@@ -1,8 +1,11 @@
use rustc_infer::traits::solve::Goal;
use rustc_macros::extension;
use rustc_middle::span_bug;
use rustc_next_trait_solver::solve::SolverDelegateEvalExt;
use crate::infer::InferCtxt;
use crate::infer::canonical::OriginalQueryValues;
use crate::solve::SolverDelegate;
use crate::traits::{
EvaluationResult, ObligationCtxt, OverflowError, PredicateObligation, SelectionContext,
};
@@ -15,6 +18,20 @@ impl<'tcx> InferCtxt<'tcx> {
self.evaluate_obligation_no_overflow(obligation).may_apply()
}
/// See the comment on [OpaqueTypesJank](crate::solve::OpaqueTypesJank)
/// for more details.
fn predicate_may_hold_opaque_types_jank(&self, obligation: &PredicateObligation<'tcx>) -> bool {
if self.next_trait_solver() {
<&SolverDelegate<'tcx>>::from(self).root_goal_may_hold_opaque_types_jank(Goal::new(
self.tcx,
obligation.param_env,
obligation.predicate,
))
} else {
self.predicate_may_hold(obligation)
}
}
/// Evaluates whether the predicate can be satisfied in the given
/// `ParamEnv`, and returns `false` if not certain. However, this is
/// not entirely accurate if inference variables are involved.