Skip to content

Commit f2f7ab9

Browse files
committed
rustc: Fix two custom attributes with custom derive
This commit fixes an issue where multiple custom attributes could not be fed into a custom derive in some situations with the `use_extern_macros` feature enabled. The problem was that the macro expander didn't consider that it was making progress when we were deducing that attributes should be lumped in with custom derive invocations. The fix applied here was to track in the expander if our attribute is changing (getting stashed away elsewhere and replaced with a new invocation). If it is swapped then it's considered progress, otherwise behavior should remain the same. Closes #52525
1 parent 5ba2184 commit f2f7ab9

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

src/libsyntax/ext/expand.rs

+17
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,13 @@ impl Invocation {
240240
InvocationKind::Derive { ref path, .. } => path.span,
241241
}
242242
}
243+
244+
pub fn attr_id(&self) -> Option<ast::AttrId> {
245+
match self.kind {
246+
InvocationKind::Attr { attr: Some(ref attr), .. } => Some(attr.id),
247+
_ => None,
248+
}
249+
}
243250
}
244251

245252
pub struct MacroExpander<'a, 'b:'a> {
@@ -331,10 +338,20 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
331338

332339
let scope =
333340
if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark };
341+
let attr_id_before = invoc.attr_id();
334342
let ext = match self.cx.resolver.resolve_invoc(&mut invoc, scope, force) {
335343
Ok(ext) => Some(ext),
336344
Err(Determinacy::Determined) => None,
337345
Err(Determinacy::Undetermined) => {
346+
// Sometimes attributes which we thought were invocations
347+
// end up being custom attributes for custom derives. If
348+
// that's the case our `invoc` will have changed out from
349+
// under us. If this is the case we're making progress so we
350+
// want to flag it as such, and we test this by looking if
351+
// the `attr_id()` method has been changing over time.
352+
if invoc.attr_id() != attr_id_before {
353+
progress = true;
354+
}
338355
undetermined_invocations.push(invoc);
339356
continue
340357
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// no-prefer-dynamic
12+
13+
#![crate_type = "proc-macro"]
14+
15+
extern crate proc_macro;
16+
17+
use proc_macro::*;
18+
19+
#[proc_macro_derive(A, attributes(b))]
20+
pub fn foo(_x: TokenStream) -> TokenStream {
21+
TokenStream::new()
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:derive-two-attrs.rs
12+
13+
#![feature(use_extern_macros)]
14+
15+
extern crate derive_two_attrs as foo;
16+
17+
use foo::A;
18+
19+
#[derive(A)]
20+
#[b]
21+
#[b]
22+
struct B;
23+
24+
fn main() {}

0 commit comments

Comments
 (0)