Introduce proc_macro_back_compat
lint, and emit for time-macros-impl
Now that future-incompat-report support has landed in nightly Cargo, we can start to make progress towards removing the various proc-macro back-compat hacks that have accumulated in the compiler. This PR introduces a new lint `proc_macro_back_compat`, which results in a future-incompat-report entry being generated. All proc-macro back-compat warnings will be grouped under this lint. Note that this lint will never actually become a hard error - instead, we will remove the special cases for various macros, which will cause older versions of those crates to emit some other error. I've added code to fire this lint for the `time-macros-impl` case. This is the easiest case out of all of our current back-compat hacks - the crate was renamed to `time-macros`, so seeing a filename with `time-macros-impl` guarantees that an older version of the parent `time` crate is in use. When Cargo's future-incompat-report feature gets stabilized, affected users will start to see future-incompat warnings when they build their crates.
This commit is contained in:
parent
d6eaea1c88
commit
f190bc4f47
8 changed files with 206 additions and 65 deletions
|
@ -11,11 +11,9 @@ use crate::tokenstream::TokenTree;
|
|||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_macros::HashStable_Generic;
|
||||
use rustc_span::hygiene::ExpnKind;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::{self, edition::Edition, FileName, RealFileName, Span, DUMMY_SP};
|
||||
use rustc_span::{self, edition::Edition, Span, DUMMY_SP};
|
||||
use std::borrow::Cow;
|
||||
use std::{fmt, mem};
|
||||
|
||||
|
@ -813,52 +811,6 @@ impl Nonterminal {
|
|||
}
|
||||
false
|
||||
}
|
||||
|
||||
// See issue #74616 for details
|
||||
pub fn ident_name_compatibility_hack(
|
||||
&self,
|
||||
orig_span: Span,
|
||||
source_map: &SourceMap,
|
||||
) -> Option<(Ident, bool)> {
|
||||
if let NtIdent(ident, is_raw) = self {
|
||||
if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind {
|
||||
let filename = source_map.span_to_filename(orig_span);
|
||||
if let FileName::Real(RealFileName::Named(path)) = filename {
|
||||
let matches_prefix = |prefix, filename| {
|
||||
// Check for a path that ends with 'prefix*/src/<filename>'
|
||||
let mut iter = path.components().rev();
|
||||
iter.next().and_then(|p| p.as_os_str().to_str()) == Some(filename)
|
||||
&& iter.next().and_then(|p| p.as_os_str().to_str()) == Some("src")
|
||||
&& iter
|
||||
.next()
|
||||
.and_then(|p| p.as_os_str().to_str())
|
||||
.map_or(false, |p| p.starts_with(prefix))
|
||||
};
|
||||
|
||||
if (macro_name == sym::impl_macros
|
||||
&& matches_prefix("time-macros-impl", "lib.rs"))
|
||||
|| (macro_name == sym::arrays && matches_prefix("js-sys", "lib.rs"))
|
||||
{
|
||||
let snippet = source_map.span_to_snippet(orig_span);
|
||||
if snippet.as_deref() == Ok("$name") {
|
||||
return Some((*ident, *is_raw));
|
||||
}
|
||||
}
|
||||
|
||||
if macro_name == sym::tuple_from_req
|
||||
&& (matches_prefix("actix-web", "extract.rs")
|
||||
|| matches_prefix("actori-web", "extract.rs"))
|
||||
{
|
||||
let snippet = source_map.span_to_snippet(orig_span);
|
||||
if snippet.as_deref() == Ok("$T") {
|
||||
return Some((*ident, *is_raw));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Nonterminal {
|
||||
|
|
|
@ -2,16 +2,21 @@ use crate::base::ExtCtxt;
|
|||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::token::Nonterminal;
|
||||
use rustc_ast::token::NtIdent;
|
||||
use rustc_ast::tokenstream::{self, CanSynthesizeMissingTokens};
|
||||
use rustc_ast::tokenstream::{DelimSpan, Spacing::*, TokenStream, TreeAndSpacing};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::Diagnostic;
|
||||
use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
|
||||
use rustc_lint_defs::BuiltinLintDiagnostics;
|
||||
use rustc_parse::lexer::nfc_normalize;
|
||||
use rustc_parse::{nt_to_tokenstream, parse_stream_from_source_str};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::hygiene::ExpnKind;
|
||||
use rustc_span::symbol::{self, kw, sym, Symbol};
|
||||
use rustc_span::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span};
|
||||
use rustc_span::{BytePos, FileName, MultiSpan, Pos, RealFileName, SourceFile, Span};
|
||||
|
||||
use pm::bridge::{server, TokenTree};
|
||||
use pm::{Delimiter, Level, LineColumn, Spacing};
|
||||
|
@ -174,9 +179,7 @@ impl FromInternal<(TreeAndSpacing, &'_ ParseSess, &'_ mut Vec<Self>)>
|
|||
}
|
||||
|
||||
Interpolated(nt) => {
|
||||
if let Some((name, is_raw)) =
|
||||
nt.ident_name_compatibility_hack(span, sess.source_map())
|
||||
{
|
||||
if let Some((name, is_raw)) = ident_name_compatibility_hack(&nt, span, sess) {
|
||||
TokenTree::Ident(Ident::new(sess, name.name, is_raw, name.span))
|
||||
} else {
|
||||
let stream = nt_to_tokenstream(&nt, sess, CanSynthesizeMissingTokens::No);
|
||||
|
@ -711,3 +714,62 @@ impl server::Span for Rustc<'_> {
|
|||
self.sess.source_map().span_to_snippet(span).ok()
|
||||
}
|
||||
}
|
||||
|
||||
// See issue #74616 for details
|
||||
fn ident_name_compatibility_hack(
|
||||
nt: &Nonterminal,
|
||||
orig_span: Span,
|
||||
sess: &ParseSess,
|
||||
) -> Option<(rustc_span::symbol::Ident, bool)> {
|
||||
if let NtIdent(ident, is_raw) = nt {
|
||||
if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind {
|
||||
let source_map = sess.source_map();
|
||||
let filename = source_map.span_to_filename(orig_span);
|
||||
if let FileName::Real(RealFileName::Named(path)) = filename {
|
||||
let matches_prefix = |prefix, filename| {
|
||||
// Check for a path that ends with 'prefix*/src/<filename>'
|
||||
let mut iter = path.components().rev();
|
||||
iter.next().and_then(|p| p.as_os_str().to_str()) == Some(filename)
|
||||
&& iter.next().and_then(|p| p.as_os_str().to_str()) == Some("src")
|
||||
&& iter
|
||||
.next()
|
||||
.and_then(|p| p.as_os_str().to_str())
|
||||
.map_or(false, |p| p.starts_with(prefix))
|
||||
};
|
||||
|
||||
let time_macros_impl =
|
||||
macro_name == sym::impl_macros && matches_prefix("time-macros-impl", "lib.rs");
|
||||
if time_macros_impl
|
||||
|| (macro_name == sym::arrays && matches_prefix("js-sys", "lib.rs"))
|
||||
{
|
||||
let snippet = source_map.span_to_snippet(orig_span);
|
||||
if snippet.as_deref() == Ok("$name") {
|
||||
if time_macros_impl {
|
||||
sess.buffer_lint_with_diagnostic(
|
||||
&PROC_MACRO_BACK_COMPAT,
|
||||
orig_span,
|
||||
ast::CRATE_NODE_ID,
|
||||
"using an old version of `time-macros-impl`",
|
||||
BuiltinLintDiagnostics::ProcMacroBackCompat(
|
||||
"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".to_string())
|
||||
);
|
||||
}
|
||||
return Some((*ident, *is_raw));
|
||||
}
|
||||
}
|
||||
|
||||
if macro_name == sym::tuple_from_req
|
||||
&& (matches_prefix("actix-web", "extract.rs")
|
||||
|| matches_prefix("actori-web", "extract.rs"))
|
||||
{
|
||||
let snippet = source_map.span_to_snippet(orig_span);
|
||||
if snippet.as_deref() == Ok("$T") {
|
||||
return Some((*ident, *is_raw));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
|
|
@ -670,6 +670,9 @@ pub trait LintContext: Sized {
|
|||
json
|
||||
);
|
||||
}
|
||||
BuiltinLintDiagnostics::ProcMacroBackCompat(note) => {
|
||||
db.note(¬e);
|
||||
}
|
||||
}
|
||||
// Rewrap `db`, and pass control to the user.
|
||||
decorate(LintDiagnosticBuilder::new(db));
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
//! compiler code, rather than using their own custom pass. Those
|
||||
//! lints are all available in `rustc_lint::builtin`.
|
||||
|
||||
use crate::{declare_lint, declare_lint_pass};
|
||||
use crate::{declare_lint, declare_lint_pass, FutureBreakage};
|
||||
use rustc_span::edition::Edition;
|
||||
|
||||
declare_lint! {
|
||||
|
@ -2955,6 +2955,7 @@ declare_lint_pass! {
|
|||
SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
|
||||
DISJOINT_CAPTURE_DROP_REORDER,
|
||||
LEGACY_DERIVE_HELPERS,
|
||||
PROC_MACRO_BACK_COMPAT,
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -3082,3 +3083,53 @@ declare_lint! {
|
|||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
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,
|
||||
Warn,
|
||||
"detects usage of old versions of certain proc-macro crates",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #83125 <https://github.com/rust-lang/rust/issues/83125>",
|
||||
edition: None,
|
||||
future_breakage: Some(FutureBreakage {
|
||||
date: None
|
||||
})
|
||||
};
|
||||
}
|
||||
|
|
|
@ -266,6 +266,7 @@ pub enum BuiltinLintDiagnostics {
|
|||
PatternsInFnsWithoutBody(Span, Ident),
|
||||
LegacyDeriveHelpers(Span),
|
||||
ExternDepSpec(String, ExternDepSpec),
|
||||
ProcMacroBackCompat(String),
|
||||
}
|
||||
|
||||
/// Lints that are buffered up early on in the `Session` before the
|
||||
|
|
|
@ -24,7 +24,8 @@ mod no_version {
|
|||
}
|
||||
|
||||
struct Foo;
|
||||
impl_macros!(Foo);
|
||||
impl_macros!(Foo); //~ WARN using an old version
|
||||
//~| WARN this was previously
|
||||
arrays!(Foo);
|
||||
other!(Foo);
|
||||
}
|
||||
|
@ -40,7 +41,8 @@ mod with_version {
|
|||
}
|
||||
|
||||
struct Foo;
|
||||
impl_macros!(Foo);
|
||||
impl_macros!(Foo); //~ WARN using an old version
|
||||
//~| WARN this was previously
|
||||
arrays!(Foo);
|
||||
other!(Foo);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
warning: using an old version of `time-macros-impl`
|
||||
--> $DIR/time-macros-impl/src/lib.rs:5:32
|
||||
|
|
||||
LL | #[my_macro] struct One($name);
|
||||
| ^^^^^
|
||||
|
|
||||
::: $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)
|
||||
|
||||
warning: using an old version of `time-macros-impl`
|
||||
--> $DIR/time-macros-impl-0.1.0/src/lib.rs:5:32
|
||||
|
|
||||
LL | #[my_macro] struct One($name);
|
||||
| ^^^^^
|
||||
|
|
||||
::: $DIR/group-compat-hack.rs:44:5
|
||||
|
|
||||
LL | impl_macros!(Foo);
|
||||
| ------------------ in this macro invocation
|
||||
|
|
||||
= 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)
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
||||
Future incompatibility report: Future breakage date: None, diagnostic:
|
||||
warning: using an old version of `time-macros-impl`
|
||||
--> $DIR/time-macros-impl/src/lib.rs:5:32
|
||||
|
|
||||
LL | #[my_macro] struct One($name);
|
||||
| ^^^^^
|
||||
|
|
||||
::: $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)
|
||||
|
||||
Future breakage date: None, diagnostic:
|
||||
warning: using an old version of `time-macros-impl`
|
||||
--> $DIR/time-macros-impl-0.1.0/src/lib.rs:5:32
|
||||
|
|
||||
LL | #[my_macro] struct One($name);
|
||||
| ^^^^^
|
||||
|
|
||||
::: $DIR/group-compat-hack.rs:44:5
|
||||
|
|
||||
LL | impl_macros!(Foo);
|
||||
| ------------------ in this macro invocation
|
||||
|
|
||||
= 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)
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl/src/lib.rs:5:21: 5:27 (#6) }, Ident { ident: "One", span: $DIR/time-macros-impl/src/lib.rs:5:28: 5:31 (#6) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:27:18: 27:21 (#0) }], span: $DIR/time-macros-impl/src/lib.rs:5:31: 5:38 (#6) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl/src/lib.rs:5:38: 5:39 (#6) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys/src/lib.rs:5:21: 5:27 (#10) }, Ident { ident: "Two", span: $DIR/js-sys/src/lib.rs:5:28: 5:31 (#10) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:28:13: 28:16 (#0) }], span: $DIR/js-sys/src/lib.rs:5:31: 5:38 (#10) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys/src/lib.rs:5:38: 5:39 (#10) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:22:25: 22:31 (#14) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:22:32: 22:37 (#14) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:29:12: 29:15 (#0) }], span: $DIR/group-compat-hack.rs:22:38: 22:43 (#14) }], span: $DIR/group-compat-hack.rs:22:37: 22:44 (#14) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:22:44: 22:45 (#14) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:21: 5:27 (#20) }, Ident { ident: "One", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:28: 5:31 (#20) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:43:18: 43:21 (#0) }], span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:31: 5:38 (#20) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:38: 5:39 (#20) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys-0.3.17/src/lib.rs:5:21: 5:27 (#24) }, Ident { ident: "Two", span: $DIR/js-sys-0.3.17/src/lib.rs:5:28: 5:31 (#24) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:44:13: 44:16 (#0) }], span: $DIR/js-sys-0.3.17/src/lib.rs:5:31: 5:38 (#24) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys-0.3.17/src/lib.rs:5:38: 5:39 (#24) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:38:25: 38:31 (#28) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:38:32: 38:37 (#28) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:45:12: 45:15 (#0) }], span: $DIR/group-compat-hack.rs:38:38: 38:43 (#28) }], span: $DIR/group-compat-hack.rs:38:37: 38:44 (#28) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:38:44: 38:45 (#28) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web/src/extract.rs:5:21: 5:27 (#33) }, Ident { ident: "Three", span: $DIR/actix-web/src/extract.rs:5:28: 5:33 (#33) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:52:21: 52:24 (#0) }], span: $DIR/actix-web/src/extract.rs:5:33: 5:37 (#33) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web/src/extract.rs:5:37: 5:38 (#33) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web-2.0.0/src/extract.rs:5:21: 5:27 (#38) }, Ident { ident: "Three", span: $DIR/actix-web-2.0.0/src/extract.rs:5:28: 5:33 (#38) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:59:21: 59:24 (#0) }], span: $DIR/actix-web-2.0.0/src/extract.rs:5:33: 5:37 (#38) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web-2.0.0/src/extract.rs:5:37: 5:38 (#38) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web/src/extract.rs:5:21: 5:27 (#43) }, Ident { ident: "Four", span: $DIR/actori-web/src/extract.rs:5:28: 5:32 (#43) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:66:21: 66:24 (#0) }], span: $DIR/actori-web/src/extract.rs:5:32: 5:36 (#43) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web/src/extract.rs:5:36: 5:37 (#43) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web-2.0.0/src/extract.rs:5:21: 5:27 (#48) }, Ident { ident: "Four", span: $DIR/actori-web-2.0.0/src/extract.rs:5:28: 5:32 (#48) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:73:21: 73:24 (#0) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:32: 5:36 (#48) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web-2.0.0/src/extract.rs:5:36: 5:37 (#48) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys/src/lib.rs:5:21: 5:27 (#10) }, Ident { ident: "Two", span: $DIR/js-sys/src/lib.rs:5:28: 5:31 (#10) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:29:13: 29:16 (#0) }], span: $DIR/js-sys/src/lib.rs:5:31: 5:38 (#10) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys/src/lib.rs:5:38: 5:39 (#10) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:22:25: 22:31 (#14) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:22:32: 22:37 (#14) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:30:12: 30:15 (#0) }], span: $DIR/group-compat-hack.rs:22:38: 22:43 (#14) }], span: $DIR/group-compat-hack.rs:22:37: 22:44 (#14) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:22:44: 22:45 (#14) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:21: 5:27 (#20) }, Ident { ident: "One", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:28: 5:31 (#20) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:44:18: 44:21 (#0) }], span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:31: 5:38 (#20) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:38: 5:39 (#20) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys-0.3.17/src/lib.rs:5:21: 5:27 (#24) }, Ident { ident: "Two", span: $DIR/js-sys-0.3.17/src/lib.rs:5:28: 5:31 (#24) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:46:13: 46:16 (#0) }], span: $DIR/js-sys-0.3.17/src/lib.rs:5:31: 5:38 (#24) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys-0.3.17/src/lib.rs:5:38: 5:39 (#24) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:39:25: 39:31 (#28) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:39:32: 39:37 (#28) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:47:12: 47:15 (#0) }], span: $DIR/group-compat-hack.rs:39:38: 39:43 (#28) }], span: $DIR/group-compat-hack.rs:39:37: 39:44 (#28) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:39:44: 39:45 (#28) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web/src/extract.rs:5:21: 5:27 (#33) }, Ident { ident: "Three", span: $DIR/actix-web/src/extract.rs:5:28: 5:33 (#33) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:54:21: 54:24 (#0) }], span: $DIR/actix-web/src/extract.rs:5:33: 5:37 (#33) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web/src/extract.rs:5:37: 5:38 (#33) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web-2.0.0/src/extract.rs:5:21: 5:27 (#38) }, Ident { ident: "Three", span: $DIR/actix-web-2.0.0/src/extract.rs:5:28: 5:33 (#38) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:61:21: 61:24 (#0) }], span: $DIR/actix-web-2.0.0/src/extract.rs:5:33: 5:37 (#38) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web-2.0.0/src/extract.rs:5:37: 5:38 (#38) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web/src/extract.rs:5:21: 5:27 (#43) }, Ident { ident: "Four", span: $DIR/actori-web/src/extract.rs:5:28: 5:32 (#43) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:68:21: 68:24 (#0) }], span: $DIR/actori-web/src/extract.rs:5:32: 5:36 (#43) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web/src/extract.rs:5:36: 5:37 (#43) }]
|
||||
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web-2.0.0/src/extract.rs:5:21: 5:27 (#48) }, Ident { ident: "Four", span: $DIR/actori-web-2.0.0/src/extract.rs:5:28: 5:32 (#48) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:75:21: 75:24 (#0) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:32: 5:36 (#48) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web-2.0.0/src/extract.rs:5:36: 5:37 (#48) }]
|
||||
|
|
Loading…
Add table
Reference in a new issue