Skip to content

FIXME(-Znext-solver) triage #141763

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,11 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
}

if !tcx.recursion_limit().value_within_limit(iteration) {
// This may actually be reachable. If so, we should convert
// this to a proper error/consider whether we should detect
// this somewhere else.
bug!(
"FIXME(-Znext-solver): Overflowed when processing region obligations: {outlives_predicates:#?}"
"unexpected overflowed when processing region obligations: {outlives_predicates:#?}"
);
}

Expand Down
16 changes: 8 additions & 8 deletions compiler/rustc_hir_analysis/src/autoderef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
self.param_env,
ty::Binder::dummy(trait_ref),
);
if !self.infcx.predicate_may_hold(&obligation) {
if !self.infcx.next_trait_solver() && !self.infcx.predicate_may_hold(&obligation) {
debug!("overloaded_deref_ty: cannot match obligation");
return None;
}
Expand All @@ -184,17 +184,17 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
self.param_env,
ty,
) else {
// We shouldn't have errors here, except for evaluate/fulfill mismatches,
// but that's not a reason for an ICE (`predicate_may_hold` is conservative
// by design).
// FIXME(-Znext-solver): This *actually* shouldn't happen then.
// We shouldn't have errors here in the old solver, except for
// evaluate/fulfill mismatches, but that's not a reason for an ICE.
return None;
};
let errors = ocx.select_where_possible();
if !errors.is_empty() {
// This shouldn't happen, except for evaluate/fulfill mismatches,
// but that's not a reason for an ICE (`predicate_may_hold` is conservative
// by design).
if self.infcx.next_trait_solver() {
unreachable!();
}
// We shouldn't have errors here in the old solver, except for
// evaluate/fulfill mismatches, but that's not a reason for an ICE.
debug!(?errors, "encountered errors while fulfilling");
return None;
}
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity })
});
let bound = (bound.upcast(tcx), span);
// FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands.
// FIXME(-Znext-solver): We can likely remove this hack once the
// new trait solver lands. This fixed an overflow in the old solver.
// This may have performance implications, so please check perf when
// removing it.
// This was added in <https://github.com/rust-lang/rust/pull/123302>.
if tcx.is_lang_item(trait_def_id, rustc_hir::LangItem::Sized) {
bounds.insert(0, bound);
} else {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (def_id, args) = match *expected_ty.kind() {
// FIXME: Could also check that the RPIT is not defined
ty::Alias(ty::Opaque, alias_ty) => (alias_ty.def_id.as_local()?, alias_ty.args),
// FIXME(-Znext-solver): Remove this branch once `replace_opaque_types_with_infer` is gone.
// FIXME(-Znext-solver=no): Remove this branch once `replace_opaque_types_with_infer` is gone.
ty::Infer(ty::TyVar(_)) => self
.inner
.borrow_mut()
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
allow_two_phase: AllowTwoPhase,
) -> Result<Ty<'tcx>, Diag<'a>> {
let expected = self.resolve_vars_with_obligations(expected);
let expected = if self.next_trait_solver() {
expected
} else {
self.resolve_vars_with_obligations(expected)
};

let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
Ok(ty) => return Ok(ty),
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1436,8 +1436,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// in this case.
#[instrument(level = "debug", skip(self, sp), ret)]
pub(crate) fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
let ty = self.resolve_vars_with_obligations(ty);

if self.next_trait_solver()
&& let ty::Alias(..) = ty.kind()
{
Expand All @@ -1455,7 +1453,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
} else {
ty
self.resolve_vars_with_obligations(ty)
}
}

Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,9 +412,10 @@ pub(crate) struct LoweredTy<'tcx> {

impl<'tcx> LoweredTy<'tcx> {
fn from_raw(fcx: &FnCtxt<'_, 'tcx>, span: Span, raw: Ty<'tcx>) -> LoweredTy<'tcx> {
// FIXME(-Znext-solver): We're still figuring out how to best handle
// normalization and this doesn't feel too great. We should look at this
// code again before stabilizing it.
// FIXME(-Znext-solver=no): This is easier than requiring all uses of `LoweredTy`
// to call `try_structurally_resolve_type` instead. This seems like a lot of
// effort, especially as we're still supporting the old solver. We may revisit
// this in the future.
let normalized = if fcx.next_trait_solver() {
fcx.try_structurally_resolve_type(span, raw)
} else {
Expand Down
15 changes: 7 additions & 8 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1913,8 +1913,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
ty::Binder::dummy(trait_ref),
);

// FIXME(-Znext-solver): We only need this hack to deal with fatal
// overflow in the old solver.
// We only need this hack to deal with fatal overflow in the old solver.
if self.infcx.next_trait_solver() || self.infcx.predicate_may_hold(&obligation)
{
ocx.register_obligation(obligation);
Expand Down Expand Up @@ -1955,17 +1954,17 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}

// FIXME(-Znext-solver): See the linked issue below.
// <https://github.com/rust-lang/trait-system-refactor-initiative/issues/134>
// See <https://github.com/rust-lang/trait-system-refactor-initiative/issues/134>.
//
// In the new solver, check the well-formedness of the return type.
// This emulates, in a way, the predicates that fall out of
// normalizing the return type in the old solver.
//
// We alternatively could check the predicates of the method itself hold,
// but we intentionally do not do this in the old solver b/c of cycles,
// and doing it in the new solver would be stronger. This should be fixed
// in the future, since it likely leads to much better method winnowing.
// FIXME(-Znext-solver): We alternatively could check the predicates of
// the method itself hold, but we intentionally do not do this in the old
// solver b/c of cycles, and doing it in the new solver would be stronger.
// This should be fixed in the future, since it likely leads to much better
// method winnowing.
if let Some(xform_ret_ty) = xform_ret_ty
&& self.infcx.next_trait_solver()
{
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_infer/src/infer/outlives/obligations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,11 @@ impl<'tcx> InferCtxt<'tcx> {
}

if !self.tcx.recursion_limit().value_within_limit(iteration) {
// This may actually be reachable. If so, we should convert
// this to a proper error/consider whether we should detect
// this somewhere else.
bug!(
"FIXME(-Znext-solver): Overflowed when processing region obligations: {my_region_obligations:#?}"
"unexpected overflowed when processing region obligations: {my_region_obligations:#?}"
);
}

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ use crate::ty::{

#[allow(rustc::usage_of_ty_tykind)]
impl<'tcx> Interner for TyCtxt<'tcx> {
fn next_trait_solver_globally(self) -> bool {
self.next_trait_solver_globally()
}

type DefId = DefId;
type LocalDefId = LocalDefId;
type Span = Span;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/inline/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
}
false
}
// FIXME(-Znext-solver): Remove this hack when trait solver overflow can return an error.
// FIXME(-Znext-solver=no): Remove this hack when trait solver overflow can return an error.
// In code like that pointed out in #128887, the type complexity we ask the solver to deal with
// grows as we recurse into the call graph. If we use the same recursion limit here and in the
// solver, the solver hits the limit first and emits a fatal error. But if we use a reduced
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_next_trait_solver/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,8 @@ where
return None;
}

// FIXME(-Znext-solver): We should instead try to find a `Certainty::Yes` response with
// a subset of the constraints that all the other responses have.
// FIXME(-Znext-solver): Add support to merge region constraints in
// responses to deal with trait-system-refactor-initiative#27.
let one = responses[0];
if responses[1..].iter().all(|&resp| resp == one) {
return Some(one);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ where
// and we tag the impl bounds with `GoalSource::ImplWhereBound`?
// Right now this includes both the impl and the assoc item where bounds,
// and I don't think the assoc item where-bounds are allowed to be coinductive.
//
// Projecting to the IAT also "steps out the impl contructor", so we would have
// to be very careful when changing the impl where-clauses to be productive.
self.add_goals(
GoalSource::Misc,
cx.predicates_of(inherent.def_id)
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,11 @@ where
.predicates_of(goal.predicate.def_id())
.iter_instantiated(cx, goal.predicate.trait_ref.args)
.map(|p| goal.with(cx, p));
// FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
// While you could think of trait aliases to have a single builtin impl
// which uses its implied trait bounds as where-clauses, using
// `GoalSource::ImplWhereClause` here would be incorrect, as we also
// impl them, which means we're "stepping out of the impl constructor"
// again. To handle this, we treat these cycles as ambiguous for now.
ecx.add_goals(GoalSource::Misc, nested_obligations);
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl<'tcx> At<'_, 'tcx> {
/// same goals in both a temporary and the shared context which negatively impacts
/// performance as these don't share caching.
///
/// FIXME(-Znext-solver): For performance reasons, we currently reuse an existing
/// FIXME(-Znext-solver=no): For performance reasons, we currently reuse an existing
/// fulfillment context in the old solver. Once we have removed the old solver, we
/// can remove the `fulfill_cx` parameter on this function.
fn deeply_normalize<T, E>(
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_traits/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ pub(crate) fn codegen_select_candidate<'tcx>(
// Currently, we use a fulfillment context to completely resolve
// all nested obligations. This is because they can inform the
// inference of the impl's type parameters.
// FIXME(-Znext-solver): Doesn't need diagnostics if new solver.
let ocx = ObligationCtxt::new(&infcx);
let impl_source = selection.map(|obligation| {
ocx.register_obligation(obligation);
Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_type_ir/src/fast_reject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ pub enum TreatParams {
///
/// This also treats projections with inference variables as infer vars
/// since they could be further normalized.
// FIXME(@lcnr): This treats aliases as rigid. This is only correct if the
// type has been structurally normalized. We should reflect this requirement
// in the variant name. It is currently incorrectly used in diagnostics.
AsRigid,
}

Expand Down Expand Up @@ -151,9 +154,11 @@ pub fn simplify_type<I: Interner>(
ty::Alias(..) => match treat_params {
// When treating `ty::Param` as a placeholder, projections also
// don't unify with anything else as long as they are fully normalized.
// FIXME(-Znext-solver): Can remove this `if` and always simplify to `Placeholder`
// when the new solver is enabled by default.
TreatParams::AsRigid if !ty.has_non_region_infer() => Some(SimplifiedType::Placeholder),
TreatParams::AsRigid
if !ty.has_non_region_infer() || cx.next_trait_solver_globally() =>
{
Some(SimplifiedType::Placeholder)
}
TreatParams::AsRigid | TreatParams::InstantiateWithInfer => None,
},
ty::Foreign(def_id) => Some(SimplifiedType::Foreign(def_id)),
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_type_ir/src/interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ pub trait Interner:
+ IrPrint<ty::FnSig<Self>>
+ IrPrint<ty::PatternKind<Self>>
{
fn next_trait_solver_globally(self) -> bool {
true
}

type DefId: DefId<Self>;
type LocalDefId: Copy + Debug + Hash + Eq + Into<Self::DefId> + TypeFoldable<Self>;
type Span: Span<Self>;
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0282]: type annotations needed
--> $DIR/recursive-coroutine-boxed.rs:14:23
--> $DIR/recursive-coroutine-boxed.rs:11:23
|
LL | let mut gen = Box::pin(foo());
| ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Box`
Expand Down
3 changes: 0 additions & 3 deletions tests/ui/impl-trait/recursive-coroutine-boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
use std::ops::{Coroutine, CoroutineState};

fn foo() -> impl Coroutine<Yield = (), Return = ()> {
// FIXME(-Znext-solver): this fails with a mismatched types as the
// hidden type of the opaque ends up as {type error}. We should not
// emit errors for such goals.
#[coroutine] || {
let mut gen = Box::pin(foo());
//[next]~^ ERROR type annotations needed
Expand Down
Loading