Use AddToDiagnostic for "use latest edition" help

This commit is contained in:
Xiretza 2022-10-05 21:40:56 +02:00
parent 0e36e7cebe
commit fc0ba2c8b6
6 changed files with 53 additions and 25 deletions

View file

@ -555,18 +555,6 @@ impl Diagnostic {
self
}
/// Help the user upgrade to the latest edition.
/// This is factored out to make sure it does the right thing with `Cargo.toml`.
pub fn help_use_latest_edition(&mut self) -> &mut Self {
if std::env::var_os("CARGO").is_some() {
self.help(&format!("set `edition = \"{}\"` in `Cargo.toml`", LATEST_STABLE_EDITION));
} else {
self.help(&format!("pass `--edition {}` to `rustc`", LATEST_STABLE_EDITION));
}
self.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
self
}
/// Disallow attaching suggestions this diagnostic.
/// Any suggestions attached e.g. with the `span_suggestion_*` methods
/// (before and after the call to `disable_suggestions`) will be ignored.
@ -1083,3 +1071,39 @@ impl PartialEq for Diagnostic {
self.keys() == other.keys()
}
}
pub enum HelpUseLatestEdition {
Cargo,
Standalone,
}
impl HelpUseLatestEdition {
pub fn new() -> Self {
if std::env::var_os("CARGO").is_some() { Self::Cargo } else { Self::Standalone }
}
}
impl AddToDiagnostic for HelpUseLatestEdition {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
let msg = f(
diag,
match self {
Self::Cargo => {
format!("set `edition = \"{}\"` in `Cargo.toml`", LATEST_STABLE_EDITION)
}
Self::Standalone => {
format!("pass `--edition {}` to `rustc`", LATEST_STABLE_EDITION)
}
}
.into(),
);
diag.help(msg);
let msg =
f(diag, "for more on editions, read https://doc.rust-lang.org/edition-guide".into());
diag.note(msg);
}
}

View file

@ -669,7 +669,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
sp: impl Into<MultiSpan>,
msg: impl Into<SubdiagnosticMessage>,
) -> &mut Self);
forward!(pub fn help_use_latest_edition(&mut self,) -> &mut Self);
forward!(pub fn set_is_lint(&mut self,) -> &mut Self);
forward!(pub fn disable_suggestions(&mut self,) -> &mut Self);

View file

@ -378,7 +378,7 @@ pub struct DelayedBugPanic;
pub use diagnostic::{
AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId,
DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
DiagnosticStyledString, HelpUseLatestEdition, IntoDiagnosticArg, SubDiagnostic,
};
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, Noted};
pub use diagnostic_impls::{DiagnosticArgFromDisplay, DiagnosticSymbolList};

View file

@ -23,8 +23,8 @@ use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId,
ErrorGuaranteed, StashKey,
pluralize, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder,
DiagnosticId, ErrorGuaranteed, HelpUseLatestEdition, StashKey,
};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
@ -2433,7 +2433,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We know by construction that `<expr>.await` is either on Rust 2015
// or results in `ExprKind::Await`. Suggest switching the edition to 2018.
err.note("to `.await` a `Future`, switch to Rust 2018 or later");
err.help_use_latest_edition();
HelpUseLatestEdition::new().add_to_diagnostic(&mut err);
}
err.emit();

View file

@ -39,8 +39,8 @@ use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, R
use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind};
use rustc_ast_pretty::pprust;
use rustc_errors::{
Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult,
StashKey,
AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
HelpUseLatestEdition, IntoDiagnostic, PResult, StashKey,
};
use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded};
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
@ -2927,7 +2927,7 @@ impl<'a> Parser<'a> {
let mut async_block_err = |e: &mut Diagnostic, span: Span| {
recover_async = true;
e.span_label(span, "`async` blocks are only allowed in Rust 2018 or later");
e.help_use_latest_edition();
HelpUseLatestEdition::new().add_to_diagnostic(e);
};
while self.token != token::CloseDelim(close_delim) {

View file

@ -16,7 +16,10 @@ use rustc_ast::{EnumDef, FieldDef, Generics, TraitRef, Ty, TyKind, Variant, Vari
use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind};
use rustc_ast::{MacCall, MacDelimiter};
use rustc_ast_pretty::pprust;
use rustc_errors::{struct_span_err, Applicability, IntoDiagnostic, PResult, StashKey};
use rustc_errors::{
struct_span_err, AddToDiagnostic, Applicability, HelpUseLatestEdition, IntoDiagnostic, PResult,
StashKey,
};
use rustc_span::edition::Edition;
use rustc_span::lev_distance::lev_distance;
use rustc_span::source_map::{self, Span};
@ -2445,10 +2448,12 @@ impl<'a> Parser<'a> {
fn ban_async_in_2015(&self, span: Span) {
if span.rust_2015() {
let diag = self.diagnostic();
struct_span_err!(diag, span, E0670, "`async fn` is not permitted in Rust 2015")
.span_label(span, "to use `async fn`, switch to Rust 2018 or later")
.help_use_latest_edition()
.emit();
let mut e =
struct_span_err!(diag, span, E0670, "`async fn` is not permitted in Rust 2015");
e.span_label(span, "to use `async fn`, switch to Rust 2018 or later");
HelpUseLatestEdition::new().add_to_diagnostic(&mut e);
e.emit();
}
}