rustc_trait_selection/error_reporting/traits/
overflow.rs1use std::fmt;
2
3use rustc_errors::{Diag, E0275, EmissionGuarantee, ErrorGuaranteed, struct_span_code_err};
4use rustc_hir::def::Namespace;
5use rustc_hir::def_id::LOCAL_CRATE;
6use rustc_hir::limit::Limit;
7use rustc_infer::traits::{Obligation, PredicateObligation};
8use rustc_middle::ty::print::{FmtPrinter, Print};
9use rustc_middle::ty::{self, TyCtxt, Upcast};
10use rustc_span::Span;
11use tracing::debug;
12
13use crate::error_reporting::TypeErrCtxt;
14
15pub enum OverflowCause<'tcx> {
16 DeeplyNormalize(ty::AliasTerm<'tcx>),
17 TraitSolver(ty::Predicate<'tcx>),
18}
19
20pub fn suggest_new_overflow_limit<'tcx, G: EmissionGuarantee>(
21 tcx: TyCtxt<'tcx>,
22 err: &mut Diag<'_, G>,
23) {
24 let suggested_limit = match tcx.recursion_limit() {
25 Limit(0) => Limit(2),
26 limit => limit * 2,
27 };
28 err.help(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider increasing the recursion limit by adding a `#![recursion_limit = \"{0}\"]` attribute to your crate (`{1}`)",
suggested_limit, tcx.crate_name(LOCAL_CRATE)))
})format!(
29 "consider increasing the recursion limit by adding a \
30 `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
31 suggested_limit,
32 tcx.crate_name(LOCAL_CRATE),
33 ));
34}
35
36impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
37 pub fn report_overflow_error(
44 &self,
45 cause: OverflowCause<'tcx>,
46 span: Span,
47 suggest_increasing_limit: bool,
48 mutate: impl FnOnce(&mut Diag<'_>),
49 ) -> ! {
50 let mut err = self.build_overflow_error(cause, span, suggest_increasing_limit);
51 mutate(&mut err);
52 err.emit().raise_fatal();
53 }
54
55 pub fn build_overflow_error(
56 &self,
57 cause: OverflowCause<'tcx>,
58 span: Span,
59 suggest_increasing_limit: bool,
60 ) -> Diag<'a> {
61 fn with_short_path<'tcx, T>(tcx: TyCtxt<'tcx>, value: T) -> String
62 where
63 T: fmt::Display + Print<'tcx, FmtPrinter<'tcx, 'tcx>>,
64 {
65 let s = value.to_string();
66 if s.len() > 50 {
67 let mut p: FmtPrinter<'_, '_> =
70 FmtPrinter::new_with_limit(tcx, Namespace::TypeNS, Limit(6));
71 value.print(&mut p).unwrap();
72 p.into_buffer()
73 } else {
74 s
75 }
76 }
77
78 let mut err = match cause {
79 OverflowCause::DeeplyNormalize(alias_term) => {
80 let alias_term = self.resolve_vars_if_possible(alias_term);
81 let kind = alias_term.kind(self.tcx).descr();
82 let alias_str = with_short_path(self.tcx, alias_term);
83 {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("overflow normalizing the {0} `{1}`",
kind, alias_str))
})).with_code(E0275)
}struct_span_code_err!(
84 self.dcx(),
85 span,
86 E0275,
87 "overflow normalizing the {kind} `{alias_str}`",
88 )
89 }
90 OverflowCause::TraitSolver(predicate) => {
91 let predicate = self.resolve_vars_if_possible(predicate);
92 match predicate.kind().skip_binder() {
93 ty::PredicateKind::Subtype(ty::SubtypePredicate { a, b, a_is_expected: _ })
94 | ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => {
95 {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("overflow assigning `{0}` to `{1}`",
a, b))
})).with_code(E0275)
}struct_span_code_err!(
96 self.dcx(),
97 span,
98 E0275,
99 "overflow assigning `{a}` to `{b}`",
100 )
101 }
102 _ => {
103 let pred_str = with_short_path(self.tcx, predicate);
104 {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("overflow evaluating the requirement `{0}`",
pred_str))
})).with_code(E0275)
}struct_span_code_err!(
105 self.dcx(),
106 span,
107 E0275,
108 "overflow evaluating the requirement `{pred_str}`",
109 )
110 }
111 }
112 }
113 };
114
115 if suggest_increasing_limit {
116 suggest_new_overflow_limit(self.tcx, &mut err);
117 }
118
119 err
120 }
121
122 pub fn report_overflow_obligation<T>(
129 &self,
130 obligation: &Obligation<'tcx, T>,
131 suggest_increasing_limit: bool,
132 ) -> !
133 where
134 T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>> + Clone,
135 {
136 let predicate = obligation.predicate.clone().upcast(self.tcx);
137 let predicate = self.resolve_vars_if_possible(predicate);
138 self.report_overflow_error(
139 OverflowCause::TraitSolver(predicate),
140 obligation.cause.span,
141 suggest_increasing_limit,
142 |err| {
143 self.note_obligation_cause_code(
144 obligation.cause.body_id,
145 err,
146 predicate,
147 obligation.param_env,
148 obligation.cause.code(),
149 &mut ::alloc::vec::Vec::new()vec![],
150 &mut Default::default(),
151 );
152 },
153 );
154 }
155
156 pub fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
162 let cycle = self.resolve_vars_if_possible(cycle.to_owned());
163 if !!cycle.is_empty() {
::core::panicking::panic("assertion failed: !cycle.is_empty()")
};assert!(!cycle.is_empty());
164
165 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs:165",
"rustc_trait_selection::error_reporting::traits::overflow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs"),
::tracing_core::__macro_support::Option::Some(165u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::overflow"),
::tracing_core::field::FieldSet::new(&["message", "cycle"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("report_overflow_error_cycle")
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&cycle) as
&dyn Value))])
});
} else { ; }
};debug!(?cycle, "report_overflow_error_cycle");
166
167 self.report_overflow_obligation(
170 cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(),
171 false,
172 );
173 }
174
175 pub fn report_overflow_no_abort(
176 &self,
177 obligation: PredicateObligation<'tcx>,
178 suggest_increasing_limit: bool,
179 ) -> ErrorGuaranteed {
180 let obligation = self.resolve_vars_if_possible(obligation);
181 let mut err = self.build_overflow_error(
182 OverflowCause::TraitSolver(obligation.predicate),
183 obligation.cause.span,
184 suggest_increasing_limit,
185 );
186 self.note_obligation_cause(&mut err, &obligation);
187 err.emit()
188 }
189}