From 4a384089402cb4b90674554467b7a506a00a5d59 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 8 Dec 2018 20:30:38 +0300 Subject: Remove `eliminate_crate_var` and special pretty-printing for `$crate` --- src/libsyntax/ext/base.rs | 2 -- src/libsyntax/ext/expand.rs | 5 +---- src/libsyntax/print/pprust.rs | 25 ++----------------------- 3 files changed, 3 insertions(+), 29 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 310cf27689b..b807a65f6ae 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -732,7 +732,6 @@ pub type NamedSyntaxExtension = (Name, SyntaxExtension); pub trait Resolver { fn next_node_id(&mut self) -> ast::NodeId; fn get_module_scope(&mut self, id: ast::NodeId) -> Mark; - fn eliminate_crate_var(&mut self, item: P) -> P; fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment, derives: &[Mark]); @@ -766,7 +765,6 @@ pub struct DummyResolver; impl Resolver for DummyResolver { fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID } fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() } - fn eliminate_crate_var(&mut self, item: P) -> P { item } fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment, _derives: &[Mark]) {} diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 03c7aa96824..57ccc3e9817 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -203,10 +203,7 @@ fn macro_bang_format(path: &ast::Path) -> ExpnFormat { if i != 0 { path_str.push_str("::"); } - - if segment.ident.name != keywords::PathRoot.name() && - segment.ident.name != keywords::DollarCrate.name() - { + if segment.ident.name != keywords::PathRoot.name() { path_str.push_str(&segment.ident.as_str()) } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 41165c7e36d..8250587f9e0 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -16,7 +16,6 @@ use util::parser::{self, AssocOp, Fixity}; use attr; use source_map::{self, SourceMap, Spanned}; use syntax_pos::{self, BytePos}; -use syntax_pos::hygiene::{Mark, SyntaxContext}; use parse::token::{self, BinOpToken, Token}; use parse::lexer::comments; use parse::{self, ParseSess}; @@ -724,12 +723,8 @@ pub trait PrintState<'a> { if i > 0 { self.writer().word("::")? } - if segment.ident.name != keywords::PathRoot.name() && - segment.ident.name != keywords::DollarCrate.name() - { + if segment.ident.name != keywords::PathRoot.name() { self.writer().word(segment.ident.as_str().get())?; - } else if segment.ident.name == keywords::DollarCrate.name() { - self.print_dollar_crate(segment.ident.span.ctxt())?; } } Ok(()) @@ -842,19 +837,6 @@ pub trait PrintState<'a> { } fn nbsp(&mut self) -> io::Result<()> { self.writer().word(" ") } - - fn print_dollar_crate(&mut self, mut ctxt: SyntaxContext) -> io::Result<()> { - if let Some(mark) = ctxt.adjust(Mark::root()) { - // Make a best effort to print something that complies - if mark.is_builtin() { - if let Some(name) = std_inject::injected_crate_name() { - self.writer().word("::")?; - self.writer().word(name)?; - } - } - } - Ok(()) - } } impl<'a> PrintState<'a> for State<'a> { @@ -2463,14 +2445,11 @@ impl<'a> State<'a> { colons_before_params: bool) -> io::Result<()> { - if segment.ident.name != keywords::PathRoot.name() && - segment.ident.name != keywords::DollarCrate.name() { + if segment.ident.name != keywords::PathRoot.name() { self.print_ident(segment.ident)?; if let Some(ref args) = segment.args { self.print_generic_args(args, colons_before_params)?; } - } else if segment.ident.name == keywords::DollarCrate.name() { - self.print_dollar_crate(segment.ident.span.ctxt())?; } Ok(()) } -- cgit 1.4.1-3-g733a5 From 69c66286a9a3240309cc5474478ad0a2186e2bce Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 9 Dec 2018 17:46:12 +0300 Subject: Reintroduce special pretty-printing for `$crate` when it's necessary for proc macros --- src/librustc_resolve/build_reduced_graph.rs | 11 + src/libsyntax/print/pprust.rs | 27 ++- src/libsyntax_pos/hygiene.rs | 26 ++- src/test/pretty/issue-4264.pp | 4 +- .../proc-macro/auxiliary/dollar-crate-external.rs | 16 ++ src/test/ui/proc-macro/auxiliary/dollar-crate.rs | 18 +- src/test/ui/proc-macro/dollar-crate.rs | 32 ++- src/test/ui/proc-macro/dollar-crate.stderr | 23 ++ src/test/ui/proc-macro/dollar-crate.stdout | 260 +++++++++++++++++++++ 9 files changed, 403 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs create mode 100644 src/test/ui/proc-macro/dollar-crate.stderr create mode 100644 src/test/ui/proc-macro/dollar-crate.stdout (limited to 'src/libsyntax') diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index f082d776969..6cfa9f95082 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -1035,4 +1035,15 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { } visit::walk_attribute(self, attr); } + + fn visit_ident(&mut self, ident: Ident) { + if ident.name == keywords::DollarCrate.name() { + let name = match self.resolver.resolve_crate_root(ident).kind { + ModuleKind::Def(_, name) if name != keywords::Invalid.name() => name, + _ => keywords::Crate.name(), + }; + ident.span.ctxt().set_dollar_crate_name(name); + } + visit::walk_ident(self, ident); + } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 8250587f9e0..5e7707f4e5c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -724,7 +724,11 @@ pub trait PrintState<'a> { self.writer().word("::")? } if segment.ident.name != keywords::PathRoot.name() { - self.writer().word(segment.ident.as_str().get())?; + if segment.ident.name == keywords::DollarCrate.name() { + self.print_dollar_crate(segment.ident)?; + } else { + self.writer().word(segment.ident.as_str().get())?; + } } } Ok(()) @@ -837,6 +841,21 @@ pub trait PrintState<'a> { } fn nbsp(&mut self) -> io::Result<()> { self.writer().word(" ") } + + // AST pretty-printer is used as a fallback for turning AST structures into token streams for + // proc macros. Additionally, proc macros may stringify their input and expect it survive the + // stringification (especially true for proc macro derives written between Rust 1.15 and 1.30). + // So we need to somehow pretty-print `$crate` in paths in a way preserving at least some of + // its hygiene data, most importantly name of the crate it refers to. + // As a result we print `$crate` as `crate` if it refers to the local crate + // and as `::other_crate_name` if it refers to some other crate. + fn print_dollar_crate(&mut self, ident: ast::Ident) -> io::Result<()> { + let name = ident.span.ctxt().dollar_crate_name(); + if !ast::Ident::with_empty_ctxt(name).is_path_segment_keyword() { + self.writer().word("::")?; + } + self.writer().word(name.as_str().get()) + } } impl<'a> PrintState<'a> for State<'a> { @@ -2446,7 +2465,11 @@ impl<'a> State<'a> { -> io::Result<()> { if segment.ident.name != keywords::PathRoot.name() { - self.print_ident(segment.ident)?; + if segment.ident.name == keywords::DollarCrate.name() { + self.print_dollar_crate(segment.ident)?; + } else { + self.print_ident(segment.ident)?; + } if let Some(ref args) = segment.args { self.print_generic_args(args, colons_before_params)?; } diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 72b48ede58e..3dc884a94c0 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -18,11 +18,11 @@ use GLOBALS; use Span; use edition::{Edition, DEFAULT_EDITION}; -use symbol::Symbol; +use symbol::{keywords, Symbol}; use serialize::{Encodable, Decodable, Encoder, Decoder}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use std::fmt; +use std::{fmt, mem}; /// A SyntaxContext represents a chain of macro expansions (represented by marks). #[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)] @@ -37,6 +37,8 @@ struct SyntaxContextData { opaque: SyntaxContext, // This context, but with all transparent marks filtered away. opaque_and_semitransparent: SyntaxContext, + // Name of the crate to which `$crate` with this context would resolve. + dollar_crate_name: Symbol, } /// A mark is a unique id associated with a macro expansion. @@ -200,6 +202,7 @@ impl HygieneData { prev_ctxt: SyntaxContext(0), opaque: SyntaxContext(0), opaque_and_semitransparent: SyntaxContext(0), + dollar_crate_name: keywords::DollarCrate.name(), }], markings: FxHashMap::default(), default_edition: DEFAULT_EDITION, @@ -258,6 +261,7 @@ impl SyntaxContext { prev_ctxt: SyntaxContext::empty(), opaque: SyntaxContext::empty(), opaque_and_semitransparent: SyntaxContext::empty(), + dollar_crate_name: keywords::DollarCrate.name(), }); SyntaxContext(data.syntax_contexts.len() as u32 - 1) }) @@ -324,6 +328,7 @@ impl SyntaxContext { prev_ctxt, opaque: new_opaque, opaque_and_semitransparent: new_opaque, + dollar_crate_name: keywords::DollarCrate.name(), }); new_opaque }); @@ -341,6 +346,7 @@ impl SyntaxContext { prev_ctxt, opaque, opaque_and_semitransparent: new_opaque_and_semitransparent, + dollar_crate_name: keywords::DollarCrate.name(), }); new_opaque_and_semitransparent }); @@ -356,6 +362,7 @@ impl SyntaxContext { prev_ctxt, opaque, opaque_and_semitransparent, + dollar_crate_name: keywords::DollarCrate.name(), }); new_opaque_and_semitransparent_and_transparent }) @@ -510,6 +517,21 @@ impl SyntaxContext { pub fn outer(self) -> Mark { HygieneData::with(|data| data.syntax_contexts[self.0 as usize].outer_mark) } + + pub fn dollar_crate_name(self) -> Symbol { + HygieneData::with(|data| data.syntax_contexts[self.0 as usize].dollar_crate_name) + } + + pub fn set_dollar_crate_name(self, dollar_crate_name: Symbol) { + HygieneData::with(|data| { + let prev_dollar_crate_name = mem::replace( + &mut data.syntax_contexts[self.0 as usize].dollar_crate_name, dollar_crate_name + ); + assert!(dollar_crate_name == prev_dollar_crate_name || + prev_dollar_crate_name == keywords::DollarCrate.name(), + "$crate name is reset for a syntax context"); + }) + } } impl fmt::Debug for SyntaxContext { diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 5f42b86c82a..3b01ab3a47b 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -39,8 +39,8 @@ pub fn bar() ({ - ((::fmt::format as - for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((<::fmt::Arguments>::new_v1 + (($crate::fmt::format as + for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((<$crate::fmt::Arguments>::new_v1 as fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments<'_>::new_v1})((&([("test" as diff --git a/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs b/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs new file mode 100644 index 00000000000..8f15a2b975b --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs @@ -0,0 +1,16 @@ +pub type S = u8; + +#[macro_export] +macro_rules! external { + () => { + dollar_crate::m! { + struct M($crate::S); + } + + #[dollar_crate::a] + struct A($crate::S); + + #[derive(dollar_crate::d)] + struct D($crate::S); + }; +} diff --git a/src/test/ui/proc-macro/auxiliary/dollar-crate.rs b/src/test/ui/proc-macro/auxiliary/dollar-crate.rs index b0727a33332..d0ea850d4e3 100644 --- a/src/test/ui/proc-macro/auxiliary/dollar-crate.rs +++ b/src/test/ui/proc-macro/auxiliary/dollar-crate.rs @@ -7,6 +7,22 @@ extern crate proc_macro; use proc_macro::TokenStream; #[proc_macro] -pub fn normalize(input: TokenStream) -> TokenStream { +pub fn m(input: TokenStream) -> TokenStream { + println!("PROC MACRO INPUT (PRETTY-PRINTED): {}", input); + println!("PROC MACRO INPUT: {:#?}", input); + input.into_iter().collect() +} + +#[proc_macro_attribute] +pub fn a(_args: TokenStream, input: TokenStream) -> TokenStream { + println!("ATTRIBUTE INPUT (PRETTY-PRINTED): {}", input); + println!("ATTRIBUTE INPUT: {:#?}", input); + input.into_iter().collect() +} + +#[proc_macro_derive(d)] +pub fn d(input: TokenStream) -> TokenStream { + println!("DERIVE INPUT (PRETTY-PRINTED): {}", input); + println!("DERIVE INPUT: {:#?}", input); input.into_iter().collect() } diff --git a/src/test/ui/proc-macro/dollar-crate.rs b/src/test/ui/proc-macro/dollar-crate.rs index b8b1ddd5d1c..3f4a01cb2dc 100644 --- a/src/test/ui/proc-macro/dollar-crate.rs +++ b/src/test/ui/proc-macro/dollar-crate.rs @@ -1,16 +1,34 @@ -// compile-pass +// edition:2018 +// compile-flags:--extern dollar_crate --extern dollar_crate_external // aux-build:dollar-crate.rs +// aux-build:dollar-crate-external.rs -extern crate dollar_crate; +// Anonymize unstable non-dummy spans while still showing dummy spans `0..0`. +// normalize-stdout-test "bytes\([^0]\w*\.\.(\w+)\)" -> "bytes(LO..$1)" +// normalize-stdout-test "bytes\((\w+)\.\.[^0]\w*\)" -> "bytes($1..HI)" type S = u8; -macro_rules! check { () => { - dollar_crate::normalize! { - type A = $crate::S; +mod local { + macro_rules! local { + () => { + dollar_crate::m! { + struct M($crate::S); + } + + #[dollar_crate::a] + struct A($crate::S); + + #[derive(dollar_crate::d)] + struct D($crate::S); //~ ERROR the name `D` is defined multiple times + }; } -}} -check!(); + local!(); +} + +mod external { + dollar_crate_external::external!(); //~ ERROR the name `D` is defined multiple times +} fn main() {} diff --git a/src/test/ui/proc-macro/dollar-crate.stderr b/src/test/ui/proc-macro/dollar-crate.stderr new file mode 100644 index 00000000000..171562a5aff --- /dev/null +++ b/src/test/ui/proc-macro/dollar-crate.stderr @@ -0,0 +1,23 @@ +error[E0428]: the name `D` is defined multiple times + --> $DIR/dollar-crate.rs:23:13 + | +LL | struct D($crate::S); //~ ERROR the name `D` is defined multiple times + | ^^^^^^^^^^^^^^^^^^^^ `D` redefined here +... +LL | local!(); + | --------- in this macro invocation + | + = note: `D` must be defined only once in the type namespace of this module + +error[E0428]: the name `D` is defined multiple times + --> $DIR/dollar-crate.rs:31:5 + | +LL | dollar_crate_external::external!(); //~ ERROR the name `D` is defined multiple times + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `D` redefined here + | + = note: `D` must be defined only once in the type namespace of this module + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout new file mode 100644 index 00000000000..8e254854e32 --- /dev/null +++ b/src/test/ui/proc-macro/dollar-crate.stdout @@ -0,0 +1,260 @@ +PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ; +PROC MACRO INPUT: TokenStream [ + Ident { + ident: "struct", + span: #2 bytes(LO..HI) + }, + Ident { + ident: "M", + span: #2 bytes(LO..HI) + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: #2 bytes(LO..HI) + }, + Punct { + ch: ':', + spacing: Joint, + span: #2 bytes(LO..HI) + }, + Punct { + ch: ':', + spacing: Alone, + span: #2 bytes(LO..HI) + }, + Ident { + ident: "S", + span: #2 bytes(LO..HI) + } + ], + span: #2 bytes(LO..HI) + }, + Punct { + ch: ';', + spacing: Alone, + span: #2 bytes(LO..HI) + } +] +ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(crate::S); +ATTRIBUTE INPUT: TokenStream [ + Ident { + ident: "struct", + span: #0 bytes(0..0) + }, + Ident { + ident: "A", + span: #0 bytes(0..0) + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "crate", + span: #0 bytes(0..0) + }, + Punct { + ch: ':', + spacing: Joint, + span: #0 bytes(0..0) + }, + Punct { + ch: ':', + spacing: Alone, + span: #0 bytes(0..0) + }, + Ident { + ident: "S", + span: #0 bytes(0..0) + } + ], + span: #0 bytes(0..0) + }, + Punct { + ch: ';', + spacing: Alone, + span: #0 bytes(0..0) + } +] +DERIVE INPUT (PRETTY-PRINTED): struct D(crate::S); +DERIVE INPUT: TokenStream [ + Ident { + ident: "struct", + span: #0 bytes(0..0) + }, + Ident { + ident: "D", + span: #0 bytes(0..0) + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "crate", + span: #0 bytes(0..0) + }, + Punct { + ch: ':', + spacing: Joint, + span: #0 bytes(0..0) + }, + Punct { + ch: ':', + spacing: Alone, + span: #0 bytes(0..0) + }, + Ident { + ident: "S", + span: #0 bytes(0..0) + } + ], + span: #0 bytes(0..0) + }, + Punct { + ch: ';', + spacing: Alone, + span: #0 bytes(0..0) + } +] +PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ; +PROC MACRO INPUT: TokenStream [ + Ident { + ident: "struct", + span: #10 bytes(LO..HI) + }, + Ident { + ident: "M", + span: #10 bytes(LO..HI) + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: #10 bytes(LO..HI) + }, + Punct { + ch: ':', + spacing: Joint, + span: #10 bytes(LO..HI) + }, + Punct { + ch: ':', + spacing: Alone, + span: #10 bytes(LO..HI) + }, + Ident { + ident: "S", + span: #10 bytes(LO..HI) + } + ], + span: #10 bytes(LO..HI) + }, + Punct { + ch: ';', + spacing: Alone, + span: #10 bytes(LO..HI) + } +] +ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(::dollar_crate_external::S); +ATTRIBUTE INPUT: TokenStream [ + Ident { + ident: "struct", + span: #0 bytes(0..0) + }, + Ident { + ident: "A", + span: #0 bytes(0..0) + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: ':', + spacing: Joint, + span: #0 bytes(0..0) + }, + Punct { + ch: ':', + spacing: Alone, + span: #0 bytes(0..0) + }, + Ident { + ident: "dollar_crate_external", + span: #0 bytes(0..0) + }, + Punct { + ch: ':', + spacing: Joint, + span: #0 bytes(0..0) + }, + Punct { + ch: ':', + spacing: Alone, + span: #0 bytes(0..0) + }, + Ident { + ident: "S", + span: #0 bytes(0..0) + } + ], + span: #0 bytes(0..0) + }, + Punct { + ch: ';', + spacing: Alone, + span: #0 bytes(0..0) + } +] +DERIVE INPUT (PRETTY-PRINTED): struct D(::dollar_crate_external::S); +DERIVE INPUT: TokenStream [ + Ident { + ident: "struct", + span: #0 bytes(0..0) + }, + Ident { + ident: "D", + span: #0 bytes(0..0) + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: ':', + spacing: Joint, + span: #0 bytes(0..0) + }, + Punct { + ch: ':', + spacing: Alone, + span: #0 bytes(0..0) + }, + Ident { + ident: "dollar_crate_external", + span: #0 bytes(0..0) + }, + Punct { + ch: ':', + spacing: Joint, + span: #0 bytes(0..0) + }, + Punct { + ch: ':', + spacing: Alone, + span: #0 bytes(0..0) + }, + Ident { + ident: "S", + span: #0 bytes(0..0) + } + ], + span: #0 bytes(0..0) + }, + Punct { + ch: ';', + spacing: Alone, + span: #0 bytes(0..0) + } +] -- cgit 1.4.1-3-g733a5 From f756257fb7a5a6ff9fedd83ef03ed09a34bfef13 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 11 Dec 2018 02:26:31 +0300 Subject: Do not interpret mismatches from pretty-printed `$crate` as token stream invalidation --- src/libsyntax/parse/token.rs | 4 +- src/libsyntax/tokenstream.rs | 4 +- src/test/ui/proc-macro/dollar-crate.stderr | 10 +++- src/test/ui/proc-macro/dollar-crate.stdout | 92 ++++++++++++------------------ 4 files changed, 50 insertions(+), 60 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index ed746657459..badcc4ed876 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -633,7 +633,9 @@ impl Token { (&Shebang(a), &Shebang(b)) => a == b, (&Lifetime(a), &Lifetime(b)) => a.name == b.name, - (&Ident(a, b), &Ident(c, d)) => a.name == c.name && b == d, + (&Ident(a, b), &Ident(c, d)) => b == d && (a.name == c.name || + a.name == keywords::DollarCrate.name() || + c.name == keywords::DollarCrate.name()), (&Literal(ref a, b), &Literal(ref c, d)) => { b == d && a.probably_equal_for_proc_macro(c) diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index c11ef33f931..013ecd3d343 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -348,7 +348,9 @@ impl TokenStream { | TokenTree::Token(_, Token::Semi) // The pretty printer collapses whitespace arbitrarily and can // introduce whitespace from `NoDelim`. - | TokenTree::Token(_, Token::Whitespace) => false, + | TokenTree::Token(_, Token::Whitespace) + // The pretty printer can turn `$crate` into `::crate_name` + | TokenTree::Token(_, Token::ModSep) => false, _ => true } } diff --git a/src/test/ui/proc-macro/dollar-crate.stderr b/src/test/ui/proc-macro/dollar-crate.stderr index 171562a5aff..75d3e17802e 100644 --- a/src/test/ui/proc-macro/dollar-crate.stderr +++ b/src/test/ui/proc-macro/dollar-crate.stderr @@ -2,7 +2,10 @@ error[E0428]: the name `D` is defined multiple times --> $DIR/dollar-crate.rs:23:13 | LL | struct D($crate::S); //~ ERROR the name `D` is defined multiple times - | ^^^^^^^^^^^^^^^^^^^^ `D` redefined here + | ^^^^^^^^^^^^^^^^^^^^ + | | + | `D` redefined here + | previous definition of the type `D` here ... LL | local!(); | --------- in this macro invocation @@ -13,7 +16,10 @@ error[E0428]: the name `D` is defined multiple times --> $DIR/dollar-crate.rs:31:5 | LL | dollar_crate_external::external!(); //~ ERROR the name `D` is defined multiple times - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `D` redefined here + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `D` redefined here + | previous definition of the type `D` here | = note: `D` must be defined only once in the type namespace of this module = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout index 8e254854e32..c47b3603f41 100644 --- a/src/test/ui/proc-macro/dollar-crate.stdout +++ b/src/test/ui/proc-macro/dollar-crate.stdout @@ -42,80 +42,80 @@ ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(crate::S); ATTRIBUTE INPUT: TokenStream [ Ident { ident: "struct", - span: #0 bytes(0..0) + span: #2 bytes(LO..HI) }, Ident { ident: "A", - span: #0 bytes(0..0) + span: #2 bytes(LO..HI) }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "crate", - span: #0 bytes(0..0) + ident: "$crate", + span: #2 bytes(LO..HI) }, Punct { ch: ':', spacing: Joint, - span: #0 bytes(0..0) + span: #2 bytes(LO..HI) }, Punct { ch: ':', spacing: Alone, - span: #0 bytes(0..0) + span: #2 bytes(LO..HI) }, Ident { ident: "S", - span: #0 bytes(0..0) + span: #2 bytes(LO..HI) } ], - span: #0 bytes(0..0) + span: #2 bytes(LO..HI) }, Punct { ch: ';', spacing: Alone, - span: #0 bytes(0..0) + span: #2 bytes(LO..HI) } ] DERIVE INPUT (PRETTY-PRINTED): struct D(crate::S); DERIVE INPUT: TokenStream [ Ident { ident: "struct", - span: #0 bytes(0..0) + span: #2 bytes(LO..HI) }, Ident { ident: "D", - span: #0 bytes(0..0) + span: #2 bytes(LO..HI) }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "crate", - span: #0 bytes(0..0) + ident: "$crate", + span: #2 bytes(LO..HI) }, Punct { ch: ':', spacing: Joint, - span: #0 bytes(0..0) + span: #2 bytes(LO..HI) }, Punct { ch: ':', spacing: Alone, - span: #0 bytes(0..0) + span: #2 bytes(LO..HI) }, Ident { ident: "S", - span: #0 bytes(0..0) + span: #2 bytes(LO..HI) } ], - span: #0 bytes(0..0) + span: #2 bytes(LO..HI) }, Punct { ch: ';', spacing: Alone, - span: #0 bytes(0..0) + span: #2 bytes(LO..HI) } ] PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ; @@ -162,99 +162,79 @@ ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(::dollar_crate_external::S); ATTRIBUTE INPUT: TokenStream [ Ident { ident: "struct", - span: #0 bytes(0..0) + span: #10 bytes(LO..HI) }, Ident { ident: "A", - span: #0 bytes(0..0) + span: #10 bytes(LO..HI) }, Group { delimiter: Parenthesis, stream: TokenStream [ - Punct { - ch: ':', - spacing: Joint, - span: #0 bytes(0..0) - }, - Punct { - ch: ':', - spacing: Alone, - span: #0 bytes(0..0) - }, Ident { - ident: "dollar_crate_external", - span: #0 bytes(0..0) + ident: "$crate", + span: #10 bytes(LO..HI) }, Punct { ch: ':', spacing: Joint, - span: #0 bytes(0..0) + span: #10 bytes(LO..HI) }, Punct { ch: ':', spacing: Alone, - span: #0 bytes(0..0) + span: #10 bytes(LO..HI) }, Ident { ident: "S", - span: #0 bytes(0..0) + span: #10 bytes(LO..HI) } ], - span: #0 bytes(0..0) + span: #10 bytes(LO..HI) }, Punct { ch: ';', spacing: Alone, - span: #0 bytes(0..0) + span: #10 bytes(LO..HI) } ] DERIVE INPUT (PRETTY-PRINTED): struct D(::dollar_crate_external::S); DERIVE INPUT: TokenStream [ Ident { ident: "struct", - span: #0 bytes(0..0) + span: #10 bytes(LO..HI) }, Ident { ident: "D", - span: #0 bytes(0..0) + span: #10 bytes(LO..HI) }, Group { delimiter: Parenthesis, stream: TokenStream [ - Punct { - ch: ':', - spacing: Joint, - span: #0 bytes(0..0) - }, - Punct { - ch: ':', - spacing: Alone, - span: #0 bytes(0..0) - }, Ident { - ident: "dollar_crate_external", - span: #0 bytes(0..0) + ident: "$crate", + span: #10 bytes(LO..HI) }, Punct { ch: ':', spacing: Joint, - span: #0 bytes(0..0) + span: #10 bytes(LO..HI) }, Punct { ch: ':', spacing: Alone, - span: #0 bytes(0..0) + span: #10 bytes(LO..HI) }, Ident { ident: "S", - span: #0 bytes(0..0) + span: #10 bytes(LO..HI) } ], - span: #0 bytes(0..0) + span: #10 bytes(LO..HI) }, Punct { ch: ';', spacing: Alone, - span: #0 bytes(0..0) + span: #10 bytes(LO..HI) } ] -- cgit 1.4.1-3-g733a5