-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Improve errors for recursive type aliases #88121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2f48bfa
cd0fc44
bf360dc
c861964
c3df832
d96234b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
use rustc_hir::def::DefKind; | ||
use rustc_query_system::query::SimpleDefKind; | ||
|
||
/// Convert a [`DefKind`] to a [`SimpleDefKind`]. | ||
/// | ||
/// *See [`SimpleDefKind`]'s docs for more information.* | ||
pub(crate) fn def_kind_to_simple_def_kind(def_kind: DefKind) -> SimpleDefKind { | ||
match def_kind { | ||
DefKind::Struct => SimpleDefKind::Struct, | ||
DefKind::Enum => SimpleDefKind::Enum, | ||
DefKind::Union => SimpleDefKind::Union, | ||
DefKind::Trait => SimpleDefKind::Trait, | ||
DefKind::TyAlias => SimpleDefKind::TyAlias, | ||
DefKind::TraitAlias => SimpleDefKind::TraitAlias, | ||
|
||
_ => SimpleDefKind::Other, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
use crate::dep_graph::DepContext; | ||
use crate::query::plumbing::CycleError; | ||
use crate::query::{QueryContext, QueryStackFrame}; | ||
use crate::query::{QueryContext, QueryStackFrame, SimpleDefKind}; | ||
|
||
use rustc_data_structures::fx::FxHashMap; | ||
use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, Handler, Level}; | ||
|
@@ -591,10 +591,33 @@ pub(crate) fn report_cycle<'a>( | |
err.span_note(span, &format!("...which requires {}...", query.description)); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm intrigued if the iteration above doesn't need to be reverted to be correct 🤔 (no need to address now) |
||
|
||
err.note(&format!( | ||
"...which again requires {}, completing the cycle", | ||
stack[0].query.description | ||
)); | ||
if stack.len() == 1 { | ||
err.note(&format!("...which immediately requires {} again", stack[0].query.description)); | ||
} else { | ||
err.note(&format!( | ||
"...which again requires {}, completing the cycle", | ||
stack[0].query.description | ||
)); | ||
} | ||
|
||
if stack.iter().all(|entry| { | ||
entry.query.def_kind.map_or(false, |def_kind| { | ||
matches!(def_kind, SimpleDefKind::TyAlias | SimpleDefKind::TraitAlias) | ||
}) | ||
}) { | ||
if stack.iter().all(|entry| { | ||
entry | ||
.query | ||
.def_kind | ||
.map_or(false, |def_kind| matches!(def_kind, SimpleDefKind::TyAlias)) | ||
}) { | ||
err.note("type aliases cannot be recursive"); | ||
err.help("consider using a struct, enum, or union instead to break the cycle"); | ||
err.help("see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information"); | ||
} else { | ||
err.note("trait aliases cannot be recursive"); | ||
} | ||
} | ||
|
||
if let Some((span, query)) = usage { | ||
err.span_note(fix_span(span, &query), &format!("cycle used when {}", query.description)); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#![feature(trait_alias)] | ||
|
||
trait T1 = T2; | ||
//~^ ERROR cycle detected when computing the super predicates of `T1` | ||
|
||
trait T2 = T3; | ||
|
||
trait T3 = T1 + T3; | ||
|
||
fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
error[E0391]: cycle detected when computing the super predicates of `T1` | ||
--> $DIR/infinite-trait-alias-recursion.rs:3:1 | ||
| | ||
LL | trait T1 = T2; | ||
| ^^^^^^^^^^^^^^ | ||
Comment on lines
+1
to
+5
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should likely point at only |
||
| | ||
note: ...which requires computing the super traits of `T1`... | ||
--> $DIR/infinite-trait-alias-recursion.rs:3:12 | ||
| | ||
LL | trait T1 = T2; | ||
| ^^ | ||
note: ...which requires computing the super predicates of `T2`... | ||
--> $DIR/infinite-trait-alias-recursion.rs:6:1 | ||
| | ||
LL | trait T2 = T3; | ||
| ^^^^^^^^^^^^^^ | ||
note: ...which requires computing the super traits of `T2`... | ||
--> $DIR/infinite-trait-alias-recursion.rs:6:12 | ||
| | ||
LL | trait T2 = T3; | ||
| ^^ | ||
note: ...which requires computing the super predicates of `T3`... | ||
--> $DIR/infinite-trait-alias-recursion.rs:8:1 | ||
| | ||
LL | trait T3 = T1 + T3; | ||
| ^^^^^^^^^^^^^^^^^^^ | ||
note: ...which requires computing the super traits of `T3`... | ||
--> $DIR/infinite-trait-alias-recursion.rs:8:12 | ||
| | ||
LL | trait T3 = T1 + T3; | ||
| ^^ | ||
= note: ...which again requires computing the super predicates of `T1`, completing the cycle | ||
= note: trait aliases cannot be recursive | ||
note: cycle used when collecting item types in top-level module | ||
--> $DIR/infinite-trait-alias-recursion.rs:3:1 | ||
| | ||
LL | trait T1 = T2; | ||
| ^^^^^^^^^^^^^^ | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0391`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
type X1 = X2; | ||
//~^ ERROR cycle detected when expanding type alias `X1` | ||
type X2 = X3; | ||
type X3 = X1; | ||
|
||
fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
error[E0391]: cycle detected when expanding type alias `X1` | ||
--> $DIR/infinite-type-alias-mutual-recursion.rs:1:11 | ||
| | ||
LL | type X1 = X2; | ||
| ^^ | ||
| | ||
note: ...which requires expanding type alias `X2`... | ||
--> $DIR/infinite-type-alias-mutual-recursion.rs:3:11 | ||
| | ||
LL | type X2 = X3; | ||
| ^^ | ||
note: ...which requires expanding type alias `X3`... | ||
--> $DIR/infinite-type-alias-mutual-recursion.rs:4:11 | ||
| | ||
LL | type X3 = X1; | ||
| ^^ | ||
= note: ...which again requires expanding type alias `X1`, completing the cycle | ||
= note: type aliases cannot be recursive | ||
= help: consider using a struct, enum, or union instead to break the cycle | ||
= help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information | ||
note: cycle used when collecting item types in top-level module | ||
--> $DIR/infinite-type-alias-mutual-recursion.rs:1:1 | ||
| | ||
LL | / type X1 = X2; | ||
LL | | | ||
LL | | type X2 = X3; | ||
LL | | type X3 = X1; | ||
LL | | | ||
LL | | fn main() {} | ||
| |____________^ | ||
Comment on lines
+21
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This reminds me, we need a way to talk about files without showing a snippet. |
||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0391`. |
Uh oh!
There was an error while loading. Please reload this page.