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 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
103 let term = with_short_path(self.tcx, term);
104 {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("overflow evaluating whether `{0}` is well-formed",
term))
})).with_code(E0275)
}struct_span_code_err!(
105 self.dcx(),
106 span,
107 E0275,
108 "overflow evaluating whether `{term}` is well-formed",
109 )
110 }
111 _ => {
112 let pred_str = with_short_path(self.tcx, predicate);
113 {
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!(
114 self.dcx(),
115 span,
116 E0275,
117 "overflow evaluating the requirement `{pred_str}`",
118 )
119 }
120 }
121 }
122 };
123
124 if suggest_increasing_limit {
125 suggest_new_overflow_limit(self.tcx, &mut err);
126 }
127
128 err
129 }
130
131 pub fn report_overflow_obligation<T>(
138 &self,
139 obligation: &Obligation<'tcx, T>,
140 suggest_increasing_limit: bool,
141 ) -> !
142 where
143 T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>> + Clone,
144 {
145 let predicate = obligation.predicate.clone().upcast(self.tcx);
146 let predicate = self.resolve_vars_if_possible(predicate);
147 self.report_overflow_error(
148 OverflowCause::TraitSolver(predicate),
149 obligation.cause.span,
150 suggest_increasing_limit,
151 |err| {
152 self.note_obligation_cause_code(
153 obligation.cause.body_id,
154 err,
155 predicate,
156 obligation.param_env,
157 obligation.cause.code(),
158 &mut ::alloc::vec::Vec::new()vec![],
159 &mut Default::default(),
160 );
161 },
162 );
163 }
164
165 pub fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
171 let cycle = self.resolve_vars_if_possible(cycle.to_owned());
172 if !!cycle.is_empty() {
::core::panicking::panic("assertion failed: !cycle.is_empty()")
};assert!(!cycle.is_empty());
173
174 {
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:174",
"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(174u32),
::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");
175
176 self.report_overflow_obligation(
179 cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(),
180 false,
181 );
182 }
183
184 pub fn report_overflow_no_abort(
185 &self,
186 obligation: PredicateObligation<'tcx>,
187 suggest_increasing_limit: bool,
188 ) -> ErrorGuaranteed {
189 let obligation = self.resolve_vars_if_possible(obligation);
190 let mut err = self.build_overflow_error(
191 OverflowCause::TraitSolver(obligation.predicate),
192 obligation.cause.span,
193 suggest_increasing_limit,
194 );
195 self.note_obligation_cause(&mut err, &obligation);
196 err.emit()
197 }
198}