|
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