Skip to content

Commit 64d2330

Browse files
authored
Unrolled build for rust-lang#115801
Rollup merge of rust-lang#115801 - compiler-errors:async-cycle-mono, r=oli-obk Detect cycle errors hidden by opaques during monomorphization Opaque types may reveal to projections, which themselves normalize to opaques. We don't currently normalize when checking that opaques are cyclical, and we may also not know that the opaque is cyclical until monomorphization (see `tests/ui/type-alias-impl-trait/mututally-recursive-overflow.rs`). Detect cycle errors in `normalize_projection_ty` and report a fatal overflow (in the old solver). Luckily, this is already detected as a fatal overflow in the new solver. Fixes rust-lang#112047
2 parents 42f5828 + 8fbd78c commit 64d2330

7 files changed

+147
-1
lines changed

compiler/rustc_traits/src/normalize_projection_ty.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ use rustc_infer::infer::TyCtxtInferExt;
33
use rustc_middle::query::Providers;
44
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
55
use rustc_trait_selection::infer::InferCtxtBuilderExt;
6+
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
67
use rustc_trait_selection::traits::query::{
78
normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution,
89
};
9-
use rustc_trait_selection::traits::{self, ObligationCause, SelectionContext};
10+
use rustc_trait_selection::traits::{
11+
self, FulfillmentErrorCode, ObligationCause, SelectionContext,
12+
};
1013
use std::sync::atomic::Ordering;
1114

1215
pub(crate) fn provide(p: &mut Providers) {
@@ -40,6 +43,27 @@ fn normalize_projection_ty<'tcx>(
4043
&mut obligations,
4144
);
4245
ocx.register_obligations(obligations);
46+
// #112047: With projections and opaques, we are able to create opaques that
47+
// are recursive (given some substitution of the opaque's type variables).
48+
// In that case, we may only realize a cycle error when calling
49+
// `normalize_erasing_regions` in mono.
50+
if !ocx.infcx.next_trait_solver() {
51+
let errors = ocx.select_where_possible();
52+
if !errors.is_empty() {
53+
// Rustdoc may attempt to normalize type alias types which are not
54+
// well-formed. Rustdoc also normalizes types that are just not
55+
// well-formed, since we don't do as much HIR analysis (checking
56+
// that impl vars are constrained by the signature, for example).
57+
if !tcx.sess.opts.actually_rustdoc {
58+
for error in &errors {
59+
if let FulfillmentErrorCode::CodeCycle(cycle) = &error.code {
60+
ocx.infcx.err_ctxt().report_overflow_obligation_cycle(cycle);
61+
}
62+
}
63+
}
64+
return Err(NoSolution);
65+
}
66+
}
4367
// FIXME(associated_const_equality): All users of normalize_projection_ty expected
4468
// a type, but there is the possibility it could've been a const now. Maybe change
4569
// it to a Term later?
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// edition: 2021
2+
// build-fail
3+
//~^^ ERROR overflow evaluating the requirement `<A as Second>::{opaque#0} == _`
4+
5+
#![feature(async_fn_in_trait)]
6+
7+
fn main() {
8+
let _ = async {
9+
A.first().await.second().await;
10+
};
11+
}
12+
13+
pub trait First {
14+
type Second: Second;
15+
async fn first(self) -> Self::Second;
16+
}
17+
18+
struct A;
19+
20+
impl First for A {
21+
type Second = A;
22+
async fn first(self) -> Self::Second {
23+
A
24+
}
25+
}
26+
27+
pub trait Second {
28+
async fn second(self);
29+
}
30+
31+
impl<C> Second for C
32+
where
33+
C: First,
34+
{
35+
async fn second(self) {
36+
self.first().await.second().await;
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
error[E0275]: overflow evaluating the requirement `<A as Second>::{opaque#0} == _`
2+
3+
error: aborting due to previous error
4+
5+
For more information about this error, try `rustc --explain E0275`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// edition: 2021
2+
// build-fail
3+
//~^^ ERROR overflow evaluating the requirement `<() as Recur>::Recur == _`
4+
5+
#![feature(impl_trait_in_assoc_type)]
6+
7+
use core::future::Future;
8+
9+
trait Recur {
10+
type Recur: Future<Output = ()>;
11+
12+
fn recur(self) -> Self::Recur;
13+
}
14+
15+
async fn recur(t: impl Recur) {
16+
t.recur().await;
17+
}
18+
19+
impl Recur for () {
20+
type Recur = impl Future<Output = ()>;
21+
22+
fn recur(self) -> Self::Recur {
23+
async move { recur(self).await; }
24+
}
25+
}
26+
27+
fn main() {
28+
recur(());
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
error[E0275]: overflow evaluating the requirement `<() as Recur>::Recur == _`
2+
3+
error: aborting due to previous error
4+
5+
For more information about this error, try `rustc --explain E0275`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// edition: 2021
2+
// build-fail
3+
//~^^ ERROR overflow evaluating the requirement `<() as B>::Assoc == _`
4+
5+
#![feature(rustc_attrs)]
6+
#![feature(impl_trait_in_assoc_type)]
7+
8+
#[rustc_coinductive]
9+
trait A {
10+
type Assoc;
11+
12+
fn test() -> Self::Assoc;
13+
}
14+
15+
#[rustc_coinductive]
16+
trait B {
17+
type Assoc;
18+
19+
fn test() -> Self::Assoc;
20+
}
21+
22+
impl<T: A> B for T {
23+
type Assoc = impl Sized;
24+
25+
fn test() -> <Self as B>::Assoc {
26+
<T as A>::test()
27+
}
28+
}
29+
30+
fn main() {
31+
<() as A>::test();
32+
}
33+
34+
impl<T: B> A for T {
35+
type Assoc = impl Sized;
36+
37+
fn test() -> <Self as A>::Assoc {
38+
<T as B>::test()
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
error[E0275]: overflow evaluating the requirement `<() as B>::Assoc == _`
2+
3+
error: aborting due to previous error
4+
5+
For more information about this error, try `rustc --explain E0275`.

0 commit comments

Comments
 (0)