rustc_trait_selection/error_reporting/traits/
overflow.rs1use std::fmt;
2
3use rustc_errors::{Diag, E0275, ErrorGuaranteed, struct_span_code_err};
4use rustc_hir::def::Namespace;
5use rustc_hir::def_id::LOCAL_CRATE;
6use rustc_infer::traits::{Obligation, PredicateObligation};
7use rustc_middle::ty::print::{FmtPrinter, Print};
8use rustc_middle::ty::{self, TyCtxt, Upcast};
9use rustc_span::Span;
10use rustc_structures::Limit;
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>(tcx: TyCtxt<'tcx>, err: &mut Diag<'_>) {
21 let suggested_limit = match tcx.recursion_limit() {
22 Limit(0) => Limit(2),
23 limit => limit * 2,
24 };
25 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!(
26 "consider increasing the recursion limit by adding a \
27 `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
28 suggested_limit,
29 tcx.crate_name(LOCAL_CRATE),
30 ));
31}
32
33impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
34 pub fn report_overflow_error(
41 &self,
42 cause: OverflowCause<'tcx>,
43 span: Span,
44 suggest_increasing_limit: bool,
45 mutate: impl FnOnce(&mut Diag<'_>),
46 ) -> ! {
47 let mut err = self.build_overflow_error(cause, span, suggest_increasing_limit);
48 mutate(&mut err);
49 err.emit_err().raise_fatal();
50 }
51
52 pub fn build_overflow_error(
53 &self,
54 cause: OverflowCause<'tcx>,
55 span: Span,
56 suggest_increasing_limit: bool,
57 ) -> Diag<'a> {
58 fn with_short_path<'tcx, T>(tcx: TyCtxt<'tcx>, value: T) -> String
59 where
60 T: fmt::Display + for<'b> Print<FmtPrinter<'b, 'tcx>>,
61 {
62 let s = value.to_string();
63 if s.len() > 50 {
64 let mut p: FmtPrinter<'_, '_> =
67 FmtPrinter::new_with_limit(tcx, Namespace::TypeNS, Limit(6));
68 value.print(&mut p).unwrap();
69 p.into_buffer()
70 } else {
71 s
72 }
73 }
74
75 let mut err = match cause {
76 OverflowCause::DeeplyNormalize(alias_term) => {
77 let alias_term = self.deeply_resolve_ignoring_regions(alias_term);
78 let kind = alias_term.kind.descr();
79 let alias_str = with_short_path(self.tcx, alias_term);
80 {
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!(
81 self.dcx(),
82 span,
83 E0275,
84 "overflow normalizing the {kind} `{alias_str}`",
85 )
86 }
87 OverflowCause::TraitSolver(predicate) => {
88 let predicate = self.deeply_resolve_ignoring_regions(predicate);
89 match predicate.kind().skip_binder() {
90 ty::PredicateKind::Subtype(ty::SubtypePredicate { a, b, a_is_expected: _ })
91 | ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => {
92 {
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!(
93 self.dcx(),
94 span,
95 E0275,
96 "overflow assigning `{a}` to `{b}`",
97 )
98 }
99 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
100 let term = with_short_path(self.tcx, term);
101 {
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!(
102 self.dcx(),
103 span,
104 E0275,
105 "overflow evaluating whether `{term}` is well-formed",
106 )
107 }
108 _ => {
109 let pred_str = with_short_path(self.tcx, predicate);
110 {
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!(
111 self.dcx(),
112 span,
113 E0275,
114 "overflow evaluating the requirement `{pred_str}`",
115 )
116 }
117 }
118 }
119 };
120
121 if suggest_increasing_limit {
122 suggest_new_overflow_limit(self.tcx, &mut err);
123 }
124
125 err
126 }
127
128 pub fn report_overflow_obligation<T>(
135 &self,
136 obligation: &Obligation<'tcx, T>,
137 suggest_increasing_limit: bool,
138 ) -> !
139 where
140 T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>> + Clone,
141 {
142 let predicate = obligation.predicate.clone().upcast(self.tcx);
143 let predicate = self.deeply_resolve_ignoring_regions(predicate);
144 self.report_overflow_error(
145 OverflowCause::TraitSolver(predicate),
146 obligation.cause.span,
147 suggest_increasing_limit,
148 |err| {
149 self.note_obligation_cause_code(
150 obligation.cause.body_def_id,
151 err,
152 predicate,
153 obligation.param_env,
154 obligation.cause.code(),
155 &mut ::alloc::vec::Vec::new()vec![],
156 &mut Default::default(),
157 );
158 },
159 );
160 }
161
162 pub fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
168 let cycle = self.deeply_resolve_ignoring_regions(cycle.to_owned());
169 if !!cycle.is_empty() {
::core::panicking::panic("assertion failed: !cycle.is_empty()")
};assert!(!cycle.is_empty());
170
171 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs:171",
"rustc_trait_selection::error_reporting::traits::overflow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs"),
::tracing_core::__macro_support::Option::Some(171u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::overflow"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("cycle")
}> =
::tracing::__macro_support::FieldName::new("cycle");
NAME.as_str()
}], ::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("report_overflow_error_cycle")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cycle)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?cycle, "report_overflow_error_cycle");
172
173 self.report_overflow_obligation(
176 cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(),
177 false,
178 );
179 }
180
181 pub fn report_overflow_no_abort(
182 &self,
183 obligation: PredicateObligation<'tcx>,
184 suggest_increasing_limit: bool,
185 ) -> ErrorGuaranteed {
186 let obligation = self.deeply_resolve_ignoring_regions(obligation);
187 let mut err = self.build_overflow_error(
188 OverflowCause::TraitSolver(obligation.predicate),
189 obligation.cause.span,
190 suggest_increasing_limit,
191 );
192 self.note_obligation_cause(&mut err, &obligation);
193 err.emit_err()
194 }
195}