Skip to content
Open
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
31 changes: 3 additions & 28 deletions compiler/rustc_type_ir/src/search_graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -916,10 +916,9 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
/// heads from the stack. This may not necessarily mean that we've actually
/// reached a fixpoint for that cycle head, which impacts the way we rebase
/// provisional cache entries.
#[derive_where(Debug; X: Cx)]
enum RebaseReason<X: Cx> {
#[derive(Debug)]
enum RebaseReason {
NoCycleUsages,
Ambiguity(X::AmbiguityInfo),
Overflow,
/// We've actually reached a fixpoint.
///
Expand Down Expand Up @@ -956,7 +955,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
&mut self,
cx: X,
stack_entry: &StackEntry<X>,
rebase_reason: RebaseReason<X>,
rebase_reason: RebaseReason,
) {
let popped_head_index = self.stack.next_index();
#[allow(rustc::potential_query_instability)]
Expand Down Expand Up @@ -1035,9 +1034,6 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
// is not actually equal to the final provisional result. We
// need to discard the provisional cache entry in this case.
RebaseReason::NoCycleUsages => return false,
RebaseReason::Ambiguity(info) => {
*result = D::propagate_ambiguity(cx, input, info);
}
RebaseReason::Overflow => *result = D::fixpoint_overflow_result(cx, input),
RebaseReason::ReachedFixpoint(None) => {}
RebaseReason::ReachedFixpoint(Some(path_kind)) => {
Expand Down Expand Up @@ -1352,27 +1348,6 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
return EvaluationResult::finalize(stack_entry, encountered_overflow, result);
}

// If computing this goal results in ambiguity with no constraints,
// we do not rerun it. It's incredibly difficult to get a different
// response in the next iteration in this case. These changes would
// likely either be caused by incompleteness or can change the maybe
// cause from ambiguity to overflow. Returning ambiguity always
// preserves soundness and completeness even if the goal is be known
// to succeed or fail.
//
// This prevents exponential blowup affecting multiple major crates.
// As we only get to this branch if we haven't yet reached a fixpoint,
// we also taint all provisional cache entries which depend on the
// current goal.
if let Some(info) = D::is_ambiguous_result(result) {
self.rebase_provisional_cache_entries(
cx,
&stack_entry,
RebaseReason::Ambiguity(info),
);
return EvaluationResult::finalize(stack_entry, encountered_overflow, result);
};

// If we've reached the fixpoint step limit, we bail with overflow and taint all
// provisional cache entries which depend on the current goal.
i += 1;
Expand Down
45 changes: 45 additions & 0 deletions tests/ui/traits/next-solver/global-where-bound-normalization.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//@ check-pass
//@ compile-flags: -Znext-solver

// Regression test for https://github.com/rust-lang/trait-system-refactor-initiative/issues/257.

#![feature(rustc_attrs)]
#![expect(internal_features)]
#![rustc_no_implicit_bounds]

pub trait Bound {}
impl Bound for u8 {}

pub trait Proj {
type Assoc;
}
impl<U: Bound> Proj for U {
type Assoc = U;
}
impl Proj for MyField {
type Assoc = u8;
}

// While wf-checking the global bounds of `fn foo`, elaborating this outlives predicate triggered a
// cycle in the search graph along a particular probe path, which was not an actual solution.
// That cycle then resulted in a forced false-positive ambiguity due to a performance hack in the
// search graph and then ended up floundering the root goal evaluation.
pub trait Field: Proj<Assoc: Bound + 'static> {}

struct MyField;
impl Field for MyField {}

trait IdReqField {
type This;
}
impl<F: Field> IdReqField for F {
type This = F;
}

fn foo()
where
<MyField as IdReqField>::This: Field,
{
}

fn main() {}
Loading