Skip to content

Commit b668081

Browse files
committed
Auto merge of #133502 - lcnr:rust4, r=<try>
[DO NOT MERGE] `-Znext-solver=globally` experiments
2 parents c290daa + 4c1b070 commit b668081

14 files changed

Lines changed: 171 additions & 147 deletions

File tree

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -747,11 +747,14 @@ fn check_new_solver_banned_features(sess: &Session, features: &Features) {
747747
.map(|feat| feat.attr_sp)
748748
{
749749
#[allow(rustc::symbol_intern_string_literal)]
750-
sess.dcx().emit_err(diagnostics::IncompatibleFeatures {
751-
spans: vec![gce_span],
752-
f1: Symbol::intern("-Znext-solver=globally"),
753-
f2: sym::generic_const_exprs,
754-
});
750+
sess.dcx()
751+
.create_fatal(diagnostics::IncompatibleFeatures {
752+
spans: vec![gce_span],
753+
f1: Symbol::intern("-Znext-solver=globally"),
754+
f2: sym::generic_const_exprs,
755+
})
756+
.with_code(rustc_errors::E0001)
757+
.emit();
755758
}
756759
}
757760

compiler/rustc_middle/src/ty/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2688,7 +2688,7 @@ impl<'tcx> TyCtxt<'tcx> {
26882688
}
26892689

26902690
pub fn next_trait_solver_globally(self) -> bool {
2691-
self.sess.opts.unstable_opts.next_solver.globally
2691+
self.sess.opts.unstable_opts.next_solver.globally && !self.features().generic_const_exprs()
26922692
}
26932693

26942694
pub fn next_trait_solver_in_coherence(self) -> bool {

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ where
226226
span: I::Span,
227227
stalled_on: Option<GoalStalledOn<I>>,
228228
) -> Result<GoalEvaluation<I>, NoSolution> {
229-
let result = EvalCtxt::enter_root(self, self.cx().recursion_limit(), span, |ecx| {
229+
let result = EvalCtxt::enter_root(self, self.cx().recursion_limit() * 2, span, |ecx| {
230230
ecx.evaluate_goal(GoalSource::Misc, goal, stalled_on)
231231
});
232232

@@ -323,18 +323,12 @@ where
323323
// We currently only consider a cycle coinductive if it steps
324324
// into a where-clause of a coinductive trait.
325325
CurrentGoalKind::CoinductiveTrait => PathKind::Coinductive,
326-
// While normalizing via an impl does step into a where-clause of
327-
// an impl, accessing the associated item immediately steps out of
328-
// it again. This means cycles/recursive calls are not guarded
329-
// by impls used for normalization.
330-
//
331-
// See tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs
332-
// for how this can go wrong.
333-
CurrentGoalKind::ProjectionComputeAssocTermCandidate => PathKind::Inductive,
334326
// We probably want to make all traits coinductive in the future,
335327
// so we treat cycles involving where-clauses of not-yet coinductive
336328
// traits as ambiguous for now.
337-
CurrentGoalKind::Misc => PathKind::Unknown,
329+
CurrentGoalKind::Misc | CurrentGoalKind::ProjectionComputeAssocTermCandidate => {
330+
PathKind::Unknown
331+
}
338332
},
339333
// Relating types is always unproductive. If we were to map proof trees to
340334
// corecursive functions as explained in #136824, relating types never
@@ -870,7 +864,7 @@ where
870864
(
871865
RerunCondition::OpaqueInStorageOrAnyOpaqueHasInferAsHidden(_),
872866
TypingMode::PostAnalysis | TypingMode::Codegen,
873-
) => RerunDecision::No,
867+
) => RerunDecision::Yes,
874868
(
875869
RerunCondition::OpaqueInStorageOrAnyOpaqueHasInferAsHidden(defids),
876870
TypingMode::Typeck { defining_opaque_types_and_generators: opaques },
@@ -1746,7 +1740,7 @@ pub fn evaluate_root_goal_for_proof_tree_raw_provider<
17461740
let mut inspect = inspect::ProofTreeBuilder::new();
17471741
let (canonical_result, accessed_opaques) = SearchGraph::<D>::evaluate_root_goal_for_proof_tree(
17481742
cx,
1749-
cx.recursion_limit(),
1743+
cx.recursion_limit() * 2,
17501744
canonical_goal,
17511745
&mut inspect,
17521746
);

compiler/rustc_next_trait_solver/src/solve/search_graph.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,12 @@ where
106106
response_no_constraints(cx, input, Certainty::overflow(true))
107107
}
108108

109+
const FIXPOINT_OVERFLOW_AMBIGUITY_KIND: Certainty = Certainty::overflow(false);
109110
fn fixpoint_overflow_result(
110111
cx: I,
111112
input: CanonicalInput<I>,
112113
) -> (QueryResult<I>, AccessedOpaques<I>) {
113-
response_no_constraints(cx, input, Certainty::overflow(false))
114+
response_no_constraints(cx, input, Self::FIXPOINT_OVERFLOW_AMBIGUITY_KIND)
114115
}
115116

116117
fn is_ambiguous_result(result: (QueryResult<I>, AccessedOpaques<I>)) -> Option<Certainty> {
@@ -125,14 +126,6 @@ where
125126
})
126127
}
127128

128-
fn propagate_ambiguity(
129-
cx: I,
130-
for_input: CanonicalInput<I>,
131-
certainty: Certainty,
132-
) -> (QueryResult<I>, AccessedOpaques<I>) {
133-
response_no_constraints(cx, for_input, certainty)
134-
}
135-
136129
fn compute_goal(
137130
search_graph: &mut SearchGraph<D>,
138131
cx: I,

compiler/rustc_session/src/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1005,7 +1005,7 @@ pub struct NextSolverConfig {
10051005
pub coherence: bool = true,
10061006
/// Whether the new trait solver should be enabled everywhere.
10071007
/// This is only `true` if `coherence` is also enabled.
1008-
pub globally: bool = false,
1008+
pub globally: bool = true,
10091009
}
10101010

10111011
#[derive(Clone)]

compiler/rustc_type_ir/src/interner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ impl<T, R, E> CollectAndApply<T, R> for Result<T, E> {
654654
impl<I: Interner> search_graph::Cx for I {
655655
type Input = CanonicalInput<I>;
656656
type Result = (QueryResult<I>, AccessedOpaques<I>);
657-
type AmbiguityInfo = Certainty;
657+
type AmbiguityKind = Certainty;
658658

659659
type DepNodeIndex = I::DepNodeIndex;
660660
type Tracked<T: Debug + Clone> = I::Tracked<T>;

compiler/rustc_type_ir/src/search_graph/mod.rs

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +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;
43+
type AmbiguityKind: Debug + Eq + Hash + Copy;
4444

4545
type DepNodeIndex;
4646
type Tracked<T: Debug + Clone>: Debug;
@@ -92,19 +92,16 @@ pub trait Delegate: Sized {
9292
cx: Self::Cx,
9393
input: <Self::Cx as Cx>::Input,
9494
) -> <Self::Cx as Cx>::Result;
95+
96+
const FIXPOINT_OVERFLOW_AMBIGUITY_KIND: <Self::Cx as Cx>::AmbiguityKind;
9597
fn fixpoint_overflow_result(
9698
cx: Self::Cx,
9799
input: <Self::Cx as Cx>::Input,
98100
) -> <Self::Cx as Cx>::Result;
99101

100102
fn is_ambiguous_result(
101103
result: <Self::Cx as Cx>::Result,
102-
) -> Option<<Self::Cx as Cx>::AmbiguityInfo>;
103-
fn propagate_ambiguity(
104-
cx: Self::Cx,
105-
for_input: <Self::Cx as Cx>::Input,
106-
ambiguity_info: <Self::Cx as Cx>::AmbiguityInfo,
107-
) -> <Self::Cx as Cx>::Result;
104+
) -> Option<<Self::Cx as Cx>::AmbiguityKind>;
108105

109106
fn compute_goal(
110107
search_graph: &mut SearchGraph<Self>,
@@ -955,8 +952,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
955952
#[derive_where(Debug; X: Cx)]
956953
enum RebaseReason<X: Cx> {
957954
NoCycleUsages,
958-
Ambiguity(X::AmbiguityInfo),
959-
Overflow,
955+
Ambiguity(X::AmbiguityKind),
960956
/// We've actually reached a fixpoint.
961957
///
962958
/// This either happens in the first evaluation step for the cycle head.
@@ -987,10 +983,9 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
987983
/// cache entries to also be ambiguous. This causes some undesirable ambiguity for nested
988984
/// goals whose result doesn't actually depend on this cycle head, but that's acceptable
989985
/// to me.
990-
#[instrument(level = "trace", skip(self, cx))]
986+
#[instrument(level = "trace", skip(self))]
991987
fn rebase_provisional_cache_entries(
992988
&mut self,
993-
cx: X,
994989
stack_entry: &StackEntry<X>,
995990
rebase_reason: RebaseReason<X>,
996991
) {
@@ -1065,18 +1060,22 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
10651060
}
10661061

10671062
// The provisional cache entry does depend on the provisional result
1068-
// of the popped cycle head. We need to mutate the result of our
1069-
// provisional cache entry in case we did not reach a fixpoint.
1063+
// of the popped cycle head. In case we didn't actually reach a fixpoint,
1064+
// we must not keep potentially incorrect provisional cache entries around.
10701065
match rebase_reason {
10711066
// If the cycle head does not actually depend on itself, then
10721067
// the provisional result used by the provisional cache entry
10731068
// is not actually equal to the final provisional result. We
10741069
// need to discard the provisional cache entry in this case.
10751070
RebaseReason::NoCycleUsages => return false,
1076-
RebaseReason::Ambiguity(info) => {
1077-
*result = D::propagate_ambiguity(cx, input, info);
1071+
// If we avoid rerunning a goal due to ambiguity, we only keep provisional
1072+
// results which depend on that cycle head if these are already ambiguous
1073+
// themselves.
1074+
RebaseReason::Ambiguity(kind) => {
1075+
if !D::is_ambiguous_result(*result).is_some_and(|k| k == kind) {
1076+
return false;
1077+
}
10781078
}
1079-
RebaseReason::Overflow => *result = D::fixpoint_overflow_result(cx, input),
10801079
RebaseReason::ReachedFixpoint(None) => {}
10811080
RebaseReason::ReachedFixpoint(Some(path_kind)) => {
10821081
if !popped_head.usages.is_single(path_kind) {
@@ -1380,17 +1379,12 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
13801379
// final result is equal to the initial response for that case.
13811380
if let Ok(fixpoint) = self.reached_fixpoint(&stack_entry, usages, result) {
13821381
self.rebase_provisional_cache_entries(
1383-
cx,
13841382
&stack_entry,
13851383
RebaseReason::ReachedFixpoint(fixpoint),
13861384
);
13871385
return EvaluationResult::finalize(stack_entry, encountered_overflow, result);
13881386
} else if usages.is_empty() {
1389-
self.rebase_provisional_cache_entries(
1390-
cx,
1391-
&stack_entry,
1392-
RebaseReason::NoCycleUsages,
1393-
);
1387+
self.rebase_provisional_cache_entries(&stack_entry, RebaseReason::NoCycleUsages);
13941388
return EvaluationResult::finalize(stack_entry, encountered_overflow, result);
13951389
}
13961390

@@ -1399,19 +1393,15 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
13991393
// response in the next iteration in this case. These changes would
14001394
// likely either be caused by incompleteness or can change the maybe
14011395
// cause from ambiguity to overflow. Returning ambiguity always
1402-
// preserves soundness and completeness even if the goal is be known
1403-
// to succeed or fail.
1396+
// preserves soundness and completeness even if the goal could
1397+
// otherwise succeed or fail.
14041398
//
14051399
// This prevents exponential blowup affecting multiple major crates.
14061400
// As we only get to this branch if we haven't yet reached a fixpoint,
14071401
// we also taint all provisional cache entries which depend on the
14081402
// current goal.
1409-
if let Some(info) = D::is_ambiguous_result(result) {
1410-
self.rebase_provisional_cache_entries(
1411-
cx,
1412-
&stack_entry,
1413-
RebaseReason::Ambiguity(info),
1414-
);
1403+
if let Some(kind) = D::is_ambiguous_result(result) {
1404+
self.rebase_provisional_cache_entries(&stack_entry, RebaseReason::Ambiguity(kind));
14151405
return EvaluationResult::finalize(stack_entry, encountered_overflow, result);
14161406
};
14171407

@@ -1421,7 +1411,10 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
14211411
if i >= D::FIXPOINT_STEP_LIMIT {
14221412
debug!("canonical cycle overflow");
14231413
let result = D::fixpoint_overflow_result(cx, input);
1424-
self.rebase_provisional_cache_entries(cx, &stack_entry, RebaseReason::Overflow);
1414+
self.rebase_provisional_cache_entries(
1415+
&stack_entry,
1416+
RebaseReason::Ambiguity(D::FIXPOINT_OVERFLOW_AMBIGUITY_KIND),
1417+
);
14251418
return EvaluationResult::finalize(stack_entry, encountered_overflow, result);
14261419
}
14271420

tests/ui/specialization/min_specialization/next-solver-region-resolution.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ trait Foo {
99

1010
trait Baz {}
1111

12-
impl<'a, T> Foo for &'a T
12+
impl<'a, T> Foo for &'a T //~ ERROR not all trait items implemented, missing: `Item`
13+
//~| ERROR type annotations needed: cannot satisfy `&'a T: Foo`
1314
where
1415
Self::Item: 'a,
1516
{
Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,58 @@
1-
error[E0391]: cycle detected when computing normalized predicates of `<impl at $DIR/next-solver-region-resolution.rs:18:1: 21:21>`
2-
--> $DIR/next-solver-region-resolution.rs:18:1
1+
error[E0046]: not all trait items implemented, missing: `Item`
2+
--> $DIR/next-solver-region-resolution.rs:12:1
33
|
4-
LL | / impl<'a, T> Foo for &T
4+
LL | type Item;
5+
| --------- `Item` from trait
6+
...
7+
LL | / impl<'a, T> Foo for &'a T
58
LL | |
69
LL | | where
7-
LL | | Self::Item: Baz,
8-
| |____________________^
10+
LL | | Self::Item: 'a,
11+
| |___________________^ missing `Item` in implementation
12+
13+
error[E0283]: type annotations needed: cannot satisfy `&'a T: Foo`
14+
--> $DIR/next-solver-region-resolution.rs:12:21
915
|
10-
= note: ...which immediately requires computing normalized predicates of `<impl at $DIR/next-solver-region-resolution.rs:18:1: 21:21>` again
11-
note: cycle used when computing whether impls specialize one another
16+
LL | impl<'a, T> Foo for &'a T
17+
| ^^^^^
18+
|
19+
note: multiple `impl`s satisfying `&'a T: Foo` found
1220
--> $DIR/next-solver-region-resolution.rs:12:1
1321
|
1422
LL | / impl<'a, T> Foo for &'a T
23+
LL | |
1524
LL | | where
1625
LL | | Self::Item: 'a,
1726
| |___________________^
18-
= note: for more information, see <https://rustc-dev-guide.rust-lang.org/overview.html#queries> and <https://rustc-dev-guide.rust-lang.org/query.html>
27+
...
28+
LL | / impl<'a, T> Foo for &T
29+
LL | |
30+
LL | | where
31+
LL | | Self::Item: Baz,
32+
| |____________________^
33+
34+
error[E0046]: not all trait items implemented, missing: `Item`
35+
--> $DIR/next-solver-region-resolution.rs:19:1
36+
|
37+
LL | type Item;
38+
| --------- `Item` from trait
39+
...
40+
LL | / impl<'a, T> Foo for &T
41+
LL | |
42+
LL | | where
43+
LL | | Self::Item: Baz,
44+
| |____________________^ missing `Item` in implementation
45+
46+
error: cannot normalize `<&_ as Foo>::Item: '_`
47+
--> $DIR/next-solver-region-resolution.rs:19:1
48+
|
49+
LL | / impl<'a, T> Foo for &T
50+
LL | |
51+
LL | | where
52+
LL | | Self::Item: Baz,
53+
| |____________________^
1954

20-
error: aborting due to 1 previous error
55+
error: aborting due to 4 previous errors
2156

22-
For more information about this error, try `rustc --explain E0391`.
57+
Some errors have detailed explanations: E0046, E0283.
58+
For more information about an error, try `rustc --explain E0046`.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0283]: type annotations needed: cannot satisfy `<Vec<T> as IntoIterator>::IntoIter: Iterator`
2+
--> $DIR/normalizes-to-is-not-productive-2.rs:21:41
3+
|
4+
LL | <Vec<T> as IntoIterator>::IntoIter: Iterator,
5+
| ^^^^^^^^
6+
|
7+
= note: cannot satisfy `<Vec<T> as IntoIterator>::IntoIter: Iterator`
8+
9+
error: aborting due to 1 previous error
10+
11+
For more information about this error, try `rustc --explain E0283`.

0 commit comments

Comments
 (0)