FIXME(-Znext-solver) triage

Co-authored-by: Michael Goulet <michael@errs.io>
This commit is contained in:
lcnr
2025-05-30 11:21:34 +00:00
parent c68032fd4c
commit 7dac755be8
20 changed files with 68 additions and 40 deletions

View File

@@ -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:#?}"
);
}

View File

@@ -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;
}
@@ -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;
}

View File

@@ -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 {

View File

@@ -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()

View File

@@ -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),

View File

@@ -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()
{
@@ -1455,7 +1453,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
} else {
ty
self.resolve_vars_with_obligations(ty)
}
}

View File

@@ -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 {

View File

@@ -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);
@@ -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()
{

View File

@@ -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:#?}"
);
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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)

View File

@@ -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)
})

View File

@@ -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>(

View File

@@ -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);

View File

@@ -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,
}
@@ -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)),

View File

@@ -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>;

View File

@@ -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`

View File

@@ -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