about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2020-10-06 16:26:16 +0900
committerGitHub <noreply@github.com>2020-10-06 16:26:16 +0900
commit552933b79d3927dc8df63389417982513156a5eb (patch)
treef770a439c36866d01c22f34d8e615e096fe3354d
parentcc908f3b7005eb9762f81148e3668603edd92003 (diff)
parent8d11f90a16fb374d68b4aae5486c3e12c74c63b7 (diff)
downloadrust-552933b79d3927dc8df63389417982513156a5eb.tar.gz
rust-552933b79d3927dc8df63389417982513156a5eb.zip
Rollup merge of #77591 - Aaron1011:fix/hygiene-def-scope, r=estebank
Record `expansion_that_defined` into crate metadata

Fixes #77523

Now that hygiene serialization is implemented, we also need to record
`expansion_that_defined` so that we properly handle a foreign
`SyntaxContext`.
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs1
-rw-r--r--compiler/rustc_middle/src/query/mod.rs5
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs6
-rw-r--r--src/test/ui/hygiene/auxiliary/def-site-async-await.rs7
-rw-r--r--src/test/ui/hygiene/auxiliary/opaque-hygiene.rs21
-rw-r--r--src/test/ui/hygiene/issue-77523-def-site-async-await.rs19
9 files changed, 66 insertions, 2 deletions
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index c31e941b3ff..8b11d2c913a 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<Symbol>)] {
         // 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 4102cf84a67..578ce382912 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 f58a792ef58..4350ac5c27a 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 1a127035d4f..9e26d02e4e1 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<DefIndex, Lazy<[ty::Variance]>>,
     generics: Table<DefIndex, Lazy<ty::Generics>>,
     explicit_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
+    expn_that_defined: Table<DefIndex, Lazy<ExpnId>>,
     // 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 d5b99ea4d28..fe115bbb9c3 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 5f5efd5fa77..f069faed9e2 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 00000000000..f7e9b801318
--- /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 00000000000..7730f91bd6a
--- /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<T> 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 00000000000..2af60ff6f53
--- /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());
+}