mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Migrate note_region_origin function
This commit is contained in:
parent
3f6cb475f7
commit
f50d1713fd
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user