From 2fd4c27c329d85a69a6b585d217e48b4d500477e Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 19 Sep 2019 03:02:08 +0000 Subject: [PATCH 1/5] add is_async_fn query --- src/librustc/query/mod.rs | 4 ++++ src/librustc_metadata/cstore_impl.rs | 1 + src/librustc_metadata/decoder.rs | 9 +++++++++ src/librustc_metadata/encoder.rs | 4 ++++ src/librustc_metadata/schema.rs | 1 + 5 files changed, 19 insertions(+) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index c7260945295a6..c4f62df12b766 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -244,6 +244,10 @@ rustc_queries! { desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) } } + query is_async_fn(key: DefId) -> hir::IsAsync { + desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } + } + /// Returns `true` if calls to the function may be promoted. /// /// This is either because the function is e.g., a tuple-struct or tuple-variant diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index a1e3bbcbf8ea9..6db3bfd8880ff 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -133,6 +133,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } is_const_fn_raw => { cdata.is_const_fn_raw(def_id.index) } + is_async_fn { cdata.fn_asyncness(def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } static_mutability => { cdata.static_mutability(def_id.index) } def_kind => { cdata.def_kind(def_id.index) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 75d7261704722..6cc5c409e1331 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1208,6 +1208,15 @@ impl<'a, 'tcx> CrateMetadata { constness == hir::Constness::Const } + pub fn is_async_fn(&self, id: DefIndex) -> bool { + let asyncness = match self.entry(id).kind { + EntryKind::Fn(data) => data.decode(self).asyncness, + EntryKind::Method(data) => data.decode(self).fn_data.asyncness, + _ => hir::IsAsync::NotAsync, + }; + asyncness == hir::IsAsync::Async + } + pub fn is_foreign_item(&self, id: DefIndex) -> bool { match self.entry(id).kind { EntryKind::ForeignImmStatic | diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index f430f01542efe..439763810ec0e 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -885,6 +885,7 @@ impl EncodeContext<'tcx> { } }; FnData { + asyncness: hir::IsAsync::NotAsync, constness: hir::Constness::NotConst, param_names, sig: self.lazy(&tcx.fn_sig(def_id)), @@ -982,6 +983,7 @@ impl EncodeContext<'tcx> { ty::AssocKind::Method => { let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node { FnData { + asyncness: sig.header.asyncness, constness: sig.header.constness, param_names: self.encode_fn_param_names_for_body(body), sig: self.lazy(&tcx.fn_sig(def_id)), @@ -1128,6 +1130,7 @@ impl EncodeContext<'tcx> { } hir::ItemKind::Fn(_, header, .., body) => { let data = FnData { + asyncness: header.asyncness, constness: header.constness, param_names: self.encode_fn_param_names_for_body(body), sig: self.lazy(tcx.fn_sig(def_id)), @@ -1675,6 +1678,7 @@ impl EncodeContext<'tcx> { let kind = match nitem.node { hir::ForeignItemKind::Fn(_, ref names, _) => { let data = FnData { + asyncness: hir::IsAsync::NotAsync, constness: hir::Constness::NotConst, param_names: self.encode_fn_param_names(names), sig: self.lazy(tcx.fn_sig(def_id)), diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 1a5f0e17ba7ce..92534ab056a8b 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -295,6 +295,7 @@ pub struct MacroDef { #[derive(RustcEncodable, RustcDecodable)] pub struct FnData<'tcx> { + pub asyncness: hir::IsAsync, pub constness: hir::Constness, pub param_names: Lazy<[ast::Name]>, pub sig: Lazy>, From 9ffb1ce28cb1656d6142f1f9f6f882eb187fac25 Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 19 Sep 2019 03:21:11 +0000 Subject: [PATCH 2/5] append asyncness info to functions --- src/librustc/query/mod.rs | 2 +- src/librustc/ty/mod.rs | 15 +++++++++++++++ src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_metadata/encoder.rs | 4 ++-- src/librustdoc/clean/inline.rs | 8 ++++++-- src/librustdoc/clean/mod.rs | 7 ++++++- 6 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index c4f62df12b766..5e1db92b55580 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -244,7 +244,7 @@ rustc_queries! { desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) } } - query is_async_fn(key: DefId) -> hir::IsAsync { + query is_async_fn(key: DefId) -> bool { desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 5ca819e12f232..97981f4782003 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3349,6 +3349,20 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { } } +fn is_async_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) { + let node = tcx.hir().get(hir_id); + if let Some(fn_like) = hir::map::blocks::FnLikeNode::from_node(node) { + fn_like.asyncness() == hir::IsAsync::Async + } else { + false + } + } else { + false + } +} + + pub fn provide(providers: &mut ty::query::Providers<'_>) { context::provide(providers); erase_regions::provide(providers); @@ -3356,6 +3370,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { util::provide(providers); constness::provide(providers); *providers = ty::query::Providers { + is_async_fn, associated_item, associated_item_def_ids, adt_sized_constraint, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 6db3bfd8880ff..c46e2a901f88d 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -133,7 +133,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } is_const_fn_raw => { cdata.is_const_fn_raw(def_id.index) } - is_async_fn { cdata.fn_asyncness(def_id.index) } + is_async_fn => { cdata.is_async_fn(def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } static_mutability => { cdata.static_mutability(def_id.index) } def_kind => { cdata.def_kind(def_id.index) } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 439763810ec0e..1e7c0829a26a9 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -875,7 +875,7 @@ impl EncodeContext<'tcx> { EntryKind::AssocConst(container, const_qualif, rendered_const) } ty::AssocKind::Method => { - let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node { + let fn_data = if let hir::TraitItemKind::Method(method_sig, m) = &ast_item.node { let param_names = match *m { hir::TraitMethod::Required(ref names) => { self.encode_fn_param_names(names) @@ -885,7 +885,7 @@ impl EncodeContext<'tcx> { } }; FnData { - asyncness: hir::IsAsync::NotAsync, + asyncness: method_sig.header.asyncness, constness: hir::Constness::NotConst, param_names, sig: self.lazy(&tcx.fn_sig(def_id)), diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index cb42ff1c8052f..0752934c8c1de 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -217,7 +217,11 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function { } else { hir::Constness::NotConst }; - + let asyncness = if cx.tcx.is_async_fn(did) { + hir::IsAsync::Async + } else { + hir::IsAsync::NotAsync + }; let predicates = cx.tcx.predicates_of(did); let (generics, decl) = clean::enter_impl_trait(cx, || { ((cx.tcx.generics_of(did), &predicates).clean(cx), (did, sig).clean(cx)) @@ -230,7 +234,7 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function { unsafety: sig.unsafety(), abi: sig.abi(), constness, - asyncness: hir::IsAsync::NotAsync, + asyncness, }, all_types, ret_types, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ae70fdc530be6..7bd54c64cf6f5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2403,6 +2403,11 @@ impl Clean for ty::AssocItem { } else { hir::Constness::NotConst }; + let asyncness = if cx.tcx.is_async_fn(self.def_id) { + hir::IsAsync::Async + } else { + hir::IsAsync::NotAsync + }; let defaultness = match self.container { ty::ImplContainer(_) => Some(self.defaultness), ty::TraitContainer(_) => None, @@ -2414,7 +2419,7 @@ impl Clean for ty::AssocItem { unsafety: sig.unsafety(), abi: sig.abi(), constness, - asyncness: hir::IsAsync::NotAsync, + asyncness, }, defaultness, all_types, From a813cc1bf190f9cdcd7dce2eba287c637ce4048f Mon Sep 17 00:00:00 2001 From: csmoe Date: Sat, 21 Sep 2019 03:17:57 +0000 Subject: [PATCH 3/5] rename is_async_fn to asyncness --- src/librustc/query/mod.rs | 2 +- src/librustc/ty/mod.rs | 11 ++++++----- src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_metadata/decoder.rs | 7 +++---- src/librustdoc/clean/inline.rs | 6 +----- src/librustdoc/clean/mod.rs | 6 +----- 6 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 5e1db92b55580..252e49d5d15f6 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -244,7 +244,7 @@ rustc_queries! { desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) } } - query is_async_fn(key: DefId) -> bool { + query asyncness(key: DefId) -> hir::IsAsync { desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 97981f4782003..dd36a4520929a 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3349,16 +3349,17 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { } } -fn is_async_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { +/// Check if a function is async. +fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) { let node = tcx.hir().get(hir_id); if let Some(fn_like) = hir::map::blocks::FnLikeNode::from_node(node) { - fn_like.asyncness() == hir::IsAsync::Async + fn_like.asyncness() } else { - false + hir::IsAsync::NotAsync } } else { - false + hir::IsAsync::NotAsync } } @@ -3370,7 +3371,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { util::provide(providers); constness::provide(providers); *providers = ty::query::Providers { - is_async_fn, + asyncness, associated_item, associated_item_def_ids, adt_sized_constraint, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index c46e2a901f88d..55cf3965aa85a 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -133,7 +133,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } is_const_fn_raw => { cdata.is_const_fn_raw(def_id.index) } - is_async_fn => { cdata.is_async_fn(def_id.index) } + asyncness => { cdata.asyncness(def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } static_mutability => { cdata.static_mutability(def_id.index) } def_kind => { cdata.def_kind(def_id.index) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 6cc5c409e1331..5153564fc8255 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1208,13 +1208,12 @@ impl<'a, 'tcx> CrateMetadata { constness == hir::Constness::Const } - pub fn is_async_fn(&self, id: DefIndex) -> bool { - let asyncness = match self.entry(id).kind { + pub fn asyncness(&self, id: DefIndex) -> hir::IsAsync { + match self.entry(id).kind { EntryKind::Fn(data) => data.decode(self).asyncness, EntryKind::Method(data) => data.decode(self).fn_data.asyncness, _ => hir::IsAsync::NotAsync, - }; - asyncness == hir::IsAsync::Async + } } pub fn is_foreign_item(&self, id: DefIndex) -> bool { diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 0752934c8c1de..d71acb4fa7b31 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -217,11 +217,7 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function { } else { hir::Constness::NotConst }; - let asyncness = if cx.tcx.is_async_fn(did) { - hir::IsAsync::Async - } else { - hir::IsAsync::NotAsync - }; + let asyncness = cx.tcx.asyncness(did); let predicates = cx.tcx.predicates_of(did); let (generics, decl) = clean::enter_impl_trait(cx, || { ((cx.tcx.generics_of(did), &predicates).clean(cx), (did, sig).clean(cx)) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7bd54c64cf6f5..95a5869e84510 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2403,11 +2403,7 @@ impl Clean for ty::AssocItem { } else { hir::Constness::NotConst }; - let asyncness = if cx.tcx.is_async_fn(self.def_id) { - hir::IsAsync::Async - } else { - hir::IsAsync::NotAsync - }; + let asyncness = cx.tcx.asyncness(self.def_id); let defaultness = match self.container { ty::ImplContainer(_) => Some(self.defaultness), ty::TraitContainer(_) => None, From 726fe3b25573c8406a74e751d54f0bd3c663ea03 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sat, 21 Sep 2019 08:14:41 +0000 Subject: [PATCH 4/5] add rustdoc test for async fn reexport --- .../rustdoc/inline_cross/auxiliary/impl_trait_aux.rs | 10 ++++++++++ src/test/rustdoc/inline_cross/impl_trait.rs | 10 +++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs index 21c733a9bc98e..913ba8f2a1649 100644 --- a/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs +++ b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs @@ -1,3 +1,5 @@ +// edition:2018 + use std::ops::Deref; pub fn func<'a>(_x: impl Clone + Into> + 'a) {} @@ -11,8 +13,16 @@ pub fn func3(_x: impl Iterator> + Clone) {} pub fn func4>(_x: T) {} +pub async fn async_fn() {} + pub struct Foo; impl Foo { pub fn method<'a>(_x: impl Clone + Into> + 'a) {} } + +pub struct Bar; + +impl Bar { + pub async fn async_foo(&self) {} +} diff --git a/src/test/rustdoc/inline_cross/impl_trait.rs b/src/test/rustdoc/inline_cross/impl_trait.rs index b1e3f8d145b5f..6f4a48c83c05b 100644 --- a/src/test/rustdoc/inline_cross/impl_trait.rs +++ b/src/test/rustdoc/inline_cross/impl_trait.rs @@ -1,4 +1,5 @@ // aux-build:impl_trait_aux.rs +// edition:2018 extern crate impl_trait_aux; @@ -20,13 +21,20 @@ pub use impl_trait_aux::func2; // @!has - '//pre[@class="rust fn"]' 'where' pub use impl_trait_aux::func3; - // @has impl_trait/fn.func4.html // @has - '//pre[@class="rust fn"]' "func4(" // @has - '//pre[@class="rust fn"]' "T: Iterator," pub use impl_trait_aux::func4; +// @has impl_trait/fn.async_fn.html +// @has - '//pre[@class="rust fn"]' "pub async fn async_fn()" +pub use impl_trait_aux::async_fn; + // @has impl_trait/struct.Foo.html // @has - '//code[@id="method.v"]' "pub fn method<'a>(_x: impl Clone + Into> + 'a)" // @!has - '//code[@id="method.v"]' 'where' pub use impl_trait_aux::Foo; + +// @has impl_trait/struct.Bar.html +// @has - '//*[@id="method.async_foo"]' "pub async fn async_foo(" +pub use impl_trait_aux::Bar; From a744fd04321f6307303a22ecc8880cbc7b6bcbda Mon Sep 17 00:00:00 2001 From: csmoe Date: Mon, 23 Sep 2019 17:13:11 +0000 Subject: [PATCH 5/5] bug-out asyncness query on non-local funtions --- src/librustc/ty/mod.rs | 21 +++++++++++---------- src/librustc_metadata/decoder.rs | 3 ++- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index dd36a4520929a..98fa64c265cb2 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3351,16 +3351,17 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { /// Check if a function is async. fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { - if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) { - let node = tcx.hir().get(hir_id); - if let Some(fn_like) = hir::map::blocks::FnLikeNode::from_node(node) { - fn_like.asyncness() - } else { - hir::IsAsync::NotAsync - } - } else { - hir::IsAsync::NotAsync - } + let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap_or_else(|| { + bug!("asyncness: expected local `DefId`, got `{:?}`", def_id) + }); + + let node = tcx.hir().get(hir_id); + + let fn_like = hir::map::blocks::FnLikeNode::from_node(node).unwrap_or_else(|| { + bug!("asyncness: expected fn-like node but got `{:?}`", def_id); + }); + + fn_like.asyncness() } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 5153564fc8255..6698c7cb17036 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1212,7 +1212,8 @@ impl<'a, 'tcx> CrateMetadata { match self.entry(id).kind { EntryKind::Fn(data) => data.decode(self).asyncness, EntryKind::Method(data) => data.decode(self).fn_data.asyncness, - _ => hir::IsAsync::NotAsync, + EntryKind::ForeignFn(data) => data.decode(self).asyncness, + _ => bug!("asyncness: expect functions entry."), } }