diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index c31e941b3ffc6..8b11d2c913ac2 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1011,6 +1011,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.tables.impl_trait_ref.get(self, id).map(|tr| tr.decode((self, tcx))) } + fn get_expn_that_defined(&self, id: DefIndex, sess: &Session) -> ExpnId { + self.root.tables.expn_that_defined.get(self, id).unwrap().decode((self, sess)) + } + /// Iterates over all the stability attributes in the given crate. fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option)] { // FIXME: For a proc macro crate, not sure whether we should return the "host" diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 4102cf84a6775..578ce382912f0 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -238,6 +238,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, } crate_extern_paths => { cdata.source().paths().cloned().collect() } + expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) } } pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index f58a792ef585e..4350ac5c27a88 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -747,6 +747,7 @@ impl EncodeContext<'a, 'tcx> { ty::Visibility::from_hir(enum_vis, enum_id, self.tcx)); record!(self.tables.span[def_id] <- self.tcx.def_span(def_id)); record!(self.tables.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]); + record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id)); record!(self.tables.children[def_id] <- variant.fields.iter().map(|f| { assert!(f.did.is_local()); f.did.index @@ -883,6 +884,7 @@ impl EncodeContext<'a, 'tcx> { record!(self.tables.visibility[def_id] <- field.vis); record!(self.tables.span[def_id] <- self.tcx.def_span(def_id)); record!(self.tables.attributes[def_id] <- variant_data.fields()[field_index].attrs); + record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id)); self.encode_ident_span(def_id, field.ident); self.encode_stability(def_id); self.encode_deprecation(def_id); @@ -924,6 +926,7 @@ impl EncodeContext<'a, 'tcx> { record!(self.tables.kind[def_id] <- EntryKind::Struct(self.lazy(data), adt_def.repr)); record!(self.tables.visibility[def_id] <- ctor_vis); record!(self.tables.span[def_id] <- self.tcx.def_span(def_id)); + record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id)); self.encode_stability(def_id); self.encode_deprecation(def_id); self.encode_item_type(def_id); @@ -1339,6 +1342,7 @@ impl EncodeContext<'a, 'tcx> { ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)); record!(self.tables.span[def_id] <- self.tcx.def_span(def_id)); record!(self.tables.attributes[def_id] <- item.attrs); + record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id)); // FIXME(eddyb) there should be a nicer way to do this. match item.kind { hir::ItemKind::ForeignMod(ref fm) => record!(self.tables.children[def_id] <- diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 1a127035d4ff7..9e26d02e4e16d 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -294,6 +294,7 @@ define_tables! { variances: Table>, generics: Table>, explicit_predicates: Table)>, + expn_that_defined: Table>, // FIXME(eddyb) this would ideally be `Lazy<[...]>` but `ty::Predicate` // doesn't handle shorthands in its own (de)serialization impls, // as it's an `enum` for which we want to derive (de)serialization, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d5b99ea4d288d..fe115bbb9c334 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -191,6 +191,11 @@ rustc_queries! { eval_always desc { |tcx| "parent module of `{}`", tcx.def_path_str(key.to_def_id()) } } + + /// Internal helper query. Use `tcx.expansion_that_defined` instead + query expn_that_defined(key: DefId) -> rustc_span::ExpnId { + desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) } + } } Codegen { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index b7530c077ccd1..7f77334acee75 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -3034,10 +3034,12 @@ impl<'tcx> TyCtxt<'tcx> { .hygienic_eq(def_name.span.ctxt(), self.expansion_that_defined(def_parent_def_id)) } - fn expansion_that_defined(self, scope: DefId) -> ExpnId { + pub fn expansion_that_defined(self, scope: DefId) -> ExpnId { match scope.as_local() { + // Parsing and expansion aren't incremental, so we don't + // need to go through a query for the same-crate case. Some(scope) => self.hir().definitions().expansion_that_defined(scope), - None => ExpnId::root(), + None => self.expn_that_defined(scope), } } diff --git a/src/test/ui/hygiene/auxiliary/def-site-async-await.rs b/src/test/ui/hygiene/auxiliary/def-site-async-await.rs new file mode 100644 index 0000000000000..f7e9b80131885 --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/def-site-async-await.rs @@ -0,0 +1,7 @@ +// edition:2018 + +extern crate opaque_hygiene; + +pub async fn serve() { + opaque_hygiene::make_it!(); +} diff --git a/src/test/ui/hygiene/auxiliary/opaque-hygiene.rs b/src/test/ui/hygiene/auxiliary/opaque-hygiene.rs new file mode 100644 index 0000000000000..7730f91bd6a03 --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/opaque-hygiene.rs @@ -0,0 +1,21 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::{TokenStream, quote}; + +#[proc_macro] +pub fn make_it(input: TokenStream) -> TokenStream { + // `quote!` applies def-site hygiene + quote! { + trait Foo { + fn my_fn(&self) {} + } + + impl Foo for T {} + "a".my_fn(); + } +} diff --git a/src/test/ui/hygiene/issue-77523-def-site-async-await.rs b/src/test/ui/hygiene/issue-77523-def-site-async-await.rs new file mode 100644 index 0000000000000..2af60ff6f53b6 --- /dev/null +++ b/src/test/ui/hygiene/issue-77523-def-site-async-await.rs @@ -0,0 +1,19 @@ +// build-pass +// aux-build:opaque-hygiene.rs +// aux-build:def-site-async-await.rs + +// Regression test for issue #77523 +// Tests that we don't ICE when an unusual combination +// of def-site hygiene and cross-crate monomorphization occurs. + +extern crate def_site_async_await; + +use std::future::Future; + +fn mk_ctxt() -> std::task::Context<'static> { + panic!() +} + +fn main() { + Box::pin(def_site_async_await::serve()).as_mut().poll(&mut mk_ctxt()); +}