diag-mig
This commit is contained in:
parent
cfb5ae26a4
commit
622217da59
@ -1,3 +1,5 @@
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
//! Error reporting machinery for lifetime errors.
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
@ -23,7 +25,10 @@ use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::borrowck_errors;
|
||||
use crate::session_diagnostics::GenericDoesNotLiveLongEnough;
|
||||
use crate::session_diagnostics::{
|
||||
FnMutError, FnMutReturnTypeErr, GenericDoesNotLiveLongEnough, LifetimeOutliveErr,
|
||||
LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote,
|
||||
};
|
||||
|
||||
use super::{OutlivesSuggestionBuilder, RegionName};
|
||||
use crate::region_infer::BlameConstraint;
|
||||
@ -488,12 +493,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
|
||||
|
||||
let mut diag = self
|
||||
.infcx
|
||||
.tcx
|
||||
.sess
|
||||
.struct_span_err(*span, "captured variable cannot escape `FnMut` closure body");
|
||||
|
||||
let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty;
|
||||
if let ty::Opaque(def_id, _) = *output_ty.kind() {
|
||||
output_ty = self.infcx.tcx.type_of(def_id)
|
||||
@ -501,19 +500,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
|
||||
debug!("report_fnmut_error: output_ty={:?}", output_ty);
|
||||
|
||||
let message = match output_ty.kind() {
|
||||
ty::Closure(_, _) => {
|
||||
"returns a closure that contains a reference to a captured variable, which then \
|
||||
escapes the closure body"
|
||||
}
|
||||
ty::Adt(def, _) if self.infcx.tcx.is_diagnostic_item(sym::gen_future, def.did()) => {
|
||||
"returns an `async` block that contains a reference to a captured variable, which then \
|
||||
escapes the closure body"
|
||||
}
|
||||
_ => "returns a reference to a captured variable which escapes the closure body",
|
||||
let err = FnMutError {
|
||||
span: *span,
|
||||
ty_err: match output_ty.kind() {
|
||||
ty::Closure(_, _) => FnMutReturnTypeErr::ReturnClosure { span: *span },
|
||||
ty::Adt(def, _)
|
||||
if self.infcx.tcx.is_diagnostic_item(sym::gen_future, def.did()) =>
|
||||
{
|
||||
FnMutReturnTypeErr::ReturnAsyncBlock { span: *span }
|
||||
}
|
||||
_ => FnMutReturnTypeErr::ReturnRef { span: *span },
|
||||
},
|
||||
};
|
||||
|
||||
diag.span_label(*span, message);
|
||||
let mut diag = self.infcx.tcx.sess.create_err(err);
|
||||
|
||||
if let ReturnConstraint::ClosureUpvar(upvar_field) = kind {
|
||||
let def_id = match self.regioncx.universal_regions().defining_ty {
|
||||
@ -532,20 +532,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
let upvars_map = self.infcx.tcx.upvars_mentioned(def_id).unwrap();
|
||||
let upvar_def_span = self.infcx.tcx.hir().span(def_hir);
|
||||
let upvar_span = upvars_map.get(&def_hir).unwrap().span;
|
||||
diag.span_label(upvar_def_span, "variable defined here");
|
||||
diag.span_label(upvar_span, "variable captured here");
|
||||
diag.subdiagnostic(VarHereDenote::Defined { span: upvar_def_span });
|
||||
diag.subdiagnostic(VarHereDenote::Captured { span: upvar_span });
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(fr_span) = self.give_region_a_name(*outlived_fr).unwrap().span() {
|
||||
diag.span_label(fr_span, "inferred to be a `FnMut` closure");
|
||||
diag.subdiagnostic(VarHereDenote::FnMutInferred { span: fr_span });
|
||||
}
|
||||
|
||||
diag.note(
|
||||
"`FnMut` closures only have access to their captured variables while they are \
|
||||
executing...",
|
||||
);
|
||||
diag.note("...therefore, they cannot allow references to captured variables to escape");
|
||||
self.suggest_move_on_borrowing_closure(&mut diag);
|
||||
|
||||
diag
|
||||
@ -681,39 +676,33 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
..
|
||||
} = errci;
|
||||
|
||||
let mut diag =
|
||||
self.infcx.tcx.sess.struct_span_err(*span, "lifetime may not live long enough");
|
||||
|
||||
let (_, mir_def_name) =
|
||||
self.infcx.tcx.article_and_description(self.mir_def_id().to_def_id());
|
||||
|
||||
let err = LifetimeOutliveErr { span: *span };
|
||||
let mut diag = self.infcx.tcx.sess.create_err(err);
|
||||
|
||||
let fr_name = self.give_region_a_name(*fr).unwrap();
|
||||
fr_name.highlight_region_name(&mut diag);
|
||||
let outlived_fr_name = self.give_region_a_name(*outlived_fr).unwrap();
|
||||
outlived_fr_name.highlight_region_name(&mut diag);
|
||||
|
||||
match (category, outlived_fr_is_local, fr_is_local) {
|
||||
(ConstraintCategory::Return(_), true, _) => {
|
||||
diag.span_label(
|
||||
*span,
|
||||
format!(
|
||||
"{mir_def_name} was supposed to return data with lifetime `{outlived_fr_name}` but it is returning \
|
||||
data with lifetime `{fr_name}`",
|
||||
),
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
diag.span_label(
|
||||
*span,
|
||||
format!(
|
||||
"{}requires that `{}` must outlive `{}`",
|
||||
category.description(),
|
||||
fr_name,
|
||||
outlived_fr_name,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
let err_category = match (category, outlived_fr_is_local, fr_is_local) {
|
||||
(ConstraintCategory::Return(_), true, _) => LifetimeReturnCategoryErr::WrongReturn {
|
||||
span: *span,
|
||||
mir_def_name,
|
||||
outlived_fr_name,
|
||||
fr_name: &fr_name,
|
||||
},
|
||||
_ => LifetimeReturnCategoryErr::ShortReturn {
|
||||
span: *span,
|
||||
category_desc: category.description(),
|
||||
free_region_name: &fr_name,
|
||||
outlived_fr_name,
|
||||
},
|
||||
};
|
||||
|
||||
diag.subdiagnostic(err_category);
|
||||
|
||||
self.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr);
|
||||
self.suggest_adding_lifetime_params(&mut diag, *fr, *outlived_fr);
|
||||
@ -862,7 +851,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
ident.span,
|
||||
"calling this method introduces the `impl`'s 'static` requirement",
|
||||
);
|
||||
err.span_note(multi_span, "the used `impl` has a `'static` requirement");
|
||||
err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span });
|
||||
err.span_suggestion_verbose(
|
||||
span.shrink_to_hi(),
|
||||
"consider relaxing the implicit `'static` requirement",
|
||||
|
@ -18,7 +18,7 @@ extern crate tracing;
|
||||
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::graph::dominators::Dominators;
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_index::bit_set::ChunkedBitSet;
|
||||
@ -50,6 +50,8 @@ use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult, MoveData, MoveE
|
||||
use rustc_mir_dataflow::Analysis;
|
||||
use rustc_mir_dataflow::MoveDataParamEnv;
|
||||
|
||||
use crate::session_diagnostics::VarNeedNotMut;
|
||||
|
||||
use self::diagnostics::{AccessKind, RegionName};
|
||||
use self::location::LocationTable;
|
||||
use self::prefixes::PrefixSet;
|
||||
@ -424,17 +426,9 @@ fn do_mir_borrowck<'a, 'tcx>(
|
||||
continue;
|
||||
}
|
||||
|
||||
tcx.struct_span_lint_hir(UNUSED_MUT, lint_root, span, |lint| {
|
||||
let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
|
||||
lint.build("variable does not need to be mutable")
|
||||
.span_suggestion_short(
|
||||
mut_span,
|
||||
"remove this `mut`",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
})
|
||||
let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
|
||||
|
||||
tcx.emit_spanned_lint(UNUSED_MUT, lint_root, span, VarNeedNotMut { span: mut_span })
|
||||
}
|
||||
|
||||
let tainted_by_errors = mbcx.emit_errors();
|
||||
|
@ -16,6 +16,8 @@ use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::TraitEngineExt as _;
|
||||
|
||||
use crate::session_diagnostics::ConstNotUsedTraitAlias;
|
||||
|
||||
use super::RegionInferenceContext;
|
||||
|
||||
impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
@ -639,17 +641,10 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
|
||||
Some(GenericArgKind::Const(c1)) => c1,
|
||||
Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
|
||||
None => {
|
||||
self.tcx
|
||||
.sess
|
||||
.struct_span_err(
|
||||
self.span,
|
||||
&format!(
|
||||
"const parameter `{}` is part of concrete type but not \
|
||||
used in parameter list for the `impl Trait` type alias",
|
||||
ct
|
||||
),
|
||||
)
|
||||
.emit();
|
||||
self.tcx.sess.emit_err(ConstNotUsedTraitAlias {
|
||||
ct: ct.to_string(),
|
||||
span: self.span,
|
||||
});
|
||||
|
||||
self.tcx().const_error(ct.ty())
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
|
||||
use rustc_errors::{IntoDiagnosticArg, MultiSpan};
|
||||
use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::diagnostics::RegionName;
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(borrowck::move_unsized, code = "E0161")]
|
||||
pub(crate) struct MoveUnsized<'tcx> {
|
||||
@ -42,3 +45,115 @@ pub(crate) struct GenericDoesNotLiveLongEnough {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(borrowck::var_does_not_need_mut)]
|
||||
pub(crate) struct VarNeedNotMut {
|
||||
#[suggestion_short(applicability = "machine-applicable", code = "")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(borrowck::const_not_used_in_type_alias)]
|
||||
pub(crate) struct ConstNotUsedTraitAlias {
|
||||
pub ct: String,
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(borrowck::var_cannot_escape_closure)]
|
||||
#[note]
|
||||
#[note(borrowck::cannot_escape)]
|
||||
pub(crate) struct FnMutError {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub ty_err: FnMutReturnTypeErr,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
pub(crate) enum VarHereDenote {
|
||||
#[label(borrowck::var_here_captured)]
|
||||
Captured {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[label(borrowck::var_here_defined)]
|
||||
Defined {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[label(borrowck::closure_inferred_mut)]
|
||||
FnMutInferred {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
pub(crate) enum FnMutReturnTypeErr {
|
||||
#[label(borrowck::returned_closure_escaped)]
|
||||
ReturnClosure {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[label(borrowck::returned_async_block_escaped)]
|
||||
ReturnAsyncBlock {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[label(borrowck::returned_ref_escaped)]
|
||||
ReturnRef {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(borrowck::lifetime_constraints_error)]
|
||||
pub(crate) struct LifetimeOutliveErr {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
pub(crate) enum LifetimeReturnCategoryErr<'a> {
|
||||
#[label(borrowck::returned_lifetime_wrong)]
|
||||
WrongReturn {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
mir_def_name: &'a str,
|
||||
outlived_fr_name: RegionName,
|
||||
fr_name: &'a RegionName,
|
||||
},
|
||||
#[label(borrowck::returned_lifetime_short)]
|
||||
ShortReturn {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
category_desc: &'static str,
|
||||
free_region_name: &'a RegionName,
|
||||
outlived_fr_name: RegionName,
|
||||
},
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for &RegionName {
|
||||
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
||||
format!("{}", self).into_diagnostic_arg()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for RegionName {
|
||||
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
||||
format!("{}", self).into_diagnostic_arg()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(SessionSubdiagnostic)]
|
||||
pub(crate) enum RequireStaticErr {
|
||||
#[note(borrowck::used_impl_require_static)]
|
||||
UsedImpl {
|
||||
#[primary_span]
|
||||
multi_span: MultiSpan,
|
||||
},
|
||||
}
|
||||
|
@ -16,3 +16,45 @@ borrowck_higher_ranked_subtype_error =
|
||||
|
||||
borrowck_generic_does_not_live_long_enough =
|
||||
`{$kind}` does not live long enough
|
||||
|
||||
borrowck_move_borrowed =
|
||||
cannot move out of `{$desc}` beacause it is borrowed
|
||||
|
||||
borrowck_var_does_not_need_mut =
|
||||
variable does not need to be mutable
|
||||
.suggestion = remove this `mut`
|
||||
|
||||
borrowck_const_not_used_in_type_alias =
|
||||
const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias
|
||||
|
||||
borrowck_var_cannot_escape_closure =
|
||||
captured variable cannot escape `FnMut` closure body
|
||||
.note = `FnMut` closures only have access to their captured variables while they are executing...
|
||||
.cannot_escape = ...therefore, they cannot allow references to captured variables to escape
|
||||
|
||||
borrowck_var_here_defined = variable defined here
|
||||
|
||||
borrowck_var_here_captured = variable captured here
|
||||
|
||||
borrowck_closure_inferred_mut = inferred to be a `FnMut` closure
|
||||
|
||||
borrowck_returned_closure_escaped =
|
||||
returns a closure that contains a reference to a captured variable, which then escapes the closure body
|
||||
|
||||
borrowck_returned_async_block_escaped =
|
||||
returns an `async` block that contains a reference to a captured variable, which then escapes the closure body
|
||||
|
||||
borrowck_returned_ref_escaped =
|
||||
returns a reference to a captured variable which escapes the closure body
|
||||
|
||||
borrowck_lifetime_constraints_error =
|
||||
lifetime may not live long enough
|
||||
|
||||
borrowck_returned_lifetime_wrong =
|
||||
{$mir_def_name} was supposed to return data with lifetime `{$outlived_fr_name}` but it is returning data with lifetime `{$fr_name}`
|
||||
|
||||
borrowck_returned_lifetime_short =
|
||||
{$category_desc}requires that `{$free_region_name}` must outlive `{$outlived_fr_name}`
|
||||
|
||||
borrowck_used_impl_require_static =
|
||||
the used `impl` has a `'static` requirement
|
||||
|
Loading…
x
Reference in New Issue
Block a user