mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 00:03:43 +00:00
Detect cycle errors hidden by opaques during monomorphization
This commit is contained in:
parent
e5fedceabf
commit
8fbd78ccea
@ -3,10 +3,13 @@ use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
|
||||
use rustc_trait_selection::infer::InferCtxtBuilderExt;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::query::{
|
||||
normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution,
|
||||
};
|
||||
use rustc_trait_selection::traits::{self, ObligationCause, SelectionContext};
|
||||
use rustc_trait_selection::traits::{
|
||||
self, FulfillmentErrorCode, ObligationCause, SelectionContext,
|
||||
};
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
pub(crate) fn provide(p: &mut Providers) {
|
||||
@ -40,6 +43,27 @@ fn normalize_projection_ty<'tcx>(
|
||||
&mut obligations,
|
||||
);
|
||||
ocx.register_obligations(obligations);
|
||||
// #112047: With projections and opaques, we are able to create opaques that
|
||||
// are recursive (given some substitution of the opaque's type variables).
|
||||
// In that case, we may only realize a cycle error when calling
|
||||
// `normalize_erasing_regions` in mono.
|
||||
if !ocx.infcx.next_trait_solver() {
|
||||
let errors = ocx.select_where_possible();
|
||||
if !errors.is_empty() {
|
||||
// Rustdoc may attempt to normalize type alias types which are not
|
||||
// well-formed. Rustdoc also normalizes types that are just not
|
||||
// well-formed, since we don't do as much HIR analysis (checking
|
||||
// that impl vars are constrained by the signature, for example).
|
||||
if !tcx.sess.opts.actually_rustdoc {
|
||||
for error in &errors {
|
||||
if let FulfillmentErrorCode::CodeCycle(cycle) = &error.code {
|
||||
ocx.infcx.err_ctxt().report_overflow_obligation_cycle(cycle);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Err(NoSolution);
|
||||
}
|
||||
}
|
||||
// FIXME(associated_const_equality): All users of normalize_projection_ty expected
|
||||
// a type, but there is the possibility it could've been a const now. Maybe change
|
||||
// it to a Term later?
|
||||
|
@ -0,0 +1,38 @@
|
||||
// edition: 2021
|
||||
// build-fail
|
||||
//~^^ ERROR overflow evaluating the requirement `<A as Second>::{opaque#0} == _`
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
|
||||
fn main() {
|
||||
let _ = async {
|
||||
A.first().await.second().await;
|
||||
};
|
||||
}
|
||||
|
||||
pub trait First {
|
||||
type Second: Second;
|
||||
async fn first(self) -> Self::Second;
|
||||
}
|
||||
|
||||
struct A;
|
||||
|
||||
impl First for A {
|
||||
type Second = A;
|
||||
async fn first(self) -> Self::Second {
|
||||
A
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Second {
|
||||
async fn second(self);
|
||||
}
|
||||
|
||||
impl<C> Second for C
|
||||
where
|
||||
C: First,
|
||||
{
|
||||
async fn second(self) {
|
||||
self.first().await.second().await;
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
error[E0275]: overflow evaluating the requirement `<A as Second>::{opaque#0} == _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
@ -0,0 +1,29 @@
|
||||
// edition: 2021
|
||||
// build-fail
|
||||
//~^^ ERROR overflow evaluating the requirement `<() as Recur>::Recur == _`
|
||||
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
|
||||
use core::future::Future;
|
||||
|
||||
trait Recur {
|
||||
type Recur: Future<Output = ()>;
|
||||
|
||||
fn recur(self) -> Self::Recur;
|
||||
}
|
||||
|
||||
async fn recur(t: impl Recur) {
|
||||
t.recur().await;
|
||||
}
|
||||
|
||||
impl Recur for () {
|
||||
type Recur = impl Future<Output = ()>;
|
||||
|
||||
fn recur(self) -> Self::Recur {
|
||||
async move { recur(self).await; }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
recur(());
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
error[E0275]: overflow evaluating the requirement `<() as Recur>::Recur == _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
@ -0,0 +1,40 @@
|
||||
// edition: 2021
|
||||
// build-fail
|
||||
//~^^ ERROR overflow evaluating the requirement `<() as B>::Assoc == _`
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
|
||||
#[rustc_coinductive]
|
||||
trait A {
|
||||
type Assoc;
|
||||
|
||||
fn test() -> Self::Assoc;
|
||||
}
|
||||
|
||||
#[rustc_coinductive]
|
||||
trait B {
|
||||
type Assoc;
|
||||
|
||||
fn test() -> Self::Assoc;
|
||||
}
|
||||
|
||||
impl<T: A> B for T {
|
||||
type Assoc = impl Sized;
|
||||
|
||||
fn test() -> <Self as B>::Assoc {
|
||||
<T as A>::test()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
<() as A>::test();
|
||||
}
|
||||
|
||||
impl<T: B> A for T {
|
||||
type Assoc = impl Sized;
|
||||
|
||||
fn test() -> <Self as A>::Assoc {
|
||||
<T as B>::test()
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
error[E0275]: overflow evaluating the requirement `<() as B>::Assoc == _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
Loading…
Reference in New Issue
Block a user