Migrate note_region_origin function

This commit is contained in:
Nikita Tomashevich 2022-08-23 13:48:14 +03:00
parent 3f6cb475f7
commit f50d1713fd
No known key found for this signature in database
GPG Key ID: B29791D4D878E345
4 changed files with 173 additions and 53 deletions

View File

@ -61,5 +61,48 @@ infer_source_kind_fully_qualified =
infer_source_kind_closure_return =
try giving this closure an explicit return type
# generator_kind may need to be translated
infer_need_type_info_in_generator =
type inside {$generator_kind} must be known in this context
infer_subtype = ...so that the {$requirement ->
[method_compat] method type is compatible with trait
[type_compat] associated type is compatible with trait
[const_compat] const is compatible with trait
[expr_assignable] expression is assignable
[if_else_different] `if` and `else` have incompatible types
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
[fn_start_correct_type] #[start]` function has the correct type
[intristic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
*[other] types are compatible
}
infer_subtype_2 = ...so that {$requirement ->
[method_compat] method type is compatible with trait
[type_compat] associated type is compatible with trait
[const_compat] const is compatible with trait
[expr_assignable] expression is assignable
[if_else_different] `if` and `else` have incompatible types
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
[fn_start_correct_type] #[start]` function has the correct type
[intristic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
*[other] types are compatible
}
infer_reborrow = ...so that reference does not outlive borrowed content
infer_reborrow_upvar = ...so that closure can access `{$name}`
infer_relate_object_bound = ...so that it can be closed over into an object
infer_data_borrowed = ...so that the type `{$name}` is not borrowed for too long
infer_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at
infer_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
[true] ...
*[false] {""}
}
infer_relate_param_bound_2 = ...that is required by this bound
infer_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied
infer_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait

View File

@ -1,4 +1,4 @@
use rustc_errors::{fluent, AddSubdiagnostic};
use rustc_errors::{fluent, AddSubdiagnostic, DiagnosticMessage, DiagnosticStyledString};
use rustc_hir::FnRetTy;
use rustc_macros::SessionDiagnostic;
use rustc_span::{BytePos, Span};
@ -185,3 +185,65 @@ impl AddSubdiagnostic for SourceKindMultiSuggestion<'_> {
}
}
}
pub enum RegionOriginNote<'a> {
Plain {
span: Span,
msg: DiagnosticMessage,
},
WithName {
span: Span,
msg: DiagnosticMessage,
name: &'a str,
continues: bool,
},
WithRequirement {
span: Span,
requirement: &'static str,
expected_found: Option<(DiagnosticStyledString, DiagnosticStyledString)>,
},
}
impl AddSubdiagnostic for RegionOriginNote<'_> {
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
let mut label_or_note = |span, msg: DiagnosticMessage| {
let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span);
if span_is_primary && sub_count == 0 && expanded_sub_count == 0 {
diag.span_label(span, msg);
} else if span_is_primary && expanded_sub_count == 0 {
diag.note(msg);
} else {
diag.span_note(span, msg);
}
};
match self {
RegionOriginNote::Plain { span, msg } => {
label_or_note(span, msg);
}
RegionOriginNote::WithName { span, msg, name, continues } => {
label_or_note(span, msg);
diag.set_arg("name", name);
diag.set_arg("continues", continues);
}
RegionOriginNote::WithRequirement {
span,
requirement,
expected_found: Some((expected, found)),
} => {
label_or_note(span, fluent::infer::subtype);
diag.set_arg("requirement", requirement);
diag.note_expected_found(&"", expected, &"", found);
}
RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => {
// FIXME: this really should be handled at some earlier stage. Our
// handling of region checking when type errors are present is
// *terrible*.
label_or_note(span, fluent::infer::subtype_2);
diag.set_arg("requirement", requirement);
}
};
}
}

View File

@ -2811,6 +2811,7 @@ pub enum FailureCode {
pub trait ObligationCauseExt<'tcx> {
fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode;
fn as_requirement_str(&self) -> &'static str;
fn as_requirement_localised(&self) -> &'static str;
}
impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
@ -2879,6 +2880,23 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
_ => "types are compatible",
}
}
fn as_requirement_localised(&self) -> &'static str {
use crate::traits::ObligationCauseCode::*;
match self.code() {
CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => "method_compat",
CompareImplItemObligation { kind: ty::AssocKind::Type, .. } => "type_compat",
CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => "const_compat",
ExprAssignable => "expr_assignable",
IfExpression { .. } => "if_else_different",
IfExpressionWithNoElse => "no_else",
MainFunctionType => "fn_main_correct_type",
StartFunctionType => "fn_start_correct_type",
IntrinsicType => "intristic_correct_type",
MethodReceiver => "method_correct_type",
_ => "other",
}
}
}
/// This is a bare signal of what kind of type we're dealing with. `ty::TyKind` tracks

View File

@ -1,13 +1,17 @@
use crate::errors::RegionOriginNote;
use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt};
use crate::infer::{self, InferCtxt, SubregionOrigin};
use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
use rustc_errors::{
fluent, struct_span_err, AddSubdiagnostic, Diagnostic, DiagnosticBuilder, DiagnosticMessage,
ErrorGuaranteed,
};
use rustc_middle::traits::ObligationCauseCode;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{self, Region};
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) {
let mut label_or_note = |span, msg: &str| {
let mut label_or_note = |span, msg: DiagnosticMessage| {
let sub_count = err.children.iter().filter(|d| d.span.is_dummy()).count();
let expanded_sub_count = err.children.iter().filter(|d| !d.span.is_dummy()).count();
let span_is_primary = err.span.primary_spans().iter().all(|&sp| sp == span);
@ -20,77 +24,70 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
};
match *origin {
infer::Subtype(ref trace) => {
if let Some((expected, found)) = self.values_str(trace.values) {
label_or_note(
trace.cause.span,
&format!("...so that the {}", trace.cause.as_requirement_str()),
);
err.note_expected_found(&"", expected, &"", found);
} else {
// FIXME: this really should be handled at some earlier stage. Our
// handling of region checking when type errors are present is
// *terrible*.
label_or_note(
trace.cause.span,
&format!("...so that {}", trace.cause.as_requirement_str()),
);
}
infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
span: trace.cause.span,
requirement: trace.cause.as_requirement_localised(),
expected_found: self.values_str(trace.values),
}
.add_to_diagnostic(err),
infer::Reborrow(span) => {
label_or_note(span, "...so that reference does not outlive borrowed content");
label_or_note(span, fluent::infer::reborrow);
RegionOriginNote::Plain { span, msg: fluent::infer::reborrow }
.add_to_diagnostic(err)
}
infer::ReborrowUpvar(span, ref upvar_id) => {
let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
label_or_note(span, &format!("...so that closure can access `{}`", var_name));
RegionOriginNote::WithName {
span,
msg: fluent::infer::reborrow,
name: &var_name.to_string(),
continues: false,
}
.add_to_diagnostic(err);
}
infer::RelateObjectBound(span) => {
label_or_note(span, "...so that it can be closed over into an object");
label_or_note(span, fluent::infer::relate_object_bound);
RegionOriginNote::Plain { span, msg: fluent::infer::relate_object_bound }
.add_to_diagnostic(err);
}
infer::DataBorrowed(ty, span) => {
label_or_note(
RegionOriginNote::WithName {
span,
&format!(
"...so that the type `{}` is not borrowed for too long",
self.ty_to_string(ty)
),
);
msg: fluent::infer::data_borrowed,
name: &self.ty_to_string(ty),
continues: false,
}
.add_to_diagnostic(err);
}
infer::ReferenceOutlivesReferent(ty, span) => {
label_or_note(
RegionOriginNote::WithName {
span,
&format!(
"...so that the reference type `{}` does not outlive the data it points at",
self.ty_to_string(ty)
),
);
msg: fluent::infer::reference_outlives_referent,
name: &self.ty_to_string(ty),
continues: false,
}
.add_to_diagnostic(err);
}
infer::RelateParamBound(span, t, opt_span) => {
label_or_note(
infer::RelateParamBound(span, ty, opt_span) => {
RegionOriginNote::WithName {
span,
&format!(
"...so that the type `{}` will meet its required lifetime bounds{}",
self.ty_to_string(t),
if opt_span.is_some() { "..." } else { "" },
),
);
msg: fluent::infer::relate_param_bound,
name: &self.ty_to_string(ty),
continues: opt_span.is_some(),
}
.add_to_diagnostic(err);
if let Some(span) = opt_span {
err.span_note(span, "...that is required by this bound");
RegionOriginNote::Plain { span, msg: fluent::infer::relate_param_bound_2 }
.add_to_diagnostic(err);
}
}
infer::RelateRegionParamBound(span) => {
label_or_note(
span,
"...so that the declared lifetime parameter bounds are satisfied",
);
RegionOriginNote::Plain { span, msg: fluent::infer::relate_region_param_bound }
.add_to_diagnostic(err);
}
infer::CompareImplItemObligation { span, .. } => {
label_or_note(
span,
"...so that the definition in impl matches the definition from the trait",
);
RegionOriginNote::Plain { span, msg: fluent::infer::compare_impl_item_obligation }
.add_to_diagnostic(err);
}
infer::CheckAssociatedTypeBounds { ref parent, .. } => {
self.note_region_origin(err, &parent);