Skip to content

Commit 863ed13

Browse files
committed
Rollup merge of #52539 - alexcrichton:two-attrs, r=petrochenkov
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
2 parents 63da812 + f2f7ab9 commit 863ed13

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

src/libsyntax/ext/expand.rs

Lines changed: 17 additions & 0 deletions
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
}
Lines changed: 22 additions & 0 deletions
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+
}
Lines changed: 24 additions & 0 deletions
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)