diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 0523765ea1897..3727615386f47 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -390,6 +390,22 @@ impl<'a> Resolver<'a> { Err(Determinacy::Determined) => {} } + // Ok at this point we've determined that the `attr` above doesn't + // actually resolve at this time, so we may want to report an error. + // It could be the case, though, that `attr` won't ever resolve! If + // there's a custom derive that could be used it might declare `attr` as + // a custom attribute accepted by the derive. In this case we don't want + // to report this particular invocation as unresolved, but rather we'd + // want to move on to the next invocation. + // + // This loop here looks through all of the derive annotations in scope + // and tries to resolve them. If they themselves successfully resolve + // *and* the resolve mentions that this attribute's name is a registered + // custom attribute then we flag this attribute as known and update + // `invoc` above to point to the next invocation. + // + // By then returning `Undetermined` we should continue resolution to + // resolve the next attribute. let attr_name = match path.segments.len() { 1 => path.segments[0].ident.name, _ => return Err(determinacy), @@ -411,8 +427,8 @@ impl<'a> Resolver<'a> { attrs.push(inert_attr); attrs }); + return Err(Determinacy::Undetermined) } - return Err(Determinacy::Undetermined); }, Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined, Err(Determinacy::Determined) => {} diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/custom-attr-only-one-derive.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/custom-attr-only-one-derive.rs new file mode 100644 index 0000000000000..4609f57bddfa4 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/custom-attr-only-one-derive.rs @@ -0,0 +1,27 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Foo)] +pub fn foo(a: TokenStream) -> TokenStream { + "".parse().unwrap() +} + +#[proc_macro_derive(Bar, attributes(custom))] +pub fn bar(a: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/run-pass-fulldeps/proc-macro/custom-attr-only-one-derive.rs b/src/test/run-pass-fulldeps/proc-macro/custom-attr-only-one-derive.rs new file mode 100644 index 0000000000000..3b2833a4bcf75 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/custom-attr-only-one-derive.rs @@ -0,0 +1,25 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:custom-attr-only-one-derive.rs + +#![feature(rust_2018_preview)] + +#[macro_use] +extern crate custom_attr_only_one_derive; + +#[derive(Bar, Foo)] +#[custom = "test"] +pub enum A { + B, + C, +} + +fn main() {}