Skip to content

Commit 513ab54

Browse files
authored
Rollup merge of #63014 - davidtwco:rustfix-incorrect-dyn-suggestion, r=estebank
Stop bare trait lint applying to macro call sites Fixes #61963. Apologies for the delay with in fixing this. If anyone has a better idea how to detect this macro call site case, I'd be happy to fix this in a more robust, less hacky way. r? @estebank
2 parents 4ad743c + cae8680 commit 513ab54

File tree

5 files changed

+134
-7
lines changed

5 files changed

+134
-7
lines changed

src/librustc/hir/lowering.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -5753,13 +5753,21 @@ impl<'a> LoweringContext<'a> {
57535753
}
57545754

57555755
fn maybe_lint_bare_trait(&self, span: Span, id: NodeId, is_global: bool) {
5756-
self.sess.buffer_lint_with_diagnostic(
5757-
builtin::BARE_TRAIT_OBJECTS,
5758-
id,
5759-
span,
5760-
"trait objects without an explicit `dyn` are deprecated",
5761-
builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global),
5762-
)
5756+
// FIXME(davidtwco): This is a hack to detect macros which produce spans of the
5757+
// call site which do not have a macro backtrace. See #61963.
5758+
let is_macro_callsite = self.sess.source_map()
5759+
.span_to_snippet(span)
5760+
.map(|snippet| snippet.starts_with("#["))
5761+
.unwrap_or(true);
5762+
if !is_macro_callsite {
5763+
self.sess.buffer_lint_with_diagnostic(
5764+
builtin::BARE_TRAIT_OBJECTS,
5765+
id,
5766+
span,
5767+
"trait objects without an explicit `dyn` are deprecated",
5768+
builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global),
5769+
)
5770+
}
57635771
}
57645772

57655773
fn wrap_in_try_constructor(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// force-host
2+
// no-prefer-dynamic
3+
#![crate_type = "proc-macro"]
4+
5+
extern crate proc_macro;
6+
7+
use proc_macro::{Group, TokenStream, TokenTree};
8+
9+
// This macro exists as part of a reproduction of #61963 but without using quote/syn/proc_macro2.
10+
11+
#[proc_macro_derive(DomObject)]
12+
pub fn expand_token_stream(input: TokenStream) -> TokenStream {
13+
// Construct a dummy span - `#0 bytes(0..0)` - which is present in the input because
14+
// of the specially crafted generated tokens in the `attribute-crate` proc-macro.
15+
let dummy_span = input.clone().into_iter().nth(0).unwrap().span();
16+
17+
// Define what the macro would output if constructed properly from the source using syn/quote.
18+
let output: TokenStream = "impl Bar for ((), Qux<Qux<Baz> >) { }
19+
impl Bar for ((), Box<Bar>) { }".parse().unwrap();
20+
21+
let mut tokens: Vec<_> = output.into_iter().collect();
22+
// Adjust token spans to match the original crate (which would use `quote`). Some of the
23+
// generated tokens point to the dummy span.
24+
for token in tokens.iter_mut() {
25+
if let TokenTree::Group(group) = token {
26+
let mut tokens: Vec<_> = group.stream().into_iter().collect();
27+
for token in tokens.iter_mut().skip(2) {
28+
token.set_span(dummy_span);
29+
}
30+
31+
let mut stream = TokenStream::new();
32+
stream.extend(tokens);
33+
*group = Group::new(group.delimiter(), stream);
34+
}
35+
}
36+
37+
let mut output = TokenStream::new();
38+
output.extend(tokens);
39+
output
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// force-host
2+
// no-prefer-dynamic
3+
#![crate_type = "proc-macro"]
4+
5+
extern crate proc_macro;
6+
7+
use proc_macro::{Group, Spacing, Punct, TokenTree, TokenStream};
8+
9+
// This macro exists as part of a reproduction of #61963 but without using quote/syn/proc_macro2.
10+
11+
#[proc_macro_attribute]
12+
pub fn dom_struct(_: TokenStream, input: TokenStream) -> TokenStream {
13+
// Construct the expected output tokens - the input but with a `#[derive(DomObject)]` applied.
14+
let attributes: TokenStream =
15+
"#[derive(DomObject)]".to_string().parse().unwrap();
16+
let output: TokenStream = attributes.into_iter()
17+
.chain(input.into_iter()).collect();
18+
19+
let mut tokens: Vec<_> = output.into_iter().collect();
20+
// Adjust the spacing of `>` tokens to match what `quote` would produce.
21+
for token in tokens.iter_mut() {
22+
if let TokenTree::Group(group) = token {
23+
let mut tokens: Vec<_> = group.stream().into_iter().collect();
24+
for token in tokens.iter_mut() {
25+
if let TokenTree::Punct(p) = token {
26+
if p.as_char() == '>' {
27+
*p = Punct::new('>', Spacing::Alone);
28+
}
29+
}
30+
}
31+
32+
let mut stream = TokenStream::new();
33+
stream.extend(tokens);
34+
*group = Group::new(group.delimiter(), stream);
35+
}
36+
}
37+
38+
let mut output = TokenStream::new();
39+
output.extend(tokens);
40+
output
41+
}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// aux-build:issue-61963.rs
2+
// aux-build:issue-61963-1.rs
3+
#![deny(bare_trait_objects)]
4+
5+
#[macro_use]
6+
extern crate issue_61963;
7+
#[macro_use]
8+
extern crate issue_61963_1;
9+
10+
// This test checks that the bare trait object lint does not trigger on macro attributes that
11+
// generate code which would trigger the lint.
12+
13+
pub struct Baz;
14+
pub trait Bar { }
15+
pub struct Qux<T>(T);
16+
17+
#[dom_struct]
18+
pub struct Foo {
19+
qux: Qux<Qux<Baz>>,
20+
bar: Box<Bar>,
21+
//~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
22+
}
23+
24+
fn main() {}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: trait objects without an explicit `dyn` are deprecated
2+
--> $DIR/issue-61963.rs:20:14
3+
|
4+
LL | bar: Box<Bar>,
5+
| ^^^ help: use `dyn`: `dyn Bar`
6+
|
7+
note: lint level defined here
8+
--> $DIR/issue-61963.rs:3:9
9+
|
10+
LL | #![deny(bare_trait_objects)]
11+
| ^^^^^^^^^^^^^^^^^^
12+
13+
error: aborting due to previous error
14+

0 commit comments

Comments
 (0)