Skip to content

Commit ccc7e13

Browse files
committed
fix RebaseReason::Ambiguity
we should not get the certainty from the current result of the provisional cache entry
1 parent 3d35461 commit ccc7e13

File tree

5 files changed

+99
-15
lines changed

5 files changed

+99
-15
lines changed

compiler/rustc_next_trait_solver/src/solve/search_graph.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,19 +99,23 @@ where
9999
response_no_constraints(cx, input, Certainty::overflow(false))
100100
}
101101

102-
fn is_ambiguous_result(result: QueryResult<I>) -> bool {
103-
result.is_ok_and(|response| {
104-
has_no_inference_or_external_constraints(response)
102+
fn is_ambiguous_result(result: QueryResult<I>) -> Option<Certainty> {
103+
result.ok().and_then(|response| {
104+
if has_no_inference_or_external_constraints(response)
105105
&& matches!(response.value.certainty, Certainty::Maybe { .. })
106+
{
107+
Some(response.value.certainty)
108+
} else {
109+
None
110+
}
106111
})
107112
}
108113

109114
fn propagate_ambiguity(
110115
cx: I,
111116
for_input: CanonicalInput<I>,
112-
from_result: QueryResult<I>,
117+
certainty: Certainty,
113118
) -> QueryResult<I> {
114-
let certainty = from_result.unwrap().value.certainty;
115119
response_no_constraints(cx, for_input, certainty)
116120
}
117121

compiler/rustc_type_ir/src/interner.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::inherent::*;
1111
use crate::ir_print::IrPrint;
1212
use crate::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem};
1313
use crate::relate::Relate;
14-
use crate::solve::{CanonicalInput, ExternalConstraintsData, QueryResult, inspect};
14+
use crate::solve::{CanonicalInput, Certainty, ExternalConstraintsData, QueryResult, inspect};
1515
use crate::visit::{Flags, TypeVisitable};
1616
use crate::{self as ty, CanonicalParamEnvCacheEntry, search_graph};
1717

@@ -548,6 +548,7 @@ impl<T, R, E> CollectAndApply<T, R> for Result<T, E> {
548548
impl<I: Interner> search_graph::Cx for I {
549549
type Input = CanonicalInput<I>;
550550
type Result = QueryResult<I>;
551+
type AmbiguityInfo = Certainty;
551552

552553
type DepNodeIndex = I::DepNodeIndex;
553554
type Tracked<T: Debug + Clone> = I::Tracked<T>;

compiler/rustc_type_ir/src/search_graph/mod.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ pub use global_cache::GlobalCache;
4040
pub trait Cx: Copy {
4141
type Input: Debug + Eq + Hash + Copy;
4242
type Result: Debug + Eq + Hash + Copy;
43+
type AmbiguityInfo: Debug + Eq + Hash + Copy;
4344

4445
type DepNodeIndex;
4546
type Tracked<T: Debug + Clone>: Debug;
@@ -96,11 +97,13 @@ pub trait Delegate: Sized {
9697
input: <Self::Cx as Cx>::Input,
9798
) -> <Self::Cx as Cx>::Result;
9899

99-
fn is_ambiguous_result(result: <Self::Cx as Cx>::Result) -> bool;
100+
fn is_ambiguous_result(
101+
result: <Self::Cx as Cx>::Result,
102+
) -> Option<<Self::Cx as Cx>::AmbiguityInfo>;
100103
fn propagate_ambiguity(
101104
cx: Self::Cx,
102105
for_input: <Self::Cx as Cx>::Input,
103-
from_result: <Self::Cx as Cx>::Result,
106+
ambiguity_info: <Self::Cx as Cx>::AmbiguityInfo,
104107
) -> <Self::Cx as Cx>::Result;
105108

106109
fn compute_goal(
@@ -913,9 +916,9 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
913916
/// heads from the stack. This may not necessarily mean that we've actually
914917
/// reached a fixpoint for that cycle head, which impacts the way we rebase
915918
/// provisional cache entries.
916-
enum RebaseReason {
919+
enum RebaseReason<X: Cx> {
917920
NoCycleUsages,
918-
Ambiguity,
921+
Ambiguity(X::AmbiguityInfo),
919922
Overflow,
920923
/// We've actually reached a fixpoint.
921924
///
@@ -951,7 +954,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
951954
&mut self,
952955
cx: X,
953956
stack_entry: &StackEntry<X>,
954-
rebase_reason: RebaseReason,
957+
rebase_reason: RebaseReason<X>,
955958
) {
956959
let popped_head_index = self.stack.next_index();
957960
#[allow(rustc::potential_query_instability)]
@@ -1029,8 +1032,8 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
10291032
// is not actually equal to the final provisional result. We
10301033
// need to discard the provisional cache entry in this case.
10311034
RebaseReason::NoCycleUsages => return false,
1032-
RebaseReason::Ambiguity => {
1033-
*result = D::propagate_ambiguity(cx, input, *result);
1035+
RebaseReason::Ambiguity(info) => {
1036+
*result = D::propagate_ambiguity(cx, input, info);
10341037
}
10351038
RebaseReason::Overflow => *result = D::fixpoint_overflow_result(cx, input),
10361039
RebaseReason::ReachedFixpoint(None) => {}
@@ -1268,6 +1271,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
12681271
}
12691272

12701273
/// Whether we've reached a fixpoint when evaluating a cycle head.
1274+
#[instrument(level = "trace", skip(self, stack_entry), ret)]
12711275
fn reached_fixpoint(
12721276
&mut self,
12731277
stack_entry: &StackEntry<X>,
@@ -1355,8 +1359,12 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
13551359
// As we only get to this branch if we haven't yet reached a fixpoint,
13561360
// we also taint all provisional cache entries which depend on the
13571361
// current goal.
1358-
if D::is_ambiguous_result(result) {
1359-
self.rebase_provisional_cache_entries(cx, &stack_entry, RebaseReason::Ambiguity);
1362+
if let Some(info) = D::is_ambiguous_result(result) {
1363+
self.rebase_provisional_cache_entries(
1364+
cx,
1365+
&stack_entry,
1366+
RebaseReason::Ambiguity(info),
1367+
);
13601368
return EvaluationResult::finalize(stack_entry, encountered_overflow, result);
13611369
};
13621370

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//@ compile-flags: -Znext-solver
2+
#![feature(rustc_attrs)]
3+
#![rustc_no_implicit_bounds]
4+
5+
// A regression test making sure that when forcing dependent
6+
// provisional cache entries to ambiguous, we use the `MaybeCause`
7+
// of the cycle head. We ended up trying to use the current result
8+
// of the provisional cache entry, which is incorrect and caused an
9+
// ICE when trying to unwrap it.
10+
11+
struct Root<T>(T);
12+
struct Head<T>(T);
13+
struct Error<T>(T);
14+
struct NotImplemented<T>(T);
15+
16+
#[rustc_coinductive]
17+
trait Trait {}
18+
impl<T> Trait for Root<T>
19+
where
20+
Head<T>: Trait,
21+
{}
22+
23+
impl<T> Trait for Head<T>
24+
where
25+
Root<T>: Trait,
26+
T: Trait, // ambiguous
27+
{}
28+
29+
impl<T> Trait for Head<T>
30+
where
31+
Error<T>: Trait,
32+
NotImplemented<T>: Trait,
33+
{}
34+
35+
impl<T> Trait for Error<T>
36+
where
37+
Head<T>: Trait,
38+
NotImplemented<T>: Trait,
39+
{}
40+
41+
fn impls_trait<T: Trait>() {}
42+
fn main() {
43+
impls_trait::<Root<_>>() //~ ERROR type annotations needed
44+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0283]: type annotations needed
2+
--> $DIR/forced_ambiguity-use-head-maybe-cause.rs:43:19
3+
|
4+
LL | impls_trait::<Root<_>>()
5+
| ^^^^^^^ cannot infer type for struct `Head<_>`
6+
|
7+
= note: cannot satisfy `Head<_>: Trait`
8+
= help: the trait `Trait` is implemented for `Head<T>`
9+
note: required for `Root<_>` to implement `Trait`
10+
--> $DIR/forced_ambiguity-use-head-maybe-cause.rs:18:9
11+
|
12+
LL | impl<T> Trait for Root<T>
13+
| ^^^^^ ^^^^^^^
14+
LL | where
15+
LL | Head<T>: Trait,
16+
| ----- unsatisfied trait bound introduced here
17+
= note: 8 redundant requirements hidden
18+
= note: required for `Root<_>` to implement `Trait`
19+
note: required by a bound in `impls_trait`
20+
--> $DIR/forced_ambiguity-use-head-maybe-cause.rs:41:19
21+
|
22+
LL | fn impls_trait<T: Trait>() {}
23+
| ^^^^^ required by this bound in `impls_trait`
24+
25+
error: aborting due to 1 previous error
26+
27+
For more information about this error, try `rustc --explain E0283`.

0 commit comments

Comments
 (0)