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}
;
8 use rustc_errors
::{Diag, Subdiagnostic}
;
9 use rustc_hir
::def_id
::{DefId, LocalDefId}
;
10 use rustc_middle
::traits
::ObligationCauseCode
;
11 use rustc_middle
::ty
::error
::TypeError
;
12 use rustc_middle
::ty
::{self, IsSuggestable, Region, Ty}
;
13 use rustc_span
::symbol
::kw
;
15 use super::ObligationCauseAsDiagArg
;
17 impl<'tcx
> TypeErrCtxt
<'_
, 'tcx
> {
18 pub(super) fn note_region_origin(&self, err
: &mut Diag
<'_
>, origin
: &SubregionOrigin
<'tcx
>) {
20 infer
::Subtype(ref trace
) => RegionOriginNote
::WithRequirement
{
21 span
: trace
.cause
.span
,
22 requirement
: ObligationCauseAsDiagArg(trace
.cause
.clone()),
23 expected_found
: self.values_str(trace
.values
).map(|(e
, f
, _
)| (e
, f
)),
26 infer
::Reborrow(span
) => {
27 RegionOriginNote
::Plain { span, msg: fluent::infer_reborrow }
.add_to_diag(err
)
29 infer
::RelateObjectBound(span
) => {
30 RegionOriginNote
::Plain { span, msg: fluent::infer_relate_object_bound }
33 infer
::ReferenceOutlivesReferent(ty
, span
) => {
34 RegionOriginNote
::WithName
{
36 msg
: fluent
::infer_reference_outlives_referent
,
37 name
: &self.ty_to_string(ty
),
42 infer
::RelateParamBound(span
, ty
, opt_span
) => {
43 RegionOriginNote
::WithName
{
45 msg
: fluent
::infer_relate_param_bound
,
46 name
: &self.ty_to_string(ty
),
47 continues
: opt_span
.is_some(),
50 if let Some(span
) = opt_span
{
51 RegionOriginNote
::Plain { span, msg: fluent::infer_relate_param_bound_2 }
55 infer
::RelateRegionParamBound(span
) => {
56 RegionOriginNote
::Plain { span, msg: fluent::infer_relate_region_param_bound }
59 infer
::CompareImplItemObligation { span, .. }
=> {
60 RegionOriginNote
::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
63 infer
::CheckAssociatedTypeBounds { ref parent, .. }
=> {
64 self.note_region_origin(err
, parent
);
66 infer
::AscribeUserTypeProvePredicate(span
) => {
67 RegionOriginNote
::Plain
{
69 msg
: fluent
::infer_ascribe_user_type_prove_predicate
,
76 pub(super) fn report_concrete_failure(
78 origin
: SubregionOrigin
<'tcx
>,
82 let mut err
= match origin
{
83 infer
::Subtype(box trace
) => {
84 let terr
= TypeError
::RegionsDoesNotOutlive(sup
, sub
);
85 let mut err
= self.report_and_explain_type_error(trace
, terr
);
87 (ty
::RePlaceholder(_
), ty
::RePlaceholder(_
)) => {}
88 (ty
::RePlaceholder(_
), _
) => {
89 note_and_explain_region(
94 " doesn't meet the lifetime requirements",
98 (_
, ty
::RePlaceholder(_
)) => {
99 note_and_explain_region(
102 "the required lifetime does not necessarily outlive ",
109 note_and_explain_region(self.tcx
, &mut err
, "", sup
, "...", None
);
110 note_and_explain_region(
113 "...does not necessarily outlive ",
122 infer
::Reborrow(span
) => {
123 let reference_valid
= note_and_explain
::RegionExplanation
::new(
127 note_and_explain
::PrefixKind
::RefValidFor
,
128 note_and_explain
::SuffixKind
::Continues
,
130 let content_valid
= note_and_explain
::RegionExplanation
::new(
134 note_and_explain
::PrefixKind
::ContentValidFor
,
135 note_and_explain
::SuffixKind
::Empty
,
137 self.dcx().create_err(OutlivesContent
{
139 notes
: reference_valid
.into_iter().chain(content_valid
).collect(),
142 infer
::RelateObjectBound(span
) => {
143 let object_valid
= note_and_explain
::RegionExplanation
::new(
147 note_and_explain
::PrefixKind
::TypeObjValidFor
,
148 note_and_explain
::SuffixKind
::Empty
,
150 let pointer_valid
= note_and_explain
::RegionExplanation
::new(
154 note_and_explain
::PrefixKind
::SourcePointerValidFor
,
155 note_and_explain
::SuffixKind
::Empty
,
157 self.dcx().create_err(OutlivesBound
{
159 notes
: object_valid
.into_iter().chain(pointer_valid
).collect(),
162 infer
::RelateParamBound(span
, ty
, opt_span
) => {
163 let prefix
= match *sub
{
164 ty
::ReStatic
=> note_and_explain
::PrefixKind
::TypeSatisfy
,
165 _
=> note_and_explain
::PrefixKind
::TypeOutlive
,
167 let suffix
= if opt_span
.is_some() {
168 note_and_explain
::SuffixKind
::ReqByBinding
170 note_and_explain
::SuffixKind
::Empty
172 let note
= note_and_explain
::RegionExplanation
::new(
173 self.tcx
, sub
, opt_span
, prefix
, suffix
,
175 self.dcx().create_err(FulfillReqLifetime
{
177 ty
: self.resolve_vars_if_possible(ty
),
181 infer
::RelateRegionParamBound(span
) => {
182 let param_instantiated
= note_and_explain
::RegionExplanation
::new(
186 note_and_explain
::PrefixKind
::LfParamInstantiatedWith
,
187 note_and_explain
::SuffixKind
::Empty
,
189 let param_must_outlive
= note_and_explain
::RegionExplanation
::new(
193 note_and_explain
::PrefixKind
::LfParamMustOutlive
,
194 note_and_explain
::SuffixKind
::Empty
,
196 self.dcx().create_err(LfBoundNotSatisfied
{
198 notes
: param_instantiated
.into_iter().chain(param_must_outlive
).collect(),
201 infer
::ReferenceOutlivesReferent(ty
, span
) => {
202 let pointer_valid
= note_and_explain
::RegionExplanation
::new(
206 note_and_explain
::PrefixKind
::PointerValidFor
,
207 note_and_explain
::SuffixKind
::Empty
,
209 let data_valid
= note_and_explain
::RegionExplanation
::new(
213 note_and_explain
::PrefixKind
::DataValidFor
,
214 note_and_explain
::SuffixKind
::Empty
,
216 self.dcx().create_err(RefLongerThanData
{
218 ty
: self.resolve_vars_if_possible(ty
),
219 notes
: pointer_valid
.into_iter().chain(data_valid
).collect(),
222 infer
::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id }
=> {
223 let mut err
= self.report_extra_impl_obligation(
227 &format
!("`{sup}: {sub}`"),
229 // We should only suggest rewriting the `where` clause if the predicate is within that `where` clause
230 if let Some(generics
) = self.tcx
.hir().get_generics(impl_item_def_id
)
231 && generics
.where_clause_span
.contains(span
)
233 self.suggest_copy_trait_method_bounds(
241 infer
::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent }
=> {
242 let mut err
= self.report_concrete_failure(*parent
, sub
, sup
);
244 // Don't mention the item name if it's an RPITIT, since that'll just confuse
246 if !self.tcx
.is_impl_trait_in_trait(impl_item_def_id
.to_def_id()) {
247 let trait_item_span
= self.tcx
.def_span(trait_item_def_id
);
248 let item_name
= self.tcx
.item_name(impl_item_def_id
.to_def_id());
251 format
!("definition of `{item_name}` from trait"),
255 self.suggest_copy_trait_method_bounds(
262 infer
::AscribeUserTypeProvePredicate(span
) => {
263 let instantiated
= note_and_explain
::RegionExplanation
::new(
267 note_and_explain
::PrefixKind
::LfInstantiatedWith
,
268 note_and_explain
::SuffixKind
::Empty
,
270 let must_outlive
= note_and_explain
::RegionExplanation
::new(
274 note_and_explain
::PrefixKind
::LfMustOutlive
,
275 note_and_explain
::SuffixKind
::Empty
,
277 self.dcx().create_err(LfBoundNotSatisfied
{
279 notes
: instantiated
.into_iter().chain(must_outlive
).collect(),
283 if sub
.is_error() || sup
.is_error() {
284 err
.downgrade_to_delayed_bug();
289 pub fn suggest_copy_trait_method_bounds(
291 trait_item_def_id
: DefId
,
292 impl_item_def_id
: LocalDefId
,
295 // FIXME(compiler-errors): Right now this is only being used for region
296 // predicate mismatches. Ideally, we'd use it for *all* predicate mismatches,
297 // but right now it's not really very smart when it comes to implicit `Sized`
298 // predicates and bounds on the trait itself.
300 let Some(impl_def_id
) = self.tcx
.associated_item(impl_item_def_id
).impl_container(self.tcx
)
304 let Some(trait_ref
) = self.tcx
.impl_trait_ref(impl_def_id
) else {
307 let trait_args
= trait_ref
308 .instantiate_identity()
309 // Replace the explicit self type with `Self` for better suggestion rendering
310 .with_self_ty(self.tcx
, Ty
::new_param(self.tcx
, 0, kw
::SelfUpper
))
312 let trait_item_args
= ty
::GenericArgs
::identity_for_item(self.tcx
, impl_item_def_id
)
313 .rebase_onto(self.tcx
, impl_def_id
, trait_args
);
315 let Ok(trait_predicates
) =
317 .explicit_predicates_of(trait_item_def_id
)
318 .instantiate_own(self.tcx
, trait_item_args
)
320 if pred
.is_suggestable(self.tcx
, false) {
326 .collect
::<Result
<Vec
<_
>, ()>>()
331 let Some(generics
) = self.tcx
.hir().get_generics(impl_item_def_id
) else {
335 let suggestion
= if trait_predicates
.is_empty() {
336 WhereClauseSuggestions
::Remove { span: generics.where_clause_span }
338 let space
= if generics
.where_clause_span
.is_empty() { " " }
else { "" }
;
339 WhereClauseSuggestions
::CopyPredicates
{
340 span
: generics
.where_clause_span
,
342 trait_predicates
: trait_predicates
.join(", "),
345 err
.subdiagnostic(self.dcx(), suggestion
);
348 pub(super) fn report_placeholder_failure(
350 placeholder_origin
: SubregionOrigin
<'tcx
>,
354 // I can't think how to do better than this right now. -nikomatsakis
355 debug
!(?placeholder_origin
, ?sub
, ?sup
, "report_placeholder_failure");
356 match placeholder_origin
{
357 infer
::Subtype(box ref trace
)
359 &trace
.cause
.code().peel_derives(),
360 ObligationCauseCode
::BindingObligation(..)
361 | ObligationCauseCode
::ExprBindingObligation(..)
364 // Hack to get around the borrow checker because trace.cause has an `Rc`.
365 if let ObligationCauseCode
::BindingObligation(_
, span
)
366 | ObligationCauseCode
::ExprBindingObligation(_
, span
, ..) =
367 &trace
.cause
.code().peel_derives()
370 self.report_concrete_failure(placeholder_origin
, sub
, sup
)
371 .with_span_note(span
, "the lifetime requirement is introduced here")
374 "control flow ensures we have a `BindingObligation` or `ExprBindingObligation` here..."
378 infer
::Subtype(box trace
) => {
379 let terr
= TypeError
::RegionsPlaceholderMismatch
;
380 return self.report_and_explain_type_error(trace
, terr
);
382 _
=> return self.report_concrete_failure(placeholder_origin
, sub
, sup
),