diff options
| author | bors <bors@rust-lang.org> | 2022-10-29 20:44:01 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-10-29 20:44:01 +0000 |
| commit | 90b3882115c9c499b67824b89b641b51f5c0c40d (patch) | |
| tree | 53c1d1843223a4e9a4f95901b7e06ac9bd9430fc /compiler | |
| parent | 636a78aca875fcba6468eabe750a79f08ee9a635 (diff) | |
| parent | 108b32ea5909e793d053a2590eb5916eac05352d (diff) | |
| download | rust-90b3882115c9c499b67824b89b641b51f5c0c40d.tar.gz rust-90b3882115c9c499b67824b89b641b51f5c0c40d.zip | |
Auto merge of #103739 - Mark-Simulacrum:beta-next, r=Mark-Simulacrum
[beta] backport rollup * poll_fn and Unpin: fix pinning #102737 * Support raw-dylib functions being used inside inlined functions #102988 * Fix line numbers for MIR inlined code #103071 * Add architectures to fn create_object_file #103240 * Add eval hack in super_relate_consts back #103279 * Mark std::os::wasi::io::AsFd etc. as stable. #103308 * Truncate thread names on Linux and Apple targets #103379 * Do not consider repeated lifetime params for elision. #103450 * rustdoc: add missing URL redirect #103588 * Remove commit_if_ok probe from NLL type relation #103601 Also includes a copy of the release notes. r? `@ghost`
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_codegen_cranelift/src/archive.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_codegen_gcc/src/archive.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/back/archive.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/archive.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/link.rs | 41 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/metadata.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/operand.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/nll_relate/mod.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/relate.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/pattern/mod.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 103 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/lib.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_span/src/lib.rs | 8 |
14 files changed, 157 insertions, 49 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs index b4c79096170..fb5313f17f3 100644 --- a/compiler/rustc_codegen_cranelift/src/archive.rs +++ b/compiler/rustc_codegen_cranelift/src/archive.rs @@ -38,6 +38,7 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { _lib_name: &str, _dll_imports: &[rustc_session::cstore::DllImport], _tmpdir: &Path, + _is_direct_dependency: bool, ) -> PathBuf { bug!("creating dll imports is not supported"); } diff --git a/compiler/rustc_codegen_gcc/src/archive.rs b/compiler/rustc_codegen_gcc/src/archive.rs index f863abdcc97..96c77310160 100644 --- a/compiler/rustc_codegen_gcc/src/archive.rs +++ b/compiler/rustc_codegen_gcc/src/archive.rs @@ -45,6 +45,7 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { _lib_name: &str, _dll_imports: &[DllImport], _tmpdir: &Path, + _is_direct_dependency: bool, ) -> PathBuf { unimplemented!(); } diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 38a366095b4..ed96355a052 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -104,10 +104,12 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { lib_name: &str, dll_imports: &[DllImport], tmpdir: &Path, + is_direct_dependency: bool, ) -> PathBuf { + let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" }; let output_path = { let mut output_path: PathBuf = tmpdir.to_path_buf(); - output_path.push(format!("{}_imports", lib_name)); + output_path.push(format!("{}{}", lib_name, name_suffix)); output_path.with_extension("lib") }; @@ -134,7 +136,8 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { // that loaded but crashed with an AV upon calling one of the imported // functions. Therefore, use binutils to create the import library instead, // by writing a .DEF file to the temp dir and calling binutils's dlltool. - let def_file_path = tmpdir.join(format!("{}_imports", lib_name)).with_extension("def"); + let def_file_path = + tmpdir.join(format!("{}{}", lib_name, name_suffix)).with_extension("def"); let def_file_content = format!( "EXPORTS\n{}", diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index bad58d0a8a0..bb76ca5d2b9 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -25,6 +25,7 @@ pub trait ArchiveBuilderBuilder { lib_name: &str, dll_imports: &[DllImport], tmpdir: &Path, + is_direct_dependency: bool, ) -> PathBuf; fn extract_bundled_libs( diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index ea0f0de76c5..6cce9542746 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -376,13 +376,14 @@ fn link_rlib<'a>( } for (raw_dylib_name, raw_dylib_imports) in - collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)? + collate_raw_dylibs(sess, codegen_results.crate_info.used_libraries.iter())? { let output_path = archive_builder_builder.create_dll_import_lib( sess, &raw_dylib_name, &raw_dylib_imports, tmpdir.as_ref(), + true, ); ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|e| { @@ -434,9 +435,9 @@ fn link_rlib<'a>( /// then the CodegenResults value contains one NativeLib instance for each block. However, the /// linker appears to expect only a single import library for each library used, so we need to /// collate the symbols together by library name before generating the import libraries. -fn collate_raw_dylibs( - sess: &Session, - used_libraries: &[NativeLib], +fn collate_raw_dylibs<'a, 'b>( + sess: &'a Session, + used_libraries: impl IntoIterator<Item = &'b NativeLib>, ) -> Result<Vec<(String, Vec<DllImport>)>, ErrorGuaranteed> { // Use index maps to preserve original order of imports and libraries. let mut dylib_table = FxIndexMap::<String, FxIndexMap<Symbol, &DllImport>>::default(); @@ -2028,13 +2029,43 @@ fn linker_with_args<'a>( // Link with the import library generated for any raw-dylib functions. for (raw_dylib_name, raw_dylib_imports) in - collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)? + collate_raw_dylibs(sess, codegen_results.crate_info.used_libraries.iter())? + { + cmd.add_object(&archive_builder_builder.create_dll_import_lib( + sess, + &raw_dylib_name, + &raw_dylib_imports, + tmpdir, + true, + )); + } + // As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case + // they are used within inlined functions or instantiated generic functions. We do this *after* + // handling the raw-dylib symbols in the current crate to make sure that those are chosen first + // by the linker. + let (_, dependency_linkage) = codegen_results + .crate_info + .dependency_formats + .iter() + .find(|(ty, _)| *ty == crate_type) + .expect("failed to find crate type in dependency format list"); + let native_libraries_from_nonstatics = codegen_results + .crate_info + .native_libraries + .iter() + .filter_map(|(cnum, libraries)| { + (dependency_linkage[cnum.as_usize() - 1] != Linkage::Static).then(|| libraries) + }) + .flatten(); + for (raw_dylib_name, raw_dylib_imports) in + collate_raw_dylibs(sess, native_libraries_from_nonstatics)? { cmd.add_object(&archive_builder_builder.create_dll_import_lib( sess, &raw_dylib_name, &raw_dylib_imports, tmpdir, + false, )); } diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index b92e146bee2..99ddd176478 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -117,6 +117,10 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static "riscv32" => Architecture::Riscv32, "riscv64" => Architecture::Riscv64, "sparc64" => Architecture::Sparc64, + "avr" => Architecture::Avr, + "msp430" => Architecture::Msp430, + "hexagon" => Architecture::Hexagon, + "bpf" => Architecture::Bpf, // Unsupported architecture. _ => return None, }; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 29c745a0886..0e3959b61a1 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -591,9 +591,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { val: &mir::ConstantKind<'tcx>, layout: Option<TyAndLayout<'tcx>>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { + // FIXME(const_prop): normalization needed b/c const prop lint in + // `mir_drops_elaborated_and_const_checked`, which happens before + // optimized MIR. Only after optimizing the MIR can we guarantee + // that the `RevealAll` pass has happened and that the body's consts + // are normalized, so any call to resolve before that needs to be + // manually normalized. + let val = self.tcx.normalize_erasing_regions(self.param_env, *val); match val { - mir::ConstantKind::Ty(ct) => self.const_to_op(*ct, layout), - mir::ConstantKind::Val(val, ty) => self.const_val_to_op(*val, *ty, layout), + mir::ConstantKind::Ty(ct) => self.const_to_op(ct, layout), + mir::ConstantKind::Val(val, ty) => self.const_val_to_op(val, ty, layout), mir::ConstantKind::Unevaluated(uv, _) => { let instance = self.resolve(uv.def, uv.substs)?; Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into()) diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index bb6f6ae60e2..00fc442d3b0 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -596,7 +596,7 @@ where (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)), (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => { - infcx.commit_if_ok(|_| infcx.super_combine_tys(self, a, b)).or_else(|err| { + infcx.super_combine_tys(self, a, b).or_else(|err| { self.tcx().sess.delay_span_bug( self.delegate.span(), "failure to relate an opaque to itself should result in an error later on", diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index e8fe37e7dab..3f987119099 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2489,7 +2489,9 @@ impl<'tcx> TyCtxt<'tcx> { && if self.features().collapse_debuginfo { span.in_macro_expansion_with_collapse_debuginfo() } else { - span.from_expansion() + // Inlined spans should not be collapsed as that leads to all of the + // inlined code being attributed to the inline callsite. + span.from_expansion() && !span.is_inlined() } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index af31f54981f..61c34730d59 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -574,8 +574,8 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( /// it. pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, - a: ty::Const<'tcx>, - b: ty::Const<'tcx>, + mut a: ty::Const<'tcx>, + mut b: ty::Const<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b); let tcx = relation.tcx(); @@ -596,6 +596,17 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( ); } + // HACK(const_generics): We still need to eagerly evaluate consts when + // relating them because during `normalize_param_env_or_error`, + // we may relate an evaluated constant in a obligation against + // an unnormalized (i.e. unevaluated) const in the param-env. + // FIXME(generic_const_exprs): Once we always lazily unify unevaluated constants + // these `eval` calls can be removed. + if !relation.tcx().features().generic_const_exprs { + a = a.eval(tcx, relation.param_env()); + b = b.eval(tcx, relation.param_env()); + } + // Currently, the values that can be unified are primitive types, // and those that derive both `PartialEq` and `Eq`, corresponding // to structural-match types. diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index e712741b7c9..0edf6a98327 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -481,7 +481,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // Use `Reveal::All` here because patterns are always monomorphic even if their function // isn't. let param_env_reveal_all = self.param_env.with_reveal_all_normalized(self.tcx); - let substs = self.typeck_results.node_substs(id); + // N.B. There is no guarantee that substs collected in typeck results are fully normalized, + // so they need to be normalized in order to pass to `Instance::resolve`, which will ICE + // if given unnormalized types. + let substs = self + .tcx + .normalize_erasing_regions(param_env_reveal_all, self.typeck_results.node_substs(id)); let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) { Ok(Some(i)) => i, Ok(None) => { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index d2a0d826b52..d8d82e125d5 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -30,6 +30,7 @@ use rustc_span::{BytePos, Span}; use smallvec::{smallvec, SmallVec}; use rustc_span::source_map::{respan, Spanned}; +use std::assert_matches::debug_assert_matches; use std::collections::{hash_map::Entry, BTreeSet}; use std::mem::{replace, take}; @@ -557,7 +558,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast> { /// They will be used to determine the correct lifetime for the fn return type. /// The `LifetimeElisionCandidate` is used for diagnostics, to suggest introducing named /// lifetimes. - lifetime_elision_candidates: Option<FxIndexMap<LifetimeRes, LifetimeElisionCandidate>>, + lifetime_elision_candidates: Option<Vec<(LifetimeRes, LifetimeElisionCandidate)>>, /// The trait that the current context can refer to. current_trait_ref: Option<(Module<'a>, TraitRef)>, @@ -1819,7 +1820,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { match res { LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static => { if let Some(ref mut candidates) = self.lifetime_elision_candidates { - candidates.insert(res, candidate); + candidates.push((res, candidate)); } } LifetimeRes::Infer | LifetimeRes::Error | LifetimeRes::ElidedAnchor { .. } => {} @@ -1872,12 +1873,25 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { has_self: bool, inputs: impl Iterator<Item = (Option<&'ast Pat>, &'ast Ty)>, ) -> Result<LifetimeRes, (Vec<MissingLifetime>, Vec<ElisionFnParameter>)> { - let outer_candidates = - replace(&mut self.lifetime_elision_candidates, Some(Default::default())); + enum Elision { + /// We have not found any candidate. + None, + /// We have a candidate bound to `self`. + Self_(LifetimeRes), + /// We have a candidate bound to a parameter. + Param(LifetimeRes), + /// We failed elision. + Err, + } - let mut elision_lifetime = None; - let mut lifetime_count = 0; + // Save elision state to reinstate it later. + let outer_candidates = self.lifetime_elision_candidates.take(); + + // Result of elision. + let mut elision_lifetime = Elision::None; + // Information for diagnostics. let mut parameter_info = Vec::new(); + let mut all_candidates = Vec::new(); let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; for (index, (pat, ty)) in inputs.enumerate() { @@ -1885,12 +1899,17 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { if let Some(pat) = pat { self.resolve_pattern(pat, PatternSource::FnParam, &mut bindings); } + + // Record elision candidates only for this parameter. + debug_assert_matches!(self.lifetime_elision_candidates, None); + self.lifetime_elision_candidates = Some(Default::default()); self.visit_ty(ty); + let local_candidates = self.lifetime_elision_candidates.take(); - if let Some(ref candidates) = self.lifetime_elision_candidates { - let new_count = candidates.len(); - let local_count = new_count - lifetime_count; - if local_count != 0 { + if let Some(candidates) = local_candidates { + let distinct: FxHashSet<_> = candidates.iter().map(|(res, _)| *res).collect(); + let lifetime_count = distinct.len(); + if lifetime_count != 0 { parameter_info.push(ElisionFnParameter { index, ident: if let Some(pat) = pat && let PatKind::Ident(_, ident, _) = pat.kind { @@ -1898,48 +1917,64 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } else { None }, - lifetime_count: local_count, + lifetime_count, span: ty.span, }); + all_candidates.extend(candidates.into_iter().filter_map(|(_, candidate)| { + match candidate { + LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => { + None + } + LifetimeElisionCandidate::Missing(missing) => Some(missing), + } + })); + } + let mut distinct_iter = distinct.into_iter(); + if let Some(res) = distinct_iter.next() { + match elision_lifetime { + // We are the first parameter to bind lifetimes. + Elision::None => { + if distinct_iter.next().is_none() { + // We have a single lifetime => success. + elision_lifetime = Elision::Param(res) + } else { + // We have have multiple lifetimes => error. + elision_lifetime = Elision::Err; + } + } + // We have 2 parameters that bind lifetimes => error. + Elision::Param(_) => elision_lifetime = Elision::Err, + // `self` elision takes precedence over everything else. + Elision::Self_(_) | Elision::Err => {} + } } - lifetime_count = new_count; } // Handle `self` specially. if index == 0 && has_self { let self_lifetime = self.find_lifetime_for_self(ty); if let Set1::One(lifetime) = self_lifetime { - elision_lifetime = Some(lifetime); - self.lifetime_elision_candidates = None; + // We found `self` elision. + elision_lifetime = Elision::Self_(lifetime); } else { - self.lifetime_elision_candidates = Some(Default::default()); - lifetime_count = 0; + // We do not have `self` elision: disregard the `Elision::Param` that we may + // have found. + elision_lifetime = Elision::None; } } debug!("(resolving function / closure) recorded parameter"); } - let all_candidates = replace(&mut self.lifetime_elision_candidates, outer_candidates); - debug!(?all_candidates); + // Reinstate elision state. + debug_assert_matches!(self.lifetime_elision_candidates, None); + self.lifetime_elision_candidates = outer_candidates; - if let Some(res) = elision_lifetime { + if let Elision::Param(res) | Elision::Self_(res) = elision_lifetime { return Ok(res); } - // We do not have a `self` candidate, look at the full list. - let all_candidates = all_candidates.unwrap(); - if all_candidates.len() == 1 { - Ok(*all_candidates.first().unwrap().0) - } else { - let all_candidates = all_candidates - .into_iter() - .filter_map(|(_, candidate)| match candidate { - LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => None, - LifetimeElisionCandidate::Missing(missing) => Some(missing), - }) - .collect(); - Err((all_candidates, parameter_info)) - } + // We do not have a candidate. + Err((all_candidates, parameter_info)) } /// List all the lifetimes that appear in the provided type. @@ -2411,7 +2446,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // Do not account for the parameters we just bound for function lifetime elision. if let Some(ref mut candidates) = self.lifetime_elision_candidates { for (_, res) in function_lifetime_rib.bindings.values() { - candidates.remove(res); + candidates.retain(|(r, _)| r != res); } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 54a7f416ce6..26b9284fe91 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -7,6 +7,7 @@ //! Type-relative name resolution (methods, fields, associated items) happens in `rustc_typeck`. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(drain_filter)] #![feature(if_let_guard)] diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index ada3bae6150..da31b346293 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -558,7 +558,7 @@ impl Span { self.data_untracked().is_dummy() } - /// Returns `true` if this span comes from a macro or desugaring. + /// Returns `true` if this span comes from any kind of macro, desugaring or inlining. #[inline] pub fn from_expansion(self) -> bool { self.ctxt() != SyntaxContext::root() @@ -571,6 +571,12 @@ impl Span { matches!(outer_expn.kind, ExpnKind::Macro(..)) && outer_expn.collapse_debuginfo } + /// Returns `true` if this span comes from MIR inlining. + pub fn is_inlined(self) -> bool { + let outer_expn = self.ctxt().outer_expn_data(); + matches!(outer_expn.kind, ExpnKind::Inlined) + } + /// Returns `true` if `span` originates in a derive-macro's expansion. pub fn in_derive_expansion(self) -> bool { matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _)) |
