diff options
| author | bors <bors@rust-lang.org> | 2019-08-05 04:36:51 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-08-05 04:36:51 +0000 |
| commit | e1d7e4ae82c5500407e606c0b2b595597b9981f3 (patch) | |
| tree | af36da7b4099f30dffe74257607bbce6f84d85e7 /src/libsyntax/ext | |
| parent | 11a51488f03405ea539a9fe84973ee972eaa7b96 (diff) | |
| parent | 2a9b75281bfb03fc795568ac8fb6eeff7cac8034 (diff) | |
| download | rust-e1d7e4ae82c5500407e606c0b2b595597b9981f3.tar.gz rust-e1d7e4ae82c5500407e606c0b2b595597b9981f3.zip | |
Auto merge of #63248 - petrochenkov:nomarker, r=matthewjasper
Move special treatment of `derive(Copy, PartialEq, Eq)` from expansion infrastructure to elsewhere As described in https://github.com/rust-lang/rust/pull/62086#issuecomment-515195477. Reminder: - `derive(PartialEq, Eq)` makes the type it applied to a "structural match" type, so constants of this type can be used in patterns (and const generics in the future). - `derive(Copy)` notifies other derives that the type it applied to implements `Copy`, so `derive(Clone)` can generate optimized code and other derives can generate code working with `packed` types and types with `rustc_layout_scalar_valid_range` attributes. First, the special behavior is now enabled after properly resolving the derives, rather than after textually comparing them with `"Copy"`, `"PartialEq"` and `"Eq"` in `fn add_derived_markers`. The markers are no longer kept as attributes in AST since derives cannot modify items and previously did it through hacks in the expansion infra. Instead, the markers are now kept in a "global context" available from all the necessary places, namely - resolver. For `derive(PartialEq, Eq)` the markers are created by the derive macros themselves and then consumed during HIR lowering to add the `#[structural_match]` attribute in HIR. This is still a hack, but now it's a hack local to two specific macros rather than affecting the whole expansion infra. Ideally we should find the way to put `#[structural_match]` on the impls rather than on the original item, and then consume it in `rustc_mir`, then no hacks in expansion and lowering will be required. (I'll make an issue about this for someone else to solve, after this PR lands.) The marker for `derive(Copy)` cannot be emitted by the `Copy` macro itself because we need to know it *before* the `Copy` macro is expanded for expanding other macros. So we have to do it in resolve and block expansion of any derives in a `derive(...)` container until we know for sure whether this container has `Copy` in it or not. Nasty stuff. r? @eddyb or @matthewjasper
Diffstat (limited to 'src/libsyntax/ext')
| -rw-r--r-- | src/libsyntax/ext/base.rs | 18 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 19 | ||||
| -rw-r--r-- | src/libsyntax/ext/proc_macro.rs | 35 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/macro_rules.rs | 5 |
4 files changed, 26 insertions, 51 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 239fe55672e..d69822c7c7f 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -595,6 +595,8 @@ pub struct SyntaxExtension { /// Built-in macros have a couple of special properties (meaning of `$crate`, /// availability in `#[no_implicit_prelude]` modules), so we have to keep this flag. pub is_builtin: bool, + /// We have to identify macros providing a `Copy` impl early for compatibility reasons. + pub is_derive_copy: bool, } impl SyntaxExtensionKind { @@ -640,6 +642,7 @@ impl SyntaxExtension { helper_attrs: Vec::new(), edition, is_builtin: false, + is_derive_copy: false, kind, } } @@ -683,6 +686,16 @@ pub type NamedSyntaxExtension = (Name, SyntaxExtension); /// Error type that denotes indeterminacy. pub struct Indeterminate; +bitflags::bitflags! { + /// Built-in derives that need some extra tracking beyond the usual macro functionality. + #[derive(Default)] + pub struct SpecialDerives: u8 { + const PARTIAL_EQ = 1 << 0; + const EQ = 1 << 1; + const COPY = 1 << 2; + } +} + pub trait Resolver { fn next_node_id(&mut self) -> ast::NodeId; @@ -699,6 +712,9 @@ pub trait Resolver { -> Result<Option<Lrc<SyntaxExtension>>, Indeterminate>; fn check_unused_macros(&self); + + fn has_derives(&self, expn_id: ExpnId, derives: SpecialDerives) -> bool; + fn add_derives(&mut self, expn_id: ExpnId, derives: SpecialDerives); } #[derive(Clone)] @@ -726,7 +742,6 @@ pub struct ExtCtxt<'a> { pub resolver: &'a mut dyn Resolver, pub current_expansion: ExpansionData, pub expansions: FxHashMap<Span, Vec<String>>, - pub allow_derive_markers: Lrc<[Symbol]>, } impl<'a> ExtCtxt<'a> { @@ -747,7 +762,6 @@ impl<'a> ExtCtxt<'a> { prior_type_ascription: None, }, expansions: FxHashMap::default(), - allow_derive_markers: [sym::rustc_attrs, sym::structural_match][..].into(), } } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 35017824233..d2807e4a4b5 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -4,7 +4,7 @@ use crate::attr::{self, HasAttrs}; use crate::source_map::{dummy_spanned, respan}; use crate::config::StripUnconfigured; use crate::ext::base::*; -use crate::ext::proc_macro::{add_derived_markers, collect_derives}; +use crate::ext::proc_macro::collect_derives; use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnInfo, ExpnKind}; use crate::ext::placeholders::{placeholder, PlaceholderExpander}; use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err}; @@ -209,7 +209,6 @@ pub enum InvocationKind { Derive { path: Path, item: Annotatable, - item_with_markers: Annotatable, }, /// "Invocation" that contains all derives from an item, /// broken into multiple `Derive` invocations when expanded. @@ -360,8 +359,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mut item = self.fully_configure(item); item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive)); - let mut item_with_markers = item.clone(); - add_derived_markers(&mut self.cx, item.span(), &traits, &mut item_with_markers); let derives = derives.entry(invoc.expansion_data.id).or_default(); derives.reserve(traits.len()); @@ -370,11 +367,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let expn_id = ExpnId::fresh(self.cx.current_expansion.id, None); derives.push(expn_id); invocations.push(Invocation { - kind: InvocationKind::Derive { - path, - item: item.clone(), - item_with_markers: item_with_markers.clone(), - }, + kind: InvocationKind::Derive { path, item: item.clone() }, fragment_kind: invoc.fragment_kind, expansion_data: ExpansionData { id: expn_id, @@ -383,7 +376,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }); } let fragment = invoc.fragment_kind - .expect_from_annotatables(::std::iter::once(item_with_markers)); + .expect_from_annotatables(::std::iter::once(item)); self.collect_invocations(fragment, derives) } else { unreachable!() @@ -574,13 +567,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } _ => unreachable!() } - InvocationKind::Derive { path, item, item_with_markers } => match ext { + InvocationKind::Derive { path, item } => match ext { SyntaxExtensionKind::Derive(expander) | SyntaxExtensionKind::LegacyDerive(expander) => { - let (path, item) = match ext { - SyntaxExtensionKind::LegacyDerive(..) => (path, item_with_markers), - _ => (path, item), - }; if !item.derive_allowed() { return fragment_kind.dummy(span); } diff --git a/src/libsyntax/ext/proc_macro.rs b/src/libsyntax/ext/proc_macro.rs index ec708994fad..c17b6f6b424 100644 --- a/src/libsyntax/ext/proc_macro.rs +++ b/src/libsyntax/ext/proc_macro.rs @@ -1,17 +1,15 @@ use crate::ast::{self, ItemKind, Attribute, Mac}; -use crate::attr::{mark_used, mark_known, HasAttrs}; +use crate::attr::{mark_used, mark_known}; use crate::errors::{Applicability, FatalError}; use crate::ext::base::{self, *}; use crate::ext::proc_macro_server; use crate::parse::{self, token}; use crate::parse::parser::PathStyle; -use crate::symbol::{sym, Symbol}; +use crate::symbol::sym; use crate::tokenstream::{self, TokenStream}; use crate::visit::Visitor; -use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; -use syntax_pos::hygiene::{ExpnInfo, ExpnKind}; use syntax_pos::{Span, DUMMY_SP}; const EXEC_STRATEGY: proc_macro::bridge::server::SameThread = @@ -217,32 +215,3 @@ crate fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>) }); result } - -crate fn add_derived_markers<T: HasAttrs>( - cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::Path], item: &mut T -) { - let (mut names, mut pretty_name) = (FxHashSet::default(), String::new()); - for (i, path) in traits.iter().enumerate() { - if i > 0 { - pretty_name.push_str(", "); - } - pretty_name.push_str(&path.to_string()); - names.insert(unwrap_or!(path.segments.get(0), continue).ident.name); - } - - let span = span.fresh_expansion(cx.current_expansion.id, ExpnInfo::allow_unstable( - ExpnKind::Macro(MacroKind::Derive, Symbol::intern(&pretty_name)), span, - cx.parse_sess.edition, cx.allow_derive_markers.clone(), - )); - - item.visit_attrs(|attrs| { - if names.contains(&sym::Eq) && names.contains(&sym::PartialEq) { - let meta = cx.meta_word(span, sym::structural_match); - attrs.push(cx.attribute(meta)); - } - if names.contains(&sym::Copy) { - let meta = cx.meta_word(span, sym::rustc_copy_clone_marker); - attrs.push(cx.attribute(meta)); - } - }); -} diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index f825d1e9aae..7401f256412 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -430,6 +430,8 @@ pub fn compile( } } + let is_builtin = attr::contains_name(&def.attrs, sym::rustc_builtin_macro); + SyntaxExtension { kind: SyntaxExtensionKind::LegacyBang(expander), span: def.span, @@ -441,7 +443,8 @@ pub fn compile( deprecation: attr::find_deprecation(&sess, &def.attrs, def.span), helper_attrs: Vec::new(), edition, - is_builtin: attr::contains_name(&def.attrs, sym::rustc_builtin_macro), + is_builtin, + is_derive_copy: is_builtin && def.ident.name == sym::Copy, } } |
