<p dir="auto">Sorry about the long title. I couldn't find a better way to express the issue :)</p>
<p dir="auto">Given the following syntax extension:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="#![crate_type = &quot;dylib&quot;]
#![allow(unstable)]
#![feature(plugin_registrar, quote)]

extern crate syntax;
extern crate rustc;

use syntax::ast::TokenTree;
use syntax::codemap::Span;
use syntax::ext::base::{DummyResult, ExtCtxt, MacExpr, MacResult};
use rustc::plugin::Registry;

fn expand&lt;'cx&gt;(cx: &amp;'cx mut ExtCtxt, sp: Span, args: &amp;[TokenTree]) -&gt; Box&lt;MacResult + 'cx&gt; {
    match args {
        [ref tt, ..] =&gt; {
            let e = quote_expr!(cx, println!(&quot;{}&quot;, $tt));
            MacExpr::new(quote_expr!(cx, $e))
        },
        _ =&gt; DummyResult::any(sp),
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &amp;mut Registry) {
    reg.register_macro(&quot;macro_test&quot;, expand);
}"><pre class="notranslate"><span class="pl-c1">#!<span class="pl-kos">[</span>crate_type = <span class="pl-s">"dylib"</span><span class="pl-kos">]</span></span>
<span class="pl-c1">#!<span class="pl-kos">[</span>allow<span class="pl-kos">(</span>unstable<span class="pl-kos">)</span><span class="pl-kos">]</span></span>
<span class="pl-c1">#!<span class="pl-kos">[</span>feature<span class="pl-kos">(</span>plugin_registrar<span class="pl-kos">,</span> quote<span class="pl-kos">)</span><span class="pl-kos">]</span></span>

<span class="pl-k">extern</span> <span class="pl-k">crate</span> syntax<span class="pl-kos">;</span>
<span class="pl-k">extern</span> <span class="pl-k">crate</span> rustc<span class="pl-kos">;</span>

<span class="pl-k">use</span> syntax<span class="pl-kos">::</span>ast<span class="pl-kos">::</span><span class="pl-v">TokenTree</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> syntax<span class="pl-kos">::</span>codemap<span class="pl-kos">::</span><span class="pl-v">Span</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> syntax<span class="pl-kos">::</span>ext<span class="pl-kos">::</span>base<span class="pl-kos">::</span><span class="pl-kos">{</span><span class="pl-v">DummyResult</span><span class="pl-kos">,</span> <span class="pl-v">ExtCtxt</span><span class="pl-kos">,</span> <span class="pl-v">MacExpr</span><span class="pl-kos">,</span> <span class="pl-v">MacResult</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> rustc<span class="pl-kos">::</span>plugin<span class="pl-kos">::</span><span class="pl-v">Registry</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">expand</span><span class="pl-kos">&lt;</span><span class="pl-c1">'</span><span class="pl-ent">cx</span><span class="pl-kos">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">cx</span><span class="pl-kos">:</span> <span class="pl-c1">&amp;</span><span class="pl-c1">'</span><span class="pl-ent">cx</span> <span class="pl-k">mut</span> <span class="pl-smi">ExtCtxt</span><span class="pl-kos">,</span> <span class="pl-s1">sp</span><span class="pl-kos">:</span> <span class="pl-smi">Span</span><span class="pl-kos">,</span> <span class="pl-s1">args</span><span class="pl-kos">:</span> <span class="pl-c1">&amp;</span><span class="pl-kos">[</span><span class="pl-smi">TokenTree</span><span class="pl-kos">]</span><span class="pl-kos">)</span> -&gt; <span class="pl-smi">Box</span><span class="pl-kos">&lt;</span><span class="pl-smi">MacResult</span> + <span class="pl-c1">'</span><span class="pl-ent">cx</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">match</span> args <span class="pl-kos">{</span>
        <span class="pl-kos">[</span><span class="pl-k">ref</span> tt<span class="pl-kos">,</span> ..<span class="pl-kos">]</span> =&gt; <span class="pl-kos">{</span>
            <span class="pl-k">let</span> e = <span class="pl-en">quote_expr</span><span class="pl-en">!</span><span class="pl-kos">(</span>cx, println!<span class="pl-kos">(</span><span class="pl-s">"{}"</span>, $tt<span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-smi">MacExpr</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-en">quote_expr</span><span class="pl-en">!</span><span class="pl-kos">(</span>cx, $e<span class="pl-kos">)</span><span class="pl-kos">)</span>
        <span class="pl-kos">}</span><span class="pl-kos">,</span>
        _ =&gt; <span class="pl-smi">DummyResult</span><span class="pl-kos">::</span><span class="pl-en">any</span><span class="pl-kos">(</span>sp<span class="pl-kos">)</span><span class="pl-kos">,</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-c1">#<span class="pl-kos">[</span>plugin_registrar<span class="pl-kos">]</span></span>
<span class="pl-k">pub</span> <span class="pl-k">fn</span> <span class="pl-en">plugin_registrar</span><span class="pl-kos">(</span><span class="pl-s1">reg</span><span class="pl-kos">:</span> <span class="pl-c1">&amp;</span><span class="pl-k">mut</span> <span class="pl-smi">Registry</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    reg<span class="pl-kos">.</span><span class="pl-en">register_macro</span><span class="pl-kos">(</span><span class="pl-s">"macro_test"</span><span class="pl-kos">,</span> expand<span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">and this test file:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="#![feature(plugin)]

#[plugin] #[no_link] extern crate quote_fail;

#[test]
fn it_works() {
    let a = &quot;hello&quot;;
    macro_test!(a);
}"><pre class="notranslate"><span class="pl-c1">#!<span class="pl-kos">[</span>feature<span class="pl-kos">(</span>plugin<span class="pl-kos">)</span><span class="pl-kos">]</span></span>

<span class="pl-c1">#<span class="pl-kos">[</span>plugin<span class="pl-kos">]</span></span> <span class="pl-c1">#<span class="pl-kos">[</span>no_link<span class="pl-kos">]</span></span> <span class="pl-k">extern</span> <span class="pl-k">crate</span> quote_fail<span class="pl-kos">;</span>

<span class="pl-c1">#<span class="pl-kos">[</span>test<span class="pl-kos">]</span></span>
<span class="pl-k">fn</span> <span class="pl-en">it_works</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> a = <span class="pl-s">"hello"</span><span class="pl-kos">;</span>
    <span class="pl-en">macro_test</span><span class="pl-en">!</span><span class="pl-kos">(</span>a<span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">The latter fails to compile with the following error:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&lt;quote expansion&gt;:1:27: 1:28 error: unresolved name `a`
&lt;quote expansion&gt;:1 name_228,ctxt_0!(&quot;{}&quot; , a)
                                              ^
note: in expansion of format_args!
&lt;std macros&gt;:2:42: 2:75 note: expansion site
&lt;std macros&gt;:1:1: 2:77 note: in expansion of println!
&lt;quote expansion&gt;:1:1: 1:29 note: expansion site
/home/chris/dev/quote_fail/tests/tests.rs:1:1: 9:1 note: in expansion of macro_test!
/home/chris/dev/quote_fail/tests/tests.rs:8:5: 8:20 note: expansion site
error: aborting due to previous error
Could not compile `quote_fail`."><pre class="notranslate"><code class="notranslate">&lt;quote expansion&gt;:1:27: 1:28 error: unresolved name `a`
&lt;quote expansion&gt;:1 name_228,ctxt_0!("{}" , a)
                                              ^
note: in expansion of format_args!
&lt;std macros&gt;:2:42: 2:75 note: expansion site
&lt;std macros&gt;:1:1: 2:77 note: in expansion of println!
&lt;quote expansion&gt;:1:1: 1:29 note: expansion site
/home/chris/dev/quote_fail/tests/tests.rs:1:1: 9:1 note: in expansion of macro_test!
/home/chris/dev/quote_fail/tests/tests.rs:8:5: 8:20 note: expansion site
error: aborting due to previous error
Could not compile `quote_fail`.
</code></pre></div>
<p dir="auto">This error goes away if I do either of these things:</p>
<ul dir="auto">
<li>Remove the <code class="notranslate">println!</code> call, i.e. replace <code class="notranslate">println!("{}", $tt)</code> with <code class="notranslate">$tt</code></li>
<li>Call <code class="notranslate">quote_expr!</code> only once instead of twice, i.e. <code class="notranslate">MacExpr::new(e)</code></li>
</ul>
<p dir="auto">I'm using <code class="notranslate">rustc</code> commit <code class="notranslate">8903c21</code> built <code class="notranslate">2015-01-16</code> on Ubuntu 14.10 x86_64.</p>
<p dir="auto"><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="38120612" data-permission-text="Title is private" data-url="https://github.com/rust-lang/rust/issues/15750" data-hovercard-type="issue" data-hovercard-url="/rust-lang/rust/issues/15750/hovercard" href="https://github.com/rust-lang/rust/issues/15750">#15750</a> is fixed now, but a variant of the same issue occurs when quoting a macro invocation.</p>
<p dir="auto">Using <code class="notranslate">plugin.rs</code> from <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="38120612" data-permission-text="Title is private" data-url="https://github.com/rust-lang/rust/issues/15750" data-hovercard-type="issue" data-hovercard-url="/rust-lang/rust/issues/15750/hovercard" href="https://github.com/rust-lang/rust/issues/15750">#15750</a> and this <code class="notranslate">test.rs</code>:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="#![feature(phase)]

#[phase(plugin)]
extern crate plugin;

fn main() {
    let x = true;
    println!(&quot;{}&quot;, mymacro!(assert!(x)));
}"><pre class="notranslate"><span class="pl-c1">#!<span class="pl-kos">[</span>feature<span class="pl-kos">(</span>phase<span class="pl-kos">)</span><span class="pl-kos">]</span></span>

<span class="pl-c1">#<span class="pl-kos">[</span>phase<span class="pl-kos">(</span>plugin<span class="pl-kos">)</span><span class="pl-kos">]</span></span>
<span class="pl-k">extern</span> <span class="pl-k">crate</span> plugin<span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> x = <span class="pl-c1">true</span><span class="pl-kos">;</span>
    <span class="pl-en">println</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-s">"{}"</span>, mymacro!<span class="pl-kos">(</span>assert!<span class="pl-kos">(</span>x<span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">I get this result:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$ rustc -v
rustc 0.12.0-pre (3f5d0b5b6 2014-08-19 16:35:51 +0000)

$ rustc plugin.rs

$ rustc -L. test.rs
&lt;quote expansion&gt;:1:20: 1:21 error: unresolved name `x`.
&lt;quote expansion&gt;:1 name_64,ctxt_11!(x)
                                       ^
&lt;std macros&gt;:1:1: 12:2 note: in expansion of assert!
&lt;quote expansion&gt;:1:1: 1:22 note: expansion site
test.rs:1:1: 9:1 note: in expansion of mymacro!
test.rs:8:20: 8:40 note: expansion site
note: in expansion of format_args!
&lt;std macros&gt;:2:23: 2:77 note: expansion site
&lt;std macros&gt;:1:1: 3:2 note: in expansion of println!
test.rs:8:5: 8:42 note: expansion site
error: aborting due to previous error"><pre class="notranslate"><code class="notranslate">$ rustc -v
rustc 0.12.0-pre (3f5d0b5b6 2014-08-19 16:35:51 +0000)

$ rustc plugin.rs

$ rustc -L. test.rs
&lt;quote expansion&gt;:1:20: 1:21 error: unresolved name `x`.
&lt;quote expansion&gt;:1 name_64,ctxt_11!(x)
                                       ^
&lt;std macros&gt;:1:1: 12:2 note: in expansion of assert!
&lt;quote expansion&gt;:1:1: 1:22 note: expansion site
test.rs:1:1: 9:1 note: in expansion of mymacro!
test.rs:8:20: 8:40 note: expansion site
note: in expansion of format_args!
&lt;std macros&gt;:2:23: 2:77 note: expansion site
&lt;std macros&gt;:1:1: 3:2 note: in expansion of println!
test.rs:8:5: 8:42 note: expansion site
error: aborting due to previous error
</code></pre></div>
<p dir="auto">Also the NULL characters used to delimit the magic identifier string appear in the error output, which causes the error caret to appear in the wrong place.</p>
<p dir="auto">See also <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="38682589" data-permission-text="Title is private" data-url="https://github.com/rust-lang/rust/issues/15962" data-hovercard-type="issue" data-hovercard-url="/rust-lang/rust/issues/15962/hovercard" href="https://github.com/rust-lang/rust/issues/15962">#15962</a>.</p>
<p dir="auto">CC <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/pnkfelix/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/pnkfelix">@pnkfelix</a>. This is still a huge improvement from before and I think I can work around the remaining issues in <code class="notranslate">html5ever</code>. Thank you for fixing <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="38120612" data-permission-text="Title is private" data-url="https://github.com/rust-lang/rust/issues/15750" data-hovercard-type="issue" data-hovercard-url="/rust-lang/rust/issues/15750/hovercard" href="https://github.com/rust-lang/rust/issues/15750">#15750</a> :)</p>