Skip to content

Commit

Permalink
Convert proc_macro_back_compat lint to an unconditional error.
Browse files Browse the repository at this point in the history
We still check for the `rental`/`allsorts-rental` crates. But now if
they are detected we just emit a fatal error, instead of emitting a
warning and providing alternative behaviour.

The original "hack" implementing alternative behaviour was added
in #73345.

The lint was added in #83127.

The tracking issue is #83125.

The direct motivation for the change is that providing the alternative
behaviour is interfering with #125174 and follow-on work.
  • Loading branch information
nnethercote committed May 27, 2024
1 parent 722b444 commit b5e92ae
Show file tree
Hide file tree
Showing 14 changed files with 54 additions and 574 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_expand/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ expand_not_a_meta_item =
expand_only_one_word =
must only be one word
expand_proc_macro_back_compat = using an old version of `{$crate_name}`
.note = older versions of the `{$crate_name}` crate no longer compile; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives
expand_proc_macro_derive_panicked =
proc-macro derive panicked
.help = message: {$message}
Expand Down
41 changes: 16 additions & 25 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::{self, Lrc};
use rustc_errors::{DiagCtxt, ErrorGuaranteed, PResult};
use rustc_feature::Features;
use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, RegisteredTools};
use rustc_lint_defs::{BufferedEarlyLint, RegisteredTools};
use rustc_parse::{parser, MACRO_ARGUMENTS};
use rustc_session::config::CollapseMacroDebuginfo;
use rustc_session::{parse::ParseSess, Limit, Session};
Expand Down Expand Up @@ -1330,13 +1329,10 @@ pub fn parse_macro_name_and_helper_attrs(
Some((trait_ident.name, proc_attrs))
}

/// This nonterminal looks like some specific enums from
/// `proc-macro-hack` and `procedural-masquerade` crates.
/// We need to maintain some special pretty-printing behavior for them due to incorrect
/// asserts in old versions of those crates and their wide use in the ecosystem.
/// See issue #73345 for more details.
/// If this item looks like a specific enums from `rental`, emit a fatal error.
/// See #73345 and #83125 for more details.
/// FIXME(#73933): Remove this eventually.
fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) -> bool {
fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) {
let name = item.ident.name;
if name == sym::ProceduralMasqueradeDummyType
&& let ast::ItemKind::Enum(enum_def, _) = &item.kind
Expand All @@ -1360,41 +1356,36 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) -> bool {
};

if crate_matches {
sess.psess.buffer_lint(
PROC_MACRO_BACK_COMPAT,
item.ident.span,
ast::CRATE_NODE_ID,
BuiltinLintDiag::ProcMacroBackCompat {
crate_name: "rental".to_string(),
fixed_version: "0.5.6".to_string(),
},
);
return true;
// FIXME: make this translatable
#[allow(rustc::untranslatable_diagnostic)]
sess.psess.dcx.emit_fatal(errors::ProcMacroBackCompat {
crate_name: "rental".to_string(),
fixed_version: "0.5.6".to_string(),
});
}
}
false
}

pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &Session) -> bool {
pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &Session) {
let item = match ann {
Annotatable::Item(item) => item,
Annotatable::Stmt(stmt) => match &stmt.kind {
ast::StmtKind::Item(item) => item,
_ => return false,
_ => return,
},
_ => return false,
_ => return,
};
pretty_printing_compatibility_hack(item, sess)
}

pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &Session) -> bool {
pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &Session) {
let item = match nt {
Nonterminal::NtItem(item) => item,
Nonterminal::NtStmt(stmt) => match &stmt.kind {
ast::StmtKind::Item(item) => item,
_ => return false,
_ => return,
},
_ => return false,
_ => return,
};
pretty_printing_compatibility_hack(item, sess)
}
10 changes: 10 additions & 0 deletions compiler/rustc_expand/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,3 +440,13 @@ pub(crate) struct EmptyDelegationList {
#[primary_span]
pub span: Span,
}

// This used to be the `proc_macro_back_compat` lint (#83125). It was later
// turned into a hard error.
#[derive(Diagnostic)]
#[diag(expand_proc_macro_back_compat)]
#[note]
pub struct ProcMacroBackCompat {
pub crate_name: String,
pub fixed_version: String,
}
21 changes: 7 additions & 14 deletions compiler/rustc_expand/src/proc_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@ use crate::proc_macro_server;

use rustc_ast as ast;
use rustc_ast::ptr::P;
use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream;
use rustc_data_structures::sync::Lrc;
use rustc_errors::ErrorGuaranteed;
use rustc_parse::parser::ForceCollect;
use rustc_session::config::ProcMacroExecutionStrategy;
use rustc_span::profiling::SpannedEventArgRecorder;
use rustc_span::{Span, DUMMY_SP};
use rustc_span::Span;

struct MessagePipe<T> {
tx: std::sync::mpsc::SyncSender<T>,
Expand Down Expand Up @@ -120,18 +118,13 @@ impl MultiItemModifier for DeriveProcMacro {
// We need special handling for statement items
// (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)
let is_stmt = matches!(item, Annotatable::Stmt(..));
let hack = crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess);
let input = if hack {
let nt = match item {
Annotatable::Item(item) => token::NtItem(item),
Annotatable::Stmt(stmt) => token::NtStmt(stmt),
_ => unreachable!(),
};
TokenStream::token_alone(token::Interpolated(Lrc::new(nt)), DUMMY_SP)
} else {
item.to_tokens()
};

// We used to have an alternative behaviour for crates that needed it.
// We had a lint for a long time, but now we just emit a hard error.
// Eventually we might remove the special case hard error check
// altogether. See #73345.
crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess);
let input = item.to_tokens();
let stream = {
let _timer =
ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
Expand Down
29 changes: 14 additions & 15 deletions compiler/rustc_expand/src/proc_macro_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,21 +276,20 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre

Interpolated(nt) => {
let stream = TokenStream::from_nonterminal_ast(&nt);
// A hack used to pass AST fragments to attribute and derive
// macros as a single nonterminal token instead of a token
// stream. Such token needs to be "unwrapped" and not
// represented as a delimited group.
// FIXME: It needs to be removed, but there are some
// compatibility issues (see #73345).
if crate::base::nt_pretty_printing_compatibility_hack(&nt, rustc.ecx.sess) {
trees.extend(Self::from_internal((stream, rustc)));
} else {
trees.push(TokenTree::Group(Group {
delimiter: pm::Delimiter::None,
stream: Some(stream),
span: DelimSpan::from_single(span),
}))
}
// We used to have an alternative behaviour for crates that
// needed it: a hack used to pass AST fragments to
// attribute and derive macros as a single nonterminal
// token instead of a token stream. Such token needs to be
// "unwrapped" and not represented as a delimited group. We
// had a lint for a long time, but now we just emit a hard
// error. Eventually we might remove the special case hard
// error check altogether. See #73345.
crate::base::nt_pretty_printing_compatibility_hack(&nt, rustc.ecx.sess);
trees.push(TokenTree::Group(Group {
delimiter: pm::Delimiter::None,
stream: Some(stream),
span: DelimSpan::from_single(span),
}))
}

OpenDelim(..) | CloseDelim(..) => unreachable!(),
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -629,9 +629,6 @@ lint_pattern_in_foreign = patterns aren't allowed in foreign function declaratio
lint_private_extern_crate_reexport =
extern crate `{$ident}` is private, and cannot be re-exported, consider declaring with `pub`
lint_proc_macro_back_compat = using an old version of `{$crate_name}`
.note = older versions of the `{$crate_name}` crate will stop compiling in future versions of Rust; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives
lint_proc_macro_derive_resolution_fallback = cannot find {$ns} `{$ident}` in this scope
.label = names from parent modules are not accessible without an explicit import
Expand Down
7 changes: 0 additions & 7 deletions compiler/rustc_lint/src/context/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,6 @@ pub(super) fn emit_buffered_lint(
BuiltinLintDiag::LegacyDeriveHelpers(label_span) => {
ctx.emit_span_lint(lint, span, lints::LegacyDeriveHelpers { span: label_span });
}
BuiltinLintDiag::ProcMacroBackCompat { crate_name, fixed_version } => {
ctx.emit_span_lint(
lint,
span,
lints::ProcMacroBackCompat { crate_name, fixed_version },
);
}
BuiltinLintDiag::OrPatternsBackCompat(suggestion_span, suggestion) => {
ctx.emit_span_lint(
lint,
Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2571,14 +2571,6 @@ pub struct LegacyDeriveHelpers {
pub span: Span,
}

#[derive(LintDiagnostic)]
#[diag(lint_proc_macro_back_compat)]
#[note]
pub struct ProcMacroBackCompat {
pub crate_name: String,
pub fixed_version: String,
}

#[derive(LintDiagnostic)]
#[diag(lint_or_patterns_back_compat)]
pub struct OrPatternsBackCompat {
Expand Down
48 changes: 0 additions & 48 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ declare_lint_pass! {
POINTER_STRUCTURAL_MATCH,
PRIVATE_BOUNDS,
PRIVATE_INTERFACES,
PROC_MACRO_BACK_COMPAT,
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
REDUNDANT_LIFETIMES,
Expand Down Expand Up @@ -3792,53 +3791,6 @@ declare_lint! {
"detects invalid `#[doc(...)]` attributes",
}

declare_lint! {
/// The `proc_macro_back_compat` lint detects uses of old versions of certain
/// proc-macro crates, which have hardcoded workarounds in the compiler.
///
/// ### Example
///
/// ```rust,ignore (needs-dependency)
///
/// use time_macros_impl::impl_macros;
/// struct Foo;
/// impl_macros!(Foo);
/// ```
///
/// This will produce:
///
/// ```text
/// warning: using an old version of `time-macros-impl`
/// ::: $DIR/group-compat-hack.rs:27:5
/// |
/// LL | impl_macros!(Foo);
/// | ------------------ in this macro invocation
/// |
/// = note: `#[warn(proc_macro_back_compat)]` on by default
/// = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
/// = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
/// = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage
/// = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
/// ```
///
/// ### Explanation
///
/// Eventually, the backwards-compatibility hacks present in the compiler will be removed,
/// causing older versions of certain crates to stop compiling.
/// This is a [future-incompatible] lint to ease the transition to an error.
/// See [issue #83125] for more details.
///
/// [issue #83125]: https://github.com/rust-lang/rust/issues/83125
/// [future-incompatible]: ../index.md#future-incompatible-lints
pub PROC_MACRO_BACK_COMPAT,
Deny,
"detects usage of old versions of certain proc-macro crates",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reference: "issue #83125 <https://github.com/rust-lang/rust/issues/83125>",
};
}

declare_lint! {
/// The `rust_2021_incompatible_or_patterns` lint detects usage of old versions of or-patterns.
///
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_lint_defs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,10 +618,6 @@ pub enum BuiltinLintDiag {
is_foreign: bool,
},
LegacyDeriveHelpers(Span),
ProcMacroBackCompat {
crate_name: String,
fixed_version: String,
},
OrPatternsBackCompat(Span, String),
ReservedPrefix(Span, String),
TrailingMacro(bool, Ident),
Expand Down
Loading

0 comments on commit b5e92ae

Please sign in to comment.