2 note_and_explain
, FulfillReqLifetime
, LfBoundNotSatisfied
, OutlivesBound
, OutlivesContent
,
3 RefLongerThanData
, RegionOriginNote
, WhereClauseSuggestions
,
5 use crate::fluent_generated
as fluent
;
6 use crate::infer
::error_reporting
::{note_and_explain_region, TypeErrCtxt}
;
7 use crate::infer
::{self, SubregionOrigin}
;
9 AddToDiagnostic
, Diagnostic
, DiagnosticBuilder
, ErrorGuaranteed
, IntoDiagnostic
,
11 use rustc_hir
::def_id
::{DefId, LocalDefId}
;
12 use rustc_middle
::traits
::ObligationCauseCode
;
13 use rustc_middle
::ty
::error
::TypeError
;
14 use rustc_middle
::ty
::{self, IsSuggestable, Region}
;
15 use rustc_span
::symbol
::kw
;
17 use super::ObligationCauseAsDiagArg
;
19 impl<'tcx
> TypeErrCtxt
<'_
, 'tcx
> {
20 pub(super) fn note_region_origin(&self, err
: &mut Diagnostic
, origin
: &SubregionOrigin
<'tcx
>) {
22 infer
::Subtype(ref trace
) => RegionOriginNote
::WithRequirement
{
23 span
: trace
.cause
.span
,
24 requirement
: ObligationCauseAsDiagArg(trace
.cause
.clone()),
25 expected_found
: self.values_str(trace
.values
).map(|(e
, f
, _
, _
)| (e
, f
)),
27 .add_to_diagnostic(err
),
28 infer
::Reborrow(span
) => {
29 RegionOriginNote
::Plain { span, msg: fluent::infer_reborrow }
.add_to_diagnostic(err
)
31 infer
::RelateObjectBound(span
) => {
32 RegionOriginNote
::Plain { span, msg: fluent::infer_relate_object_bound }
33 .add_to_diagnostic(err
);
35 infer
::ReferenceOutlivesReferent(ty
, span
) => {
36 RegionOriginNote
::WithName
{
38 msg
: fluent
::infer_reference_outlives_referent
,
39 name
: &self.ty_to_string(ty
),
42 .add_to_diagnostic(err
);
44 infer
::RelateParamBound(span
, ty
, opt_span
) => {
45 RegionOriginNote
::WithName
{
47 msg
: fluent
::infer_relate_param_bound
,
48 name
: &self.ty_to_string(ty
),
49 continues
: opt_span
.is_some(),
51 .add_to_diagnostic(err
);
52 if let Some(span
) = opt_span
{
53 RegionOriginNote
::Plain { span, msg: fluent::infer_relate_param_bound_2 }
54 .add_to_diagnostic(err
);
57 infer
::RelateRegionParamBound(span
) => {
58 RegionOriginNote
::Plain { span, msg: fluent::infer_relate_region_param_bound }
59 .add_to_diagnostic(err
);
61 infer
::CompareImplItemObligation { span, .. }
=> {
62 RegionOriginNote
::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
63 .add_to_diagnostic(err
);
65 infer
::CheckAssociatedTypeBounds { ref parent, .. }
=> {
66 self.note_region_origin(err
, &parent
);
68 infer
::AscribeUserTypeProvePredicate(span
) => {
69 RegionOriginNote
::Plain
{
71 msg
: fluent
::infer_ascribe_user_type_prove_predicate
,
73 .add_to_diagnostic(err
);
78 pub(super) fn report_concrete_failure(
80 origin
: SubregionOrigin
<'tcx
>,
83 ) -> DiagnosticBuilder
<'tcx
, ErrorGuaranteed
> {
84 let mut err
= match origin
{
85 infer
::Subtype(box trace
) => {
86 let terr
= TypeError
::RegionsDoesNotOutlive(sup
, sub
);
87 let mut err
= self.report_and_explain_type_error(trace
, terr
);
89 (ty
::RePlaceholder(_
), ty
::RePlaceholder(_
)) => {}
90 (ty
::RePlaceholder(_
), _
) => {
91 note_and_explain_region(
96 " doesn't meet the lifetime requirements",
100 (_
, ty
::RePlaceholder(_
)) => {
101 note_and_explain_region(
104 "the required lifetime does not necessarily outlive ",
111 note_and_explain_region(self.tcx
, &mut err
, "", sup
, "...", None
);
112 note_and_explain_region(
115 "...does not necessarily outlive ",
124 infer
::Reborrow(span
) => {
125 let reference_valid
= note_and_explain
::RegionExplanation
::new(
129 note_and_explain
::PrefixKind
::RefValidFor
,
130 note_and_explain
::SuffixKind
::Continues
,
132 let content_valid
= note_and_explain
::RegionExplanation
::new(
136 note_and_explain
::PrefixKind
::ContentValidFor
,
137 note_and_explain
::SuffixKind
::Empty
,
141 notes
: reference_valid
.into_iter().chain(content_valid
).collect(),
143 .into_diagnostic(&self.tcx
.sess
.parse_sess
.span_diagnostic
)
145 infer
::RelateObjectBound(span
) => {
146 let object_valid
= note_and_explain
::RegionExplanation
::new(
150 note_and_explain
::PrefixKind
::TypeObjValidFor
,
151 note_and_explain
::SuffixKind
::Empty
,
153 let pointer_valid
= note_and_explain
::RegionExplanation
::new(
157 note_and_explain
::PrefixKind
::SourcePointerValidFor
,
158 note_and_explain
::SuffixKind
::Empty
,
162 notes
: object_valid
.into_iter().chain(pointer_valid
).collect(),
164 .into_diagnostic(&self.tcx
.sess
.parse_sess
.span_diagnostic
)
166 infer
::RelateParamBound(span
, ty
, opt_span
) => {
167 let prefix
= match *sub
{
168 ty
::ReStatic
=> note_and_explain
::PrefixKind
::TypeSatisfy
,
169 _
=> note_and_explain
::PrefixKind
::TypeOutlive
,
171 let suffix
= if opt_span
.is_some() {
172 note_and_explain
::SuffixKind
::ReqByBinding
174 note_and_explain
::SuffixKind
::Empty
176 let note
= note_and_explain
::RegionExplanation
::new(
177 self.tcx
, sub
, opt_span
, prefix
, suffix
,
179 FulfillReqLifetime { span, ty: self.resolve_vars_if_possible(ty), note }
180 .into_diagnostic(&self.tcx
.sess
.parse_sess
.span_diagnostic
)
182 infer
::RelateRegionParamBound(span
) => {
183 let param_instantiated
= note_and_explain
::RegionExplanation
::new(
187 note_and_explain
::PrefixKind
::LfParamInstantiatedWith
,
188 note_and_explain
::SuffixKind
::Empty
,
190 let param_must_outlive
= note_and_explain
::RegionExplanation
::new(
194 note_and_explain
::PrefixKind
::LfParamMustOutlive
,
195 note_and_explain
::SuffixKind
::Empty
,
197 LfBoundNotSatisfied
{
199 notes
: param_instantiated
.into_iter().chain(param_must_outlive
).collect(),
201 .into_diagnostic(&self.tcx
.sess
.parse_sess
.span_diagnostic
)
203 infer
::ReferenceOutlivesReferent(ty
, span
) => {
204 let pointer_valid
= note_and_explain
::RegionExplanation
::new(
208 note_and_explain
::PrefixKind
::PointerValidFor
,
209 note_and_explain
::SuffixKind
::Empty
,
211 let data_valid
= note_and_explain
::RegionExplanation
::new(
215 note_and_explain
::PrefixKind
::DataValidFor
,
216 note_and_explain
::SuffixKind
::Empty
,
220 ty
: self.resolve_vars_if_possible(ty
),
221 notes
: pointer_valid
.into_iter().chain(data_valid
).collect(),
223 .into_diagnostic(&self.tcx
.sess
.parse_sess
.span_diagnostic
)
225 infer
::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id }
=> {
226 let mut err
= self.report_extra_impl_obligation(
230 &format
!("`{}: {}`", sup
, sub
),
232 // We should only suggest rewriting the `where` clause if the predicate is within that `where` clause
233 if let Some(generics
) = self.tcx
.hir().get_generics(impl_item_def_id
)
234 && generics
.where_clause_span
.contains(span
)
236 self.suggest_copy_trait_method_bounds(
244 infer
::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent }
=> {
245 let mut err
= self.report_concrete_failure(*parent
, sub
, sup
);
246 let trait_item_span
= self.tcx
.def_span(trait_item_def_id
);
247 let item_name
= self.tcx
.item_name(impl_item_def_id
.to_def_id());
250 format
!("definition of `{}` from trait", item_name
),
252 self.suggest_copy_trait_method_bounds(
259 infer
::AscribeUserTypeProvePredicate(span
) => {
260 let instantiated
= note_and_explain
::RegionExplanation
::new(
264 note_and_explain
::PrefixKind
::LfInstantiatedWith
,
265 note_and_explain
::SuffixKind
::Empty
,
267 let must_outlive
= note_and_explain
::RegionExplanation
::new(
271 note_and_explain
::PrefixKind
::LfMustOutlive
,
272 note_and_explain
::SuffixKind
::Empty
,
274 LfBoundNotSatisfied
{
276 notes
: instantiated
.into_iter().chain(must_outlive
).collect(),
278 .into_diagnostic(&self.tcx
.sess
.parse_sess
.span_diagnostic
)
281 if sub
.is_error() || sup
.is_error() {
287 pub fn suggest_copy_trait_method_bounds(
289 trait_item_def_id
: DefId
,
290 impl_item_def_id
: LocalDefId
,
291 err
: &mut Diagnostic
,
293 // FIXME(compiler-errors): Right now this is only being used for region
294 // predicate mismatches. Ideally, we'd use it for *all* predicate mismatches,
295 // but right now it's not really very smart when it comes to implicit `Sized`
296 // predicates and bounds on the trait itself.
298 let Some(impl_def_id
) =
299 self.tcx
.associated_item(impl_item_def_id
).impl_container(self.tcx
) else { return; }
;
300 let Some(trait_ref
) = self
302 .impl_trait_ref(impl_def_id
)
304 let trait_substs
= trait_ref
306 // Replace the explicit self type with `Self` for better suggestion rendering
307 .with_self_ty(self.tcx
, self.tcx
.mk_ty_param(0, kw
::SelfUpper
))
309 let trait_item_substs
= ty
::InternalSubsts
::identity_for_item(self.tcx
, impl_item_def_id
)
310 .rebase_onto(self.tcx
, impl_def_id
, trait_substs
);
312 let Ok(trait_predicates
) = self
314 .explicit_predicates_of(trait_item_def_id
)
315 .instantiate_own(self.tcx
, trait_item_substs
)
317 if pred
.is_suggestable(self.tcx
, false) {
323 .collect
::<Result
<Vec
<_
>, ()>>() else { return; }
;
325 let Some(generics
) = self.tcx
.hir().get_generics(impl_item_def_id
) else { return; }
;
327 let suggestion
= if trait_predicates
.is_empty() {
328 WhereClauseSuggestions
::Remove { span: generics.where_clause_span }
330 let space
= if generics
.where_clause_span
.is_empty() { " " }
else { "" }
;
331 WhereClauseSuggestions
::CopyPredicates
{
332 span
: generics
.where_clause_span
,
334 trait_predicates
: trait_predicates
.join(", "),
337 err
.subdiagnostic(suggestion
);
340 pub(super) fn report_placeholder_failure(
342 placeholder_origin
: SubregionOrigin
<'tcx
>,
345 ) -> DiagnosticBuilder
<'tcx
, ErrorGuaranteed
> {
346 // I can't think how to do better than this right now. -nikomatsakis
347 debug
!(?placeholder_origin
, ?sub
, ?sup
, "report_placeholder_failure");
348 match placeholder_origin
{
349 infer
::Subtype(box ref trace
)
351 &trace
.cause
.code().peel_derives(),
352 ObligationCauseCode
::BindingObligation(..)
353 | ObligationCauseCode
::ExprBindingObligation(..)
356 // Hack to get around the borrow checker because trace.cause has an `Rc`.
357 if let ObligationCauseCode
::BindingObligation(_
, span
)
358 | ObligationCauseCode
::ExprBindingObligation(_
, span
, ..) =
359 &trace
.cause
.code().peel_derives()
362 let mut err
= self.report_concrete_failure(placeholder_origin
, sub
, sup
);
363 err
.span_note(span
, "the lifetime requirement is introduced here");
369 infer
::Subtype(box trace
) => {
370 let terr
= TypeError
::RegionsPlaceholderMismatch
;
371 return self.report_and_explain_type_error(trace
, terr
);
373 _
=> return self.report_concrete_failure(placeholder_origin
, sub
, sup
),