Skip to content

Commit 8fc5ba6

Browse files
committed
Port OutlivesContent, OutlivesBound, FUllfillReqLifetime, LfBoundNotSatisfied diagnostics
1 parent 9bb6e60 commit 8fc5ba6

File tree

4 files changed

+131
-76
lines changed

4 files changed

+131
-76
lines changed

compiler/rustc_error_messages/locales/en-US/infer.ftl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,14 @@ infer_lifetime_param_suggestion_elided = each elided lifetime in input position
140140
141141
infer_region_explanation = {$pref_kind ->
142142
*[should_not_happen] [{$pref_kind}]
143+
[ref_valid_for] ...the reference is valid for
144+
[content_valid_for] ...but the borrowed content is only valid for
145+
[type_valid_for] object type is valid for
146+
[source_pointer_valid_for] source pointer is only valid for
147+
[type_satisfy] type must satisfy
148+
[type_outlive] type must outlive
149+
[lf_instantiated_with] lifetime parameter instantiated with
150+
[lf_must_outlive] but lifetime parameter must outlive
143151
[empty] {""}
144152
}{$pref_kind ->
145153
[empty] {""}
@@ -158,8 +166,14 @@ infer_region_explanation = {$pref_kind ->
158166
*[should_not_happen] [{$suff_kind}]
159167
[empty]{""}
160168
[continues] ...
169+
[req_by_binding] {" "}as required by this binding
161170
}
162171
172+
infer_outlives_content = lifetime of reference outlives lifetime of borrowed content...
173+
infer_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
174+
infer_fullfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
175+
infer_lf_bound_not_satisfied = lifetime bound not satisfied
176+
163177
infer_mismatched_static_lifetime = incompatible lifetime on type
164178
infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
165179
infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement

compiler/rustc_infer/src/errors/mod.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,3 +933,40 @@ pub struct ButNeedsToSatisfy {
933933
pub has_lifetime: bool,
934934
pub lifetime: String,
935935
}
936+
937+
#[derive(Diagnostic)]
938+
#[diag(infer_outlives_content, code = "E0312")]
939+
pub struct OutlivesContent<'a> {
940+
#[primary_span]
941+
pub span: Span,
942+
#[subdiagnostic]
943+
pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
944+
}
945+
946+
#[derive(Diagnostic)]
947+
#[diag(infer_outlives_bound, code = "E0476")]
948+
pub struct OutlivesBound<'a> {
949+
#[primary_span]
950+
pub span: Span,
951+
#[subdiagnostic]
952+
pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
953+
}
954+
955+
#[derive(Diagnostic)]
956+
#[diag(infer_fullfill_req_lifetime, code = "E0477")]
957+
pub struct FullfillReqLifetime<'a> {
958+
#[primary_span]
959+
pub span: Span,
960+
pub ty: Ty<'a>,
961+
#[subdiagnostic]
962+
pub note: Option<note_and_explain::RegionExplanation<'a>>,
963+
}
964+
965+
#[derive(Diagnostic)]
966+
#[diag(infer_lf_bound_not_satisfied, code = "E0478")]
967+
pub struct LfBoundNotSatisfied<'a> {
968+
#[primary_span]
969+
pub span: Span,
970+
#[subdiagnostic]
971+
pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
972+
}

compiler/rustc_infer/src/errors/note_and_explain.rs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,34 @@ impl<'a> DescriptionCtx<'a> {
121121

122122
pub enum PrefixKind {
123123
Empty,
124+
RefValidFor,
125+
ContentValidFor,
126+
TypeValidFor,
127+
SourcePointerValidFor,
128+
TypeSatisfy,
129+
TypeOutlive,
130+
LfInstantiatedWith,
131+
LfMustOutlive,
124132
}
125133

126134
pub enum SuffixKind {
135+
Empty,
127136
Continues,
137+
ReqByBinding,
128138
}
129139

130140
impl IntoDiagnosticArg for PrefixKind {
131141
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
132142
let kind = match self {
133143
Self::Empty => "empty",
144+
Self::RefValidFor => "ref_valid_for",
145+
Self::ContentValidFor => "content_valid_for",
146+
Self::TypeValidFor => "type_valid_for",
147+
Self::SourcePointerValidFor => "source_pointer_valid_for",
148+
Self::TypeSatisfy => "type_satisfy",
149+
Self::TypeOutlive => "type_outlive",
150+
Self::LfInstantiatedWith => "lf_instantiated_with",
151+
Self::LfMustOutlive => "lf_must_outlive",
134152
}
135153
.into();
136154
rustc_errors::DiagnosticArgValue::Str(kind)
@@ -140,7 +158,9 @@ impl IntoDiagnosticArg for PrefixKind {
140158
impl IntoDiagnosticArg for SuffixKind {
141159
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
142160
let kind = match self {
161+
Self::Empty => "empty",
143162
Self::Continues => "continues",
163+
Self::ReqByBinding => "req_by_binding",
144164
}
145165
.into();
146166
rustc_errors::DiagnosticArgValue::Str(kind)
@@ -166,17 +186,19 @@ impl RegionExplanation<'_> {
166186
}
167187

168188
impl AddToDiagnostic for RegionExplanation<'_> {
169-
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
189+
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
170190
where
171191
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
172192
{
173-
if let Some(span) = self.desc.span {
174-
diag.span_note(span, fluent::infer_region_explanation);
175-
} else {
176-
diag.note(fluent::infer_region_explanation);
177-
}
178-
self.desc.add_to(diag);
179193
diag.set_arg("pref_kind", self.prefix);
180194
diag.set_arg("suff_kind", self.suffix);
195+
let desc_span = self.desc.span;
196+
self.desc.add_to(diag);
197+
let msg = f(diag, fluent::infer_region_explanation.into());
198+
if let Some(span) = desc_span {
199+
diag.span_note(span, msg);
200+
} else {
201+
diag.note(msg);
202+
}
181203
}
182204
}

compiler/rustc_infer/src/infer/error_reporting/note.rs

Lines changed: 51 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
use crate::errors::RegionOriginNote;
1+
use crate::errors::{
2+
note_and_explain, FullfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent,
3+
RegionOriginNote,
4+
};
25
use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt};
36
use crate::infer::{self, SubregionOrigin};
47
use rustc_errors::{
58
fluent, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder,
6-
ErrorGuaranteed,
9+
ErrorGuaranteed, IntoDiagnostic,
710
};
811
use rustc_hir::def_id::{DefId, LocalDefId};
912
use rustc_middle::traits::ObligationCauseCode;
@@ -119,104 +122,83 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
119122
err
120123
}
121124
infer::Reborrow(span) => {
122-
let mut err = struct_span_err!(
123-
self.tcx.sess,
124-
span,
125-
E0312,
126-
"lifetime of reference outlives lifetime of borrowed content..."
127-
);
128-
note_and_explain_region(
125+
let reference_valid = note_and_explain::RegionExplanation::new(
129126
self.tcx,
130-
&mut err,
131-
"...the reference is valid for ",
132127
sub,
133-
"...",
134128
None,
129+
note_and_explain::PrefixKind::RefValidFor,
130+
note_and_explain::SuffixKind::Continues,
135131
);
136-
note_and_explain_region(
132+
let content_valid = note_and_explain::RegionExplanation::new(
137133
self.tcx,
138-
&mut err,
139-
"...but the borrowed content is only valid for ",
140134
sup,
141-
"",
142135
None,
136+
note_and_explain::PrefixKind::ContentValidFor,
137+
note_and_explain::SuffixKind::Empty,
143138
);
144-
err
139+
OutlivesContent {
140+
span,
141+
notes: reference_valid.into_iter().chain(content_valid).collect(),
142+
}
143+
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
145144
}
146145
infer::RelateObjectBound(span) => {
147-
let mut err = struct_span_err!(
148-
self.tcx.sess,
149-
span,
150-
E0476,
151-
"lifetime of the source pointer does not outlive lifetime bound of the \
152-
object type"
153-
);
154-
note_and_explain_region(
146+
let object_valid = note_and_explain::RegionExplanation::new(
155147
self.tcx,
156-
&mut err,
157-
"object type is valid for ",
158148
sub,
159-
"",
160149
None,
150+
note_and_explain::PrefixKind::TypeValidFor,
151+
note_and_explain::SuffixKind::Empty,
161152
);
162-
note_and_explain_region(
153+
let pointer_valid = note_and_explain::RegionExplanation::new(
163154
self.tcx,
164-
&mut err,
165-
"source pointer is only valid for ",
166155
sup,
167-
"",
168156
None,
157+
note_and_explain::PrefixKind::SourcePointerValidFor,
158+
note_and_explain::SuffixKind::Empty,
169159
);
170-
err
160+
OutlivesBound {
161+
span,
162+
notes: object_valid.into_iter().chain(pointer_valid).collect(),
163+
}
164+
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
171165
}
172166
infer::RelateParamBound(span, ty, opt_span) => {
173-
let mut err = struct_span_err!(
174-
self.tcx.sess,
175-
span,
176-
E0477,
177-
"the type `{}` does not fulfill the required lifetime",
178-
self.ty_to_string(ty)
167+
let prefix = match *sub {
168+
ty::ReStatic => note_and_explain::PrefixKind::TypeSatisfy,
169+
_ => note_and_explain::PrefixKind::TypeOutlive,
170+
};
171+
let suffix = if opt_span.is_some() {
172+
note_and_explain::SuffixKind::ReqByBinding
173+
} else {
174+
note_and_explain::SuffixKind::Empty
175+
};
176+
let note = note_and_explain::RegionExplanation::new(
177+
self.tcx, sub, opt_span, prefix, suffix,
179178
);
180-
match *sub {
181-
ty::ReStatic => note_and_explain_region(
182-
self.tcx,
183-
&mut err,
184-
"type must satisfy ",
185-
sub,
186-
if opt_span.is_some() { " as required by this binding" } else { "" },
187-
opt_span,
188-
),
189-
_ => note_and_explain_region(
190-
self.tcx,
191-
&mut err,
192-
"type must outlive ",
193-
sub,
194-
if opt_span.is_some() { " as required by this binding" } else { "" },
195-
opt_span,
196-
),
197-
}
198-
err
179+
FullfillReqLifetime { span, ty: self.resolve_vars_if_possible(ty), note }
180+
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
199181
}
200182
infer::RelateRegionParamBound(span) => {
201-
let mut err =
202-
struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
203-
note_and_explain_region(
183+
let param_instantiated = note_and_explain::RegionExplanation::new(
204184
self.tcx,
205-
&mut err,
206-
"lifetime parameter instantiated with ",
207185
sup,
208-
"",
209186
None,
187+
note_and_explain::PrefixKind::LfInstantiatedWith,
188+
note_and_explain::SuffixKind::Empty,
210189
);
211-
note_and_explain_region(
190+
let param_must_outlive = note_and_explain::RegionExplanation::new(
212191
self.tcx,
213-
&mut err,
214-
"but lifetime parameter must outlive ",
215192
sub,
216-
"",
217193
None,
194+
note_and_explain::PrefixKind::LfMustOutlive,
195+
note_and_explain::SuffixKind::Empty,
218196
);
219-
err
197+
LfBoundNotSatisfied {
198+
span,
199+
notes: param_instantiated.into_iter().chain(param_must_outlive).collect(),
200+
}
201+
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
220202
}
221203
infer::ReferenceOutlivesReferent(ty, span) => {
222204
let mut err = struct_span_err!(

0 commit comments

Comments
 (0)