Skip to content

Diag migrate #100871

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 49 additions & 55 deletions compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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,
};

use super::{OutlivesSuggestionBuilder, RegionName};
use crate::region_infer::BlameConstraint;
Expand Down Expand Up @@ -488,33 +493,29 @@ 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)
};

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 mut 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 },
},
upvar_def_span: None,
upvar_span: None,
fr_span: None,
};

diag.span_label(*span, message);

if let ReturnConstraint::ClosureUpvar(upvar_field) = kind {
let def_id = match self.regioncx.universal_regions().defining_ty {
DefiningTy::Closure(def_id, _) => def_id,
Expand All @@ -532,20 +533,17 @@ 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");
err.upvar_def_span = Some(upvar_def_span);
err.upvar_span = Some(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");
err.fr_span = Some(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");
let mut diag = self.infcx.tcx.sess.create_err(err);

self.suggest_move_on_borrowing_closure(&mut diag);

diag
Expand Down Expand Up @@ -681,39 +679,35 @@ 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 mut err = LifeTimeOutLiveErr { span: *span, category: None };

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: mir_def_name.to_string(),
outlived_fr_name: outlived_fr_name.to_string(),
fr_name: fr_name.to_string(),
},
_ => LifeTimeReturnCategoryErr::ShortReturn {
span: *span,
category_desc: category.description().to_string(),
free_region_name: fr_name.to_string(),
outlived_fr_name: outlived_fr_name.to_string(),
},
};

err.category = Some(err_category);

let mut diag = self.infcx.tcx.sess.create_err(err);

fr_name.highlight_region_name(&mut diag);
outlived_fr_name.highlight_region_name(&mut diag);

self.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr);
self.suggest_adding_lifetime_params(&mut diag, *fr, *outlived_fr);
Expand Down Expand Up @@ -862,7 +856,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",
Expand Down
16 changes: 4 additions & 12 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -424,17 +426,7 @@ 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();
})
tcx.emit_spanned_lint(UNUSED_MUT, lint_root, span, VarNeedNotMut { span })
}

let tainted_by_errors = mbcx.emit_errors();
Expand Down
17 changes: 6 additions & 11 deletions compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -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())
}
Expand Down
82 changes: 81 additions & 1 deletion compiler/rustc_borrowck/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
use rustc_middle::ty::Ty;
use rustc_span::Span;

Expand Down Expand Up @@ -42,3 +42,83 @@ 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,
#[label(borrowck::upvar_def)]
pub upvar_def_span: Option<Span>,
#[label(borrowck::upvar)]
pub upvar_span: Option<Span>,
#[label(borrowck::fr)]
pub fr_span: Option<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,
#[subdiagnostic]
pub category: LifeTimeReturnCategoryErr,
}

#[derive(SessionSubdiagnostic)]
pub(crate) enum LifeTimeReturnCategoryErr {
#[label(borrowck::returned_lifetime_wrong)]
WrongReturn {
#[primary_span]
span: Span,
mir_def_name: String,
outlived_fr_name: String,
fr_name: String,
},
#[label(borrowck::returned_lifetime_short)]
ShortReturn {
#[primary_span]
span: Span,
category_desc: String,
free_region_name: String,
outlived_fr_name: String,
},
}
44 changes: 44 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/borrowck.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,47 @@ 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
.upvar_def = variable defined here
.upvar = variable captured here
.fr = inferred to be a `FnMut` closure
.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_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
2 changes: 1 addition & 1 deletion src/tools/miri
Submodule miri updated 286 files