Rollup merge of #149904 - ShoyuVanilla:ns-remove-sg-hack, r=lcnr
`-Znext-solver` Remove the forced ambiguity hack from search graph As discussed in https://github.com/rust-lang/trait-system-refactor-initiative/issues/257 r? lcnr
This commit is contained in:
commit
c108ad5617
2 changed files with 48 additions and 28 deletions
|
|
@ -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
|
/// 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
|
/// reached a fixpoint for that cycle head, which impacts the way we rebase
|
||||||
/// provisional cache entries.
|
/// provisional cache entries.
|
||||||
#[derive_where(Debug; X: Cx)]
|
#[derive(Debug)]
|
||||||
enum RebaseReason<X: Cx> {
|
enum RebaseReason {
|
||||||
NoCycleUsages,
|
NoCycleUsages,
|
||||||
Ambiguity(X::AmbiguityInfo),
|
|
||||||
Overflow,
|
Overflow,
|
||||||
/// We've actually reached a fixpoint.
|
/// We've actually reached a fixpoint.
|
||||||
///
|
///
|
||||||
|
|
@ -956,7 +955,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
|
||||||
&mut self,
|
&mut self,
|
||||||
cx: X,
|
cx: X,
|
||||||
stack_entry: &StackEntry<X>,
|
stack_entry: &StackEntry<X>,
|
||||||
rebase_reason: RebaseReason<X>,
|
rebase_reason: RebaseReason,
|
||||||
) {
|
) {
|
||||||
let popped_head_index = self.stack.next_index();
|
let popped_head_index = self.stack.next_index();
|
||||||
#[allow(rustc::potential_query_instability)]
|
#[allow(rustc::potential_query_instability)]
|
||||||
|
|
@ -1035,9 +1034,6 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
|
||||||
// is not actually equal to the final provisional result. We
|
// is not actually equal to the final provisional result. We
|
||||||
// need to discard the provisional cache entry in this case.
|
// need to discard the provisional cache entry in this case.
|
||||||
RebaseReason::NoCycleUsages => return false,
|
RebaseReason::NoCycleUsages => return false,
|
||||||
RebaseReason::Ambiguity(info) => {
|
|
||||||
*result = D::propagate_ambiguity(cx, input, info);
|
|
||||||
}
|
|
||||||
RebaseReason::Overflow => *result = D::fixpoint_overflow_result(cx, input),
|
RebaseReason::Overflow => *result = D::fixpoint_overflow_result(cx, input),
|
||||||
RebaseReason::ReachedFixpoint(None) => {}
|
RebaseReason::ReachedFixpoint(None) => {}
|
||||||
RebaseReason::ReachedFixpoint(Some(path_kind)) => {
|
RebaseReason::ReachedFixpoint(Some(path_kind)) => {
|
||||||
|
|
@ -1352,27 +1348,6 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
|
||||||
return EvaluationResult::finalize(stack_entry, encountered_overflow, result);
|
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
|
// If we've reached the fixpoint step limit, we bail with overflow and taint all
|
||||||
// provisional cache entries which depend on the current goal.
|
// provisional cache entries which depend on the current goal.
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|
|
||||||
|
|
@ -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…
Add table
Add a link
Reference in a new issue