Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 136dfc1

Browse files
committed
Auto merge of rust-lang#80417 - Mark-Simulacrum:beta-next, r=Mark-Simulacrum
[beta] backports This backports the following to 1.49: * Revert change to trait evaluation order rust-lang#80132 * Don't allow `const` to begin a nonterminal rust-lang#80135 * Prevent caching normalization results with a cycle rust-lang#80246 r? `@Mark-Simulacrum`
2 parents b0dc3c6 + 2f925da commit 136dfc1

File tree

16 files changed

+220
-27
lines changed

16 files changed

+220
-27
lines changed

compiler/rustc_infer/src/traits/project.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ impl ProjectionCacheKey<'tcx> {
9090
pub enum ProjectionCacheEntry<'tcx> {
9191
InProgress,
9292
Ambiguous,
93+
Recur,
9394
Error,
9495
NormalizedTy(NormalizedTy<'tcx>),
9596
}
@@ -143,7 +144,12 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
143144
"ProjectionCacheEntry::insert_ty: adding cache entry: key={:?}, value={:?}",
144145
key, value
145146
);
146-
let fresh_key = self.map().insert(key, ProjectionCacheEntry::NormalizedTy(value));
147+
let mut map = self.map();
148+
if let Some(ProjectionCacheEntry::Recur) = map.get(&key) {
149+
debug!("Not overwriting Recur");
150+
return;
151+
}
152+
let fresh_key = map.insert(key, ProjectionCacheEntry::NormalizedTy(value));
147153
assert!(!fresh_key, "never started projecting `{:?}`", key);
148154
}
149155

@@ -197,6 +203,14 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
197203
assert!(!fresh, "never started projecting `{:?}`", key);
198204
}
199205

206+
/// Indicates that while trying to normalize `key`, `key` was required to
207+
/// be normalized again. Selection or evaluation should eventually report
208+
/// an error here.
209+
pub fn recur(&mut self, key: ProjectionCacheKey<'tcx>) {
210+
let fresh = self.map().insert(key, ProjectionCacheEntry::Recur);
211+
assert!(!fresh, "never started projecting `{:?}`", key);
212+
}
213+
200214
/// Indicates that trying to normalize `key` resulted in
201215
/// error.
202216
pub fn error(&mut self, key: ProjectionCacheKey<'tcx>) {

compiler/rustc_parse/src/parser/nonterminal.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ impl<'a> Parser<'a> {
2727
token.can_begin_expr()
2828
// This exception is here for backwards compatibility.
2929
&& !token.is_keyword(kw::Let)
30+
// This exception is here for backwards compatibility.
31+
&& !token.is_keyword(kw::Const)
3032
}
3133
NonterminalKind::Ty => token.can_begin_type(),
3234
NonterminalKind::Ident => get_macro_ident(token).is_some(),

compiler/rustc_trait_selection/src/traits/project.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -496,12 +496,6 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
496496
return Ok(None);
497497
}
498498
Err(ProjectionCacheEntry::InProgress) => {
499-
// If while normalized A::B, we are asked to normalize
500-
// A::B, just return A::B itself. This is a conservative
501-
// answer, in the sense that A::B *is* clearly equivalent
502-
// to A::B, though there may be a better value we can
503-
// find.
504-
505499
// Under lazy normalization, this can arise when
506500
// bootstrapping. That is, imagine an environment with a
507501
// where-clause like `A::B == u32`. Now, if we are asked
@@ -512,6 +506,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
512506

513507
debug!("found cache entry: in-progress");
514508

509+
// Cache that normalizing this projection resulted in a cycle. This
510+
// should ensure that, unless this happens within a snapshot that's
511+
// rolled back, fulfillment or evaluation will notice the cycle.
512+
513+
infcx.inner.borrow_mut().projection_cache().recur(cache_key);
514+
return Err(InProgress);
515+
}
516+
Err(ProjectionCacheEntry::Recur) => {
515517
return Err(InProgress);
516518
}
517519
Err(ProjectionCacheEntry::NormalizedTy(ty)) => {
@@ -734,7 +736,14 @@ fn project_type<'cx, 'tcx>(
734736

735737
if !selcx.tcx().sess.recursion_limit().value_within_limit(obligation.recursion_depth) {
736738
debug!("project: overflow!");
737-
return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
739+
match selcx.query_mode() {
740+
super::TraitQueryMode::Standard => {
741+
selcx.infcx().report_overflow_error(&obligation, true);
742+
}
743+
super::TraitQueryMode::Canonical => {
744+
return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
745+
}
746+
}
738747
}
739748

740749
let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx());

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
335335
fn vtable_impl(
336336
&mut self,
337337
impl_def_id: DefId,
338-
mut substs: Normalized<'tcx, SubstsRef<'tcx>>,
338+
substs: Normalized<'tcx, SubstsRef<'tcx>>,
339339
cause: ObligationCause<'tcx>,
340340
recursion_depth: usize,
341341
param_env: ty::ParamEnv<'tcx>,
@@ -357,9 +357,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
357357
// relying on projections in the impl-trait-ref.
358358
//
359359
// e.g., `impl<U: Tr, V: Iterator<Item=U>> Foo<<U as Tr>::T> for V`
360-
substs.obligations.append(&mut impl_obligations);
360+
impl_obligations.extend(substs.obligations);
361361

362-
ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: substs.obligations }
362+
ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: impl_obligations }
363363
}
364364

365365
fn confirm_object_candidate(

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
290290
self.infcx.tcx
291291
}
292292

293+
pub(super) fn query_mode(&self) -> TraitQueryMode {
294+
self.query_mode
295+
}
296+
293297
///////////////////////////////////////////////////////////////////////////
294298
// Selection
295299
//

src/test/ui/associated-types/defaults-cyclic-fail-1.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ impl Tr for u32 {
2424
// ...but not in an impl that redefines one of the types.
2525
impl Tr for bool {
2626
type A = Box<Self::B>;
27-
//~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
27+
//~^ ERROR overflow evaluating the requirement `<bool as Tr>::B == _`
2828
}
2929
// (the error is shown twice for some reason)
3030

3131
impl Tr for usize {
3232
type B = &'static Self::A;
33-
//~^ ERROR type mismatch resolving `<usize as Tr>::A == _`
33+
//~^ ERROR overflow evaluating the requirement `<usize as Tr>::A == _`
3434
}
3535

3636
fn main() {
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
1+
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B == _`
22
--> $DIR/defaults-cyclic-fail-1.rs:26:5
33
|
44
LL | type A = Box<Self::B>;
5-
| ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
5+
| ^^^^^^^^^^^^^^^^^^^^^^
66

7-
error[E0271]: type mismatch resolving `<usize as Tr>::A == _`
7+
error[E0275]: overflow evaluating the requirement `<usize as Tr>::A == _`
88
--> $DIR/defaults-cyclic-fail-1.rs:32:5
99
|
1010
LL | type B = &'static Self::A;
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

1313
error: aborting due to 2 previous errors
1414

15-
For more information about this error, try `rustc --explain E0271`.
15+
For more information about this error, try `rustc --explain E0275`.

src/test/ui/associated-types/defaults-cyclic-fail-2.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ impl Tr for u32 {
2525

2626
impl Tr for bool {
2727
type A = Box<Self::B>;
28-
//~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
28+
//~^ ERROR overflow evaluating the requirement `<bool as Tr>::B == _`
2929
}
3030
// (the error is shown twice for some reason)
3131

3232
impl Tr for usize {
3333
type B = &'static Self::A;
34-
//~^ ERROR type mismatch resolving `<usize as Tr>::A == _`
34+
//~^ ERROR overflow evaluating the requirement `<usize as Tr>::A == _`
3535
}
3636

3737
fn main() {
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
1+
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B == _`
22
--> $DIR/defaults-cyclic-fail-2.rs:27:5
33
|
44
LL | type A = Box<Self::B>;
5-
| ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
5+
| ^^^^^^^^^^^^^^^^^^^^^^
66

7-
error[E0271]: type mismatch resolving `<usize as Tr>::A == _`
7+
error[E0275]: overflow evaluating the requirement `<usize as Tr>::A == _`
88
--> $DIR/defaults-cyclic-fail-2.rs:33:5
99
|
1010
LL | type B = &'static Self::A;
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

1313
error: aborting due to 2 previous errors
1414

15-
For more information about this error, try `rustc --explain E0271`.
15+
For more information about this error, try `rustc --explain E0275`.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Regression test for #79714
2+
3+
trait Baz {}
4+
impl Baz for () {}
5+
impl<T> Baz for (T,) {}
6+
7+
trait Fiz {}
8+
impl Fiz for bool {}
9+
10+
trait Grault {
11+
type A;
12+
type B;
13+
}
14+
15+
impl<T: Grault> Grault for (T,)
16+
where
17+
Self::A: Baz,
18+
Self::B: Fiz,
19+
{
20+
type A = ();
21+
//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
22+
type B = bool;
23+
//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
24+
}
25+
//~^^^^^^^^^^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
26+
27+
fn main() {
28+
let x: <(_,) as Grault>::A = ();
29+
}

0 commit comments

Comments
 (0)