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::query::Providers;
|
||||||
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
|
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
|
||||||
use rustc_trait_selection::infer::InferCtxtBuilderExt;
|
use rustc_trait_selection::infer::InferCtxtBuilderExt;
|
||||||
|
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||||
use rustc_trait_selection::traits::query::{
|
use rustc_trait_selection::traits::query::{
|
||||||
normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution,
|
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;
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
pub(crate) fn provide(p: &mut Providers) {
|
pub(crate) fn provide(p: &mut Providers) {
|
||||||
@ -40,6 +43,27 @@ fn normalize_projection_ty<'tcx>(
|
|||||||
&mut obligations,
|
&mut obligations,
|
||||||
);
|
);
|
||||||
ocx.register_obligations(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
|
// 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
|
// a type, but there is the possibility it could've been a const now. Maybe change
|
||||||
// it to a Term later?
|
// 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…
x
Reference in New Issue
Block a user