Port OutlivesContent, OutlivesBound, FUllfillReqLifetime, LfBoundNotSatisfied diagnostics
This commit is contained in:
parent
9bb6e60d1f
commit
8fc5ba65e1
4 changed files with 131 additions and 76 deletions
|
@ -140,6 +140,14 @@ infer_lifetime_param_suggestion_elided = each elided lifetime in input position
|
||||||
|
|
||||||
infer_region_explanation = {$pref_kind ->
|
infer_region_explanation = {$pref_kind ->
|
||||||
*[should_not_happen] [{$pref_kind}]
|
*[should_not_happen] [{$pref_kind}]
|
||||||
|
[ref_valid_for] ...the reference is valid for
|
||||||
|
[content_valid_for] ...but the borrowed content is only valid for
|
||||||
|
[type_valid_for] object type is valid for
|
||||||
|
[source_pointer_valid_for] source pointer is only valid for
|
||||||
|
[type_satisfy] type must satisfy
|
||||||
|
[type_outlive] type must outlive
|
||||||
|
[lf_instantiated_with] lifetime parameter instantiated with
|
||||||
|
[lf_must_outlive] but lifetime parameter must outlive
|
||||||
[empty] {""}
|
[empty] {""}
|
||||||
}{$pref_kind ->
|
}{$pref_kind ->
|
||||||
[empty] {""}
|
[empty] {""}
|
||||||
|
@ -158,8 +166,14 @@ infer_region_explanation = {$pref_kind ->
|
||||||
*[should_not_happen] [{$suff_kind}]
|
*[should_not_happen] [{$suff_kind}]
|
||||||
[empty]{""}
|
[empty]{""}
|
||||||
[continues] ...
|
[continues] ...
|
||||||
|
[req_by_binding] {" "}as required by this binding
|
||||||
}
|
}
|
||||||
|
|
||||||
|
infer_outlives_content = lifetime of reference outlives lifetime of borrowed content...
|
||||||
|
infer_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
|
||||||
|
infer_fullfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
|
||||||
|
infer_lf_bound_not_satisfied = lifetime bound not satisfied
|
||||||
|
|
||||||
infer_mismatched_static_lifetime = incompatible lifetime on type
|
infer_mismatched_static_lifetime = incompatible lifetime on type
|
||||||
infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
|
infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
|
||||||
infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
|
infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
|
||||||
|
|
|
@ -933,3 +933,40 @@ pub struct ButNeedsToSatisfy {
|
||||||
pub has_lifetime: bool,
|
pub has_lifetime: bool,
|
||||||
pub lifetime: String,
|
pub lifetime: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(infer_outlives_content, code = "E0312")]
|
||||||
|
pub struct OutlivesContent<'a> {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(infer_outlives_bound, code = "E0476")]
|
||||||
|
pub struct OutlivesBound<'a> {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(infer_fullfill_req_lifetime, code = "E0477")]
|
||||||
|
pub struct FullfillReqLifetime<'a> {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub ty: Ty<'a>,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub note: Option<note_and_explain::RegionExplanation<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(infer_lf_bound_not_satisfied, code = "E0478")]
|
||||||
|
pub struct LfBoundNotSatisfied<'a> {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
|
||||||
|
}
|
||||||
|
|
|
@ -121,16 +121,34 @@ impl<'a> DescriptionCtx<'a> {
|
||||||
|
|
||||||
pub enum PrefixKind {
|
pub enum PrefixKind {
|
||||||
Empty,
|
Empty,
|
||||||
|
RefValidFor,
|
||||||
|
ContentValidFor,
|
||||||
|
TypeValidFor,
|
||||||
|
SourcePointerValidFor,
|
||||||
|
TypeSatisfy,
|
||||||
|
TypeOutlive,
|
||||||
|
LfInstantiatedWith,
|
||||||
|
LfMustOutlive,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum SuffixKind {
|
pub enum SuffixKind {
|
||||||
|
Empty,
|
||||||
Continues,
|
Continues,
|
||||||
|
ReqByBinding,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoDiagnosticArg for PrefixKind {
|
impl IntoDiagnosticArg for PrefixKind {
|
||||||
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
||||||
let kind = match self {
|
let kind = match self {
|
||||||
Self::Empty => "empty",
|
Self::Empty => "empty",
|
||||||
|
Self::RefValidFor => "ref_valid_for",
|
||||||
|
Self::ContentValidFor => "content_valid_for",
|
||||||
|
Self::TypeValidFor => "type_valid_for",
|
||||||
|
Self::SourcePointerValidFor => "source_pointer_valid_for",
|
||||||
|
Self::TypeSatisfy => "type_satisfy",
|
||||||
|
Self::TypeOutlive => "type_outlive",
|
||||||
|
Self::LfInstantiatedWith => "lf_instantiated_with",
|
||||||
|
Self::LfMustOutlive => "lf_must_outlive",
|
||||||
}
|
}
|
||||||
.into();
|
.into();
|
||||||
rustc_errors::DiagnosticArgValue::Str(kind)
|
rustc_errors::DiagnosticArgValue::Str(kind)
|
||||||
|
@ -140,7 +158,9 @@ impl IntoDiagnosticArg for PrefixKind {
|
||||||
impl IntoDiagnosticArg for SuffixKind {
|
impl IntoDiagnosticArg for SuffixKind {
|
||||||
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
||||||
let kind = match self {
|
let kind = match self {
|
||||||
|
Self::Empty => "empty",
|
||||||
Self::Continues => "continues",
|
Self::Continues => "continues",
|
||||||
|
Self::ReqByBinding => "req_by_binding",
|
||||||
}
|
}
|
||||||
.into();
|
.into();
|
||||||
rustc_errors::DiagnosticArgValue::Str(kind)
|
rustc_errors::DiagnosticArgValue::Str(kind)
|
||||||
|
@ -166,17 +186,19 @@ impl RegionExplanation<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddToDiagnostic for RegionExplanation<'_> {
|
impl AddToDiagnostic for RegionExplanation<'_> {
|
||||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
|
||||||
where
|
where
|
||||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
{
|
{
|
||||||
if let Some(span) = self.desc.span {
|
|
||||||
diag.span_note(span, fluent::infer_region_explanation);
|
|
||||||
} else {
|
|
||||||
diag.note(fluent::infer_region_explanation);
|
|
||||||
}
|
|
||||||
self.desc.add_to(diag);
|
|
||||||
diag.set_arg("pref_kind", self.prefix);
|
diag.set_arg("pref_kind", self.prefix);
|
||||||
diag.set_arg("suff_kind", self.suffix);
|
diag.set_arg("suff_kind", self.suffix);
|
||||||
|
let desc_span = self.desc.span;
|
||||||
|
self.desc.add_to(diag);
|
||||||
|
let msg = f(diag, fluent::infer_region_explanation.into());
|
||||||
|
if let Some(span) = desc_span {
|
||||||
|
diag.span_note(span, msg);
|
||||||
|
} else {
|
||||||
|
diag.note(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
use crate::errors::RegionOriginNote;
|
use crate::errors::{
|
||||||
|
note_and_explain, FullfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent,
|
||||||
|
RegionOriginNote,
|
||||||
|
};
|
||||||
use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt};
|
use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt};
|
||||||
use crate::infer::{self, SubregionOrigin};
|
use crate::infer::{self, SubregionOrigin};
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
fluent, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder,
|
fluent, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder,
|
||||||
ErrorGuaranteed,
|
ErrorGuaranteed, IntoDiagnostic,
|
||||||
};
|
};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_middle::traits::ObligationCauseCode;
|
use rustc_middle::traits::ObligationCauseCode;
|
||||||
|
@ -119,104 +122,83 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
infer::Reborrow(span) => {
|
infer::Reborrow(span) => {
|
||||||
let mut err = struct_span_err!(
|
let reference_valid = note_and_explain::RegionExplanation::new(
|
||||||
self.tcx.sess,
|
|
||||||
span,
|
|
||||||
E0312,
|
|
||||||
"lifetime of reference outlives lifetime of borrowed content..."
|
|
||||||
);
|
|
||||||
note_and_explain_region(
|
|
||||||
self.tcx,
|
self.tcx,
|
||||||
&mut err,
|
|
||||||
"...the reference is valid for ",
|
|
||||||
sub,
|
sub,
|
||||||
"...",
|
|
||||||
None,
|
None,
|
||||||
|
note_and_explain::PrefixKind::RefValidFor,
|
||||||
|
note_and_explain::SuffixKind::Continues,
|
||||||
);
|
);
|
||||||
note_and_explain_region(
|
let content_valid = note_and_explain::RegionExplanation::new(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
&mut err,
|
|
||||||
"...but the borrowed content is only valid for ",
|
|
||||||
sup,
|
sup,
|
||||||
"",
|
|
||||||
None,
|
None,
|
||||||
|
note_and_explain::PrefixKind::ContentValidFor,
|
||||||
|
note_and_explain::SuffixKind::Empty,
|
||||||
);
|
);
|
||||||
err
|
OutlivesContent {
|
||||||
|
span,
|
||||||
|
notes: reference_valid.into_iter().chain(content_valid).collect(),
|
||||||
|
}
|
||||||
|
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
|
||||||
}
|
}
|
||||||
infer::RelateObjectBound(span) => {
|
infer::RelateObjectBound(span) => {
|
||||||
let mut err = struct_span_err!(
|
let object_valid = note_and_explain::RegionExplanation::new(
|
||||||
self.tcx.sess,
|
|
||||||
span,
|
|
||||||
E0476,
|
|
||||||
"lifetime of the source pointer does not outlive lifetime bound of the \
|
|
||||||
object type"
|
|
||||||
);
|
|
||||||
note_and_explain_region(
|
|
||||||
self.tcx,
|
self.tcx,
|
||||||
&mut err,
|
|
||||||
"object type is valid for ",
|
|
||||||
sub,
|
sub,
|
||||||
"",
|
|
||||||
None,
|
None,
|
||||||
|
note_and_explain::PrefixKind::TypeValidFor,
|
||||||
|
note_and_explain::SuffixKind::Empty,
|
||||||
);
|
);
|
||||||
note_and_explain_region(
|
let pointer_valid = note_and_explain::RegionExplanation::new(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
&mut err,
|
|
||||||
"source pointer is only valid for ",
|
|
||||||
sup,
|
sup,
|
||||||
"",
|
|
||||||
None,
|
None,
|
||||||
|
note_and_explain::PrefixKind::SourcePointerValidFor,
|
||||||
|
note_and_explain::SuffixKind::Empty,
|
||||||
);
|
);
|
||||||
err
|
OutlivesBound {
|
||||||
|
span,
|
||||||
|
notes: object_valid.into_iter().chain(pointer_valid).collect(),
|
||||||
|
}
|
||||||
|
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
|
||||||
}
|
}
|
||||||
infer::RelateParamBound(span, ty, opt_span) => {
|
infer::RelateParamBound(span, ty, opt_span) => {
|
||||||
let mut err = struct_span_err!(
|
let prefix = match *sub {
|
||||||
self.tcx.sess,
|
ty::ReStatic => note_and_explain::PrefixKind::TypeSatisfy,
|
||||||
span,
|
_ => note_and_explain::PrefixKind::TypeOutlive,
|
||||||
E0477,
|
};
|
||||||
"the type `{}` does not fulfill the required lifetime",
|
let suffix = if opt_span.is_some() {
|
||||||
self.ty_to_string(ty)
|
note_and_explain::SuffixKind::ReqByBinding
|
||||||
|
} else {
|
||||||
|
note_and_explain::SuffixKind::Empty
|
||||||
|
};
|
||||||
|
let note = note_and_explain::RegionExplanation::new(
|
||||||
|
self.tcx, sub, opt_span, prefix, suffix,
|
||||||
);
|
);
|
||||||
match *sub {
|
FullfillReqLifetime { span, ty: self.resolve_vars_if_possible(ty), note }
|
||||||
ty::ReStatic => note_and_explain_region(
|
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
|
||||||
self.tcx,
|
|
||||||
&mut err,
|
|
||||||
"type must satisfy ",
|
|
||||||
sub,
|
|
||||||
if opt_span.is_some() { " as required by this binding" } else { "" },
|
|
||||||
opt_span,
|
|
||||||
),
|
|
||||||
_ => note_and_explain_region(
|
|
||||||
self.tcx,
|
|
||||||
&mut err,
|
|
||||||
"type must outlive ",
|
|
||||||
sub,
|
|
||||||
if opt_span.is_some() { " as required by this binding" } else { "" },
|
|
||||||
opt_span,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
err
|
|
||||||
}
|
}
|
||||||
infer::RelateRegionParamBound(span) => {
|
infer::RelateRegionParamBound(span) => {
|
||||||
let mut err =
|
let param_instantiated = note_and_explain::RegionExplanation::new(
|
||||||
struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
|
|
||||||
note_and_explain_region(
|
|
||||||
self.tcx,
|
self.tcx,
|
||||||
&mut err,
|
|
||||||
"lifetime parameter instantiated with ",
|
|
||||||
sup,
|
sup,
|
||||||
"",
|
|
||||||
None,
|
None,
|
||||||
|
note_and_explain::PrefixKind::LfInstantiatedWith,
|
||||||
|
note_and_explain::SuffixKind::Empty,
|
||||||
);
|
);
|
||||||
note_and_explain_region(
|
let param_must_outlive = note_and_explain::RegionExplanation::new(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
&mut err,
|
|
||||||
"but lifetime parameter must outlive ",
|
|
||||||
sub,
|
sub,
|
||||||
"",
|
|
||||||
None,
|
None,
|
||||||
|
note_and_explain::PrefixKind::LfMustOutlive,
|
||||||
|
note_and_explain::SuffixKind::Empty,
|
||||||
);
|
);
|
||||||
err
|
LfBoundNotSatisfied {
|
||||||
|
span,
|
||||||
|
notes: param_instantiated.into_iter().chain(param_must_outlive).collect(),
|
||||||
|
}
|
||||||
|
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
|
||||||
}
|
}
|
||||||
infer::ReferenceOutlivesReferent(ty, span) => {
|
infer::ReferenceOutlivesReferent(ty, span) => {
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue