|
1 | 1 | use crate::query::plumbing::CycleError;
|
2 | 2 | use crate::query::{QueryContext, QueryStackFrame};
|
3 |
| -use rustc_hir::def::DefKind; |
4 | 3 |
|
5 | 4 | use rustc_data_structures::fx::FxHashMap;
|
6 |
| -use rustc_errors::{ |
7 |
| - struct_span_err, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, Handler, Level, |
8 |
| -}; |
9 |
| -use rustc_session::Session; |
| 5 | +use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed, Handler, Level}; |
| 6 | +use rustc_hir::def::DefKind; |
| 7 | +use rustc_session::{Session, SessionDiagnostic}; |
10 | 8 | use rustc_span::Span;
|
11 | 9 |
|
12 | 10 | use std::hash::Hash;
|
@@ -536,46 +534,29 @@ pub(crate) fn report_cycle<'a>(
|
536 | 534 | assert!(!stack.is_empty());
|
537 | 535 |
|
538 | 536 | let span = stack[0].query.default_span(stack[1 % stack.len()].span);
|
539 |
| - let mut err = |
540 |
| - struct_span_err!(sess, span, E0391, "cycle detected when {}", stack[0].query.description); |
| 537 | + |
| 538 | + let mut cycle_diag = crate::error::Cycle { |
| 539 | + span, |
| 540 | + upper_stack_info: Vec::with_capacity(stack.len() - 1), |
| 541 | + stack_bottom: stack[0].query.description.to_owned(), |
| 542 | + recursive_ty_alias: false, |
| 543 | + recursive_trait_alias: false, |
| 544 | + cycle_usage: usage.map(|(span, query)| (query.default_span(span), query.description)), |
| 545 | + }; |
541 | 546 |
|
542 | 547 | for i in 1..stack.len() {
|
543 | 548 | let query = &stack[i].query;
|
544 | 549 | let span = query.default_span(stack[(i + 1) % stack.len()].span);
|
545 |
| - err.span_note(span, &format!("...which requires {}...", query.description)); |
546 |
| - } |
547 |
| - |
548 |
| - if stack.len() == 1 { |
549 |
| - err.note(&format!("...which immediately requires {} again", stack[0].query.description)); |
550 |
| - } else { |
551 |
| - err.note(&format!( |
552 |
| - "...which again requires {}, completing the cycle", |
553 |
| - stack[0].query.description |
554 |
| - )); |
555 |
| - } |
556 |
| - |
557 |
| - if stack.iter().all(|entry| { |
558 |
| - entry |
559 |
| - .query |
560 |
| - .def_kind |
561 |
| - .map_or(false, |def_kind| matches!(def_kind, DefKind::TyAlias | DefKind::TraitAlias)) |
562 |
| - }) { |
563 |
| - if stack.iter().all(|entry| { |
564 |
| - entry.query.def_kind.map_or(false, |def_kind| matches!(def_kind, DefKind::TyAlias)) |
565 |
| - }) { |
566 |
| - err.note("type aliases cannot be recursive"); |
567 |
| - err.help("consider using a struct, enum, or union instead to break the cycle"); |
568 |
| - err.help("see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information"); |
569 |
| - } else { |
570 |
| - err.note("trait aliases cannot be recursive"); |
571 |
| - } |
| 550 | + cycle_diag.upper_stack_info.push((span, query.description.to_owned())); |
572 | 551 | }
|
573 | 552 |
|
574 |
| - if let Some((span, query)) = usage { |
575 |
| - err.span_note(query.default_span(span), &format!("cycle used when {}", query.description)); |
| 553 | + if stack.iter().all(|entry| entry.query.def_kind == Some(DefKind::TyAlias)) { |
| 554 | + cycle_diag.recursive_ty_alias = true; |
| 555 | + } else if stack.iter().all(|entry| entry.query.def_kind == Some(DefKind::TraitAlias)) { |
| 556 | + cycle_diag.recursive_trait_alias = true; |
576 | 557 | }
|
577 | 558 |
|
578 |
| - err |
| 559 | + cycle_diag.into_diagnostic(&sess.parse_sess) |
579 | 560 | }
|
580 | 561 |
|
581 | 562 | pub fn print_query_stack<CTX: QueryContext>(
|
|
0 commit comments