From 44bf6b6f55be89926d9f18b4d90a9eaefb84d02c Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 20 Jul 2019 10:49:02 +0100 Subject: [PATCH 1/2] tests: Add minimal reproduction of #61963. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds a reproduction of the error reported in servo which demonstrates the current, incorrect behaviour. Co-authored-by: Rémy Rakić --- .../ui/suggestions/auxiliary/issue-61963-1.rs | 40 ++++++++++++++++++ .../ui/suggestions/auxiliary/issue-61963.rs | 41 +++++++++++++++++++ src/test/ui/suggestions/issue-61963.rs | 25 +++++++++++ src/test/ui/suggestions/issue-61963.stderr | 20 +++++++++ 4 files changed, 126 insertions(+) create mode 100644 src/test/ui/suggestions/auxiliary/issue-61963-1.rs create mode 100644 src/test/ui/suggestions/auxiliary/issue-61963.rs create mode 100644 src/test/ui/suggestions/issue-61963.rs create mode 100644 src/test/ui/suggestions/issue-61963.stderr diff --git a/src/test/ui/suggestions/auxiliary/issue-61963-1.rs b/src/test/ui/suggestions/auxiliary/issue-61963-1.rs new file mode 100644 index 0000000000000..6c2df7e84e07c --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/issue-61963-1.rs @@ -0,0 +1,40 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Group, TokenStream, TokenTree}; + +// This macro exists as part of a reproduction of #61963 but without using quote/syn/proc_macro2. + +#[proc_macro_derive(DomObject)] +pub fn expand_token_stream(input: TokenStream) -> TokenStream { + // Construct a dummy span - `#0 bytes(0..0)` - which is present in the input because + // of the specially crafted generated tokens in the `attribute-crate` proc-macro. + let dummy_span = input.clone().into_iter().nth(0).unwrap().span(); + + // Define what the macro would output if constructed properly from the source using syn/quote. + let output: TokenStream = "impl Bar for ((), Qux >) { } + impl Bar for ((), Box) { }".parse().unwrap(); + + let mut tokens: Vec<_> = output.into_iter().collect(); + // Adjust token spans to match the original crate (which would use `quote`). Some of the + // generated tokens point to the dummy span. + for token in tokens.iter_mut() { + if let TokenTree::Group(group) = token { + let mut tokens: Vec<_> = group.stream().into_iter().collect(); + for token in tokens.iter_mut().skip(2) { + token.set_span(dummy_span); + } + + let mut stream = TokenStream::new(); + stream.extend(tokens); + *group = Group::new(group.delimiter(), stream); + } + } + + let mut output = TokenStream::new(); + output.extend(tokens); + output +} diff --git a/src/test/ui/suggestions/auxiliary/issue-61963.rs b/src/test/ui/suggestions/auxiliary/issue-61963.rs new file mode 100644 index 0000000000000..e86f1610ab0d0 --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/issue-61963.rs @@ -0,0 +1,41 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Group, Spacing, Punct, TokenTree, TokenStream}; + +// This macro exists as part of a reproduction of #61963 but without using quote/syn/proc_macro2. + +#[proc_macro_attribute] +pub fn dom_struct(_: TokenStream, input: TokenStream) -> TokenStream { + // Construct the expected output tokens - the input but with a `#[derive(DomObject)]` applied. + let attributes: TokenStream = + "#[derive(DomObject)]".to_string().parse().unwrap(); + let output: TokenStream = attributes.into_iter() + .chain(input.into_iter()).collect(); + + let mut tokens: Vec<_> = output.into_iter().collect(); + // Adjust the spacing of `>` tokens to match what `quote` would produce. + for token in tokens.iter_mut() { + if let TokenTree::Group(group) = token { + let mut tokens: Vec<_> = group.stream().into_iter().collect(); + for token in tokens.iter_mut() { + if let TokenTree::Punct(p) = token { + if p.as_char() == '>' { + *p = Punct::new('>', Spacing::Alone); + } + } + } + + let mut stream = TokenStream::new(); + stream.extend(tokens); + *group = Group::new(group.delimiter(), stream); + } + } + + let mut output = TokenStream::new(); + output.extend(tokens); + output +} diff --git a/src/test/ui/suggestions/issue-61963.rs b/src/test/ui/suggestions/issue-61963.rs new file mode 100644 index 0000000000000..540a7c42d2fd3 --- /dev/null +++ b/src/test/ui/suggestions/issue-61963.rs @@ -0,0 +1,25 @@ +// aux-build:issue-61963.rs +// aux-build:issue-61963-1.rs +#![deny(bare_trait_objects)] + +#[macro_use] +extern crate issue_61963; +#[macro_use] +extern crate issue_61963_1; + +// This test checks that the bare trait object lint does not trigger on macro attributes that +// generate code which would trigger the lint. + +pub struct Baz; +pub trait Bar { } +pub struct Qux(T); + +#[dom_struct] +//~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] +pub struct Foo { + qux: Qux>, + bar: Box, + //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-61963.stderr b/src/test/ui/suggestions/issue-61963.stderr new file mode 100644 index 0000000000000..261b384ca5716 --- /dev/null +++ b/src/test/ui/suggestions/issue-61963.stderr @@ -0,0 +1,20 @@ +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:21:14 + | +LL | bar: Box, + | ^^^ help: use `dyn`: `dyn Bar` + | +note: lint level defined here + --> $DIR/issue-61963.rs:3:9 + | +LL | #![deny(bare_trait_objects)] + | ^^^^^^^^^^^^^^^^^^ + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:17:1 + | +LL | #[dom_struct] + | ^^^^^^^^^^^^^ help: use `dyn`: `dyn #[dom_struct]` + +error: aborting due to 2 previous errors + From cae8680544418d838344d9c258030592f0461ee9 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 26 Jul 2019 17:31:39 +0100 Subject: [PATCH 2/2] lowering: Omit bare trait lint on macro call sites This commit implements a hacky fix for detecting when a span is pointing at a macro call site so that bare trait lints are not made incorrectly. --- src/librustc/hir/lowering.rs | 22 +++++++++++++++------- src/test/ui/suggestions/issue-61963.rs | 1 - src/test/ui/suggestions/issue-61963.stderr | 10 ++-------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index c228bc2cf6b8c..248a120e741aa 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -5754,13 +5754,21 @@ impl<'a> LoweringContext<'a> { } fn maybe_lint_bare_trait(&self, span: Span, id: NodeId, is_global: bool) { - self.sess.buffer_lint_with_diagnostic( - builtin::BARE_TRAIT_OBJECTS, - id, - span, - "trait objects without an explicit `dyn` are deprecated", - builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global), - ) + // FIXME(davidtwco): This is a hack to detect macros which produce spans of the + // call site which do not have a macro backtrace. See #61963. + let is_macro_callsite = self.sess.source_map() + .span_to_snippet(span) + .map(|snippet| snippet.starts_with("#[")) + .unwrap_or(true); + if !is_macro_callsite { + self.sess.buffer_lint_with_diagnostic( + builtin::BARE_TRAIT_OBJECTS, + id, + span, + "trait objects without an explicit `dyn` are deprecated", + builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global), + ) + } } fn wrap_in_try_constructor( diff --git a/src/test/ui/suggestions/issue-61963.rs b/src/test/ui/suggestions/issue-61963.rs index 540a7c42d2fd3..c9d738f5a283e 100644 --- a/src/test/ui/suggestions/issue-61963.rs +++ b/src/test/ui/suggestions/issue-61963.rs @@ -15,7 +15,6 @@ pub trait Bar { } pub struct Qux(T); #[dom_struct] -//~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] pub struct Foo { qux: Qux>, bar: Box, diff --git a/src/test/ui/suggestions/issue-61963.stderr b/src/test/ui/suggestions/issue-61963.stderr index 261b384ca5716..46943f40066ff 100644 --- a/src/test/ui/suggestions/issue-61963.stderr +++ b/src/test/ui/suggestions/issue-61963.stderr @@ -1,5 +1,5 @@ error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:21:14 + --> $DIR/issue-61963.rs:20:14 | LL | bar: Box, | ^^^ help: use `dyn`: `dyn Bar` @@ -10,11 +10,5 @@ note: lint level defined here LL | #![deny(bare_trait_objects)] | ^^^^^^^^^^^^^^^^^^ -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:17:1 - | -LL | #[dom_struct] - | ^^^^^^^^^^^^^ help: use `dyn`: `dyn #[dom_struct]` - -error: aborting due to 2 previous errors +error: aborting due to previous error