diff --git a/RELEASES.md b/RELEASES.md index ecf49278f4b52..766cf64410c77 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -70,10 +70,10 @@ Misc Compatibility Notes ------------------- -- Unfortunately the [`x86_64-unknown-uefi` platform can not be built][62785] - with rustc 1.39.0. -- The [`armv7-unknown-linux-gnueabihf` platform is also known to have - issues][62896] for certain crates such as libc. +- The [`x86_64-unknown-uefi` platform can not be built][62785] with rustc + 1.38.0. +- The [`armv7-unknown-linux-gnueabihf` platform is known to have + issues][62896] with certain crates such as libc. [60260]: https://github.com/rust-lang/rust/pull/60260/ [61457]: https://github.com/rust-lang/rust/pull/61457/ diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index c7260945295a6..252e49d5d15f6 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 asyncness(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/ty/mod.rs b/src/librustc/ty/mod.rs index 8bb9648e031ef..89afbbaf4d402 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3353,6 +3353,22 @@ 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 { + 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() +} + + pub fn provide(providers: &mut ty::query::Providers<'_>) { context::provide(providers); erase_regions::provide(providers); @@ -3360,6 +3376,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { util::provide(providers); constness::provide(providers); *providers = ty::query::Providers { + 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 a1e3bbcbf8ea9..55cf3965aa85a 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) } + 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 34c84b1d79d4b..247748eb3eba5 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1212,6 +1212,15 @@ impl<'a, 'tcx> CrateMetadata { constness == hir::Constness::Const } + 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, + EntryKind::ForeignFn(data) => data.decode(self).asyncness, + _ => bug!("asyncness: expect functions entry."), + } + } + 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..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,6 +885,7 @@ impl EncodeContext<'tcx> { } }; FnData { + asyncness: method_sig.header.asyncness, 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>, diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index d687a5084e231..2cd8507d753a6 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -676,7 +676,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } else { // Pattern has wrong number of fields. - self.e0023(pat.span, res, &subpats, &variant.fields, expected); + self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected); on_error(); return tcx.types.err; } @@ -687,22 +687,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, pat_span: Span, res: Res, + qpath: &hir::QPath, subpats: &'tcx [P], fields: &[ty::FieldDef], expected: Ty<'tcx> ) { let subpats_ending = pluralise!(subpats.len()); let fields_ending = pluralise!(fields.len()); - let missing_parenthesis = match expected.sty { - ty::Adt(_, substs) if fields.len() == 1 => { - let field_ty = fields[0].ty(self.tcx, substs); - match field_ty.sty { - ty::Tuple(_) => field_ty.tuple_fields().count() == subpats.len(), - _ => false, - } - } - _ => false, - }; let res_span = self.tcx.def_span(res.def_id()); let mut err = struct_span_err!( self.tcx.sess, @@ -723,11 +714,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )) .span_label(res_span, format!("{} defined here", res.descr())); + // Identify the case `Some(x, y)` where the expected type is e.g. `Option<(T, U)>`. + // More generally, the expected type wants a tuple variant with one field of an + // N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern + // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`. + let missing_parenthesis = match expected.sty { + ty::Adt(_, substs) if fields.len() == 1 => { + let field_ty = fields[0].ty(self.tcx, substs); + match field_ty.sty { + ty::Tuple(_) => field_ty.tuple_fields().count() == subpats.len(), + _ => false, + } + } + _ => false, + }; if missing_parenthesis { + let (left, right) = match subpats { + // This is the zero case; we aim to get the "hi" part of the `QPath`'s + // span as the "lo" and then the "hi" part of the pattern's span as the "hi". + // This looks like: + // + // help: missing parenthesis + // | + // L | let A(()) = A(()); + // | ^ ^ + [] => { + let qpath_span = match qpath { + hir::QPath::Resolved(_, path) => path.span, + hir::QPath::TypeRelative(_, ps) => ps.ident.span, + }; + (qpath_span.shrink_to_hi(), pat_span) + }, + // Easy case. Just take the "lo" of the first sub-pattern and the "hi" of the + // last sub-pattern. In the case of `A(x)` the first and last may coincide. + // This looks like: + // + // help: missing parenthesis + // | + // L | let A((x, y)) = A((1, 2)); + // | ^ ^ + [first, ..] => (first.span.shrink_to_lo(), subpats.last().unwrap().span), + }; err.multipart_suggestion( "missing parenthesis", - vec![(subpats[0].span.shrink_to_lo(), "(".to_string()), - (subpats[subpats.len()-1].span.shrink_to_hi(), ")".to_string())], + vec![ + (left, "(".to_string()), + (right.shrink_to_hi(), ")".to_string()), + ], Applicability::MachineApplicable, ); } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index cb42ff1c8052f..d71acb4fa7b31 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -217,7 +217,7 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function { } else { hir::Constness::NotConst }; - + 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)) @@ -230,7 +230,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..95a5869e84510 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2403,6 +2403,7 @@ impl Clean for ty::AssocItem { } else { hir::Constness::NotConst }; + let asyncness = cx.tcx.asyncness(self.def_id); let defaultness = match self.container { ty::ImplContainer(_) => Some(self.defaultness), ty::TraitContainer(_) => None, @@ -2414,7 +2415,7 @@ impl Clean for ty::AssocItem { unsafety: sig.unsafety(), abi: sig.abi(), constness, - asyncness: hir::IsAsync::NotAsync, + asyncness, }, defaultness, all_types, diff --git a/src/stage0.txt b/src/stage0.txt index 2711b33b3635f..20e87d435bc18 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,7 +12,7 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2019-09-24 +date: 2019-09-26 rustc: 1.38.0 cargo: 0.39.0 @@ -34,4 +34,4 @@ cargo: 0.39.0 # looking at a beta source tarball and it's uncommented we'll shortly comment it # out. -dev: 1 +#dev: 1 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; diff --git a/src/test/ui/error-codes/E0023.rs b/src/test/ui/error-codes/E0023.rs index dc421e060e86f..7ac22bb71092e 100644 --- a/src/test/ui/error-codes/E0023.rs +++ b/src/test/ui/error-codes/E0023.rs @@ -2,9 +2,9 @@ enum Fruit { Apple(String, String), Pear(u32), Orange((String, String)), + Banana(()), } - fn main() { let x = Fruit::Apple(String::new(), String::new()); match x { @@ -12,5 +12,6 @@ fn main() { Fruit::Apple(a, b, c) => {}, //~ ERROR E0023 Fruit::Pear(1, 2) => {}, //~ ERROR E0023 Fruit::Orange(a, b) => {}, //~ ERROR E0023 + Fruit::Banana() => {}, //~ ERROR E0023 } } diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr index 8ae7d01ed5f7e..dbce6003a2bad 100644 --- a/src/test/ui/error-codes/E0023.stderr +++ b/src/test/ui/error-codes/E0023.stderr @@ -38,6 +38,19 @@ help: missing parenthesis LL | Fruit::Orange((a, b)) => {}, | ^ ^ -error: aborting due to 4 previous errors +error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 1 field + --> $DIR/E0023.rs:15:9 + | +LL | Banana(()), + | ---------- tuple variant defined here +... +LL | Fruit::Banana() => {}, + | ^^^^^^^^^^^^^^^ expected 1 field, found 0 +help: missing parenthesis + | +LL | Fruit::Banana(()) => {}, + | ^ ^ + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0023`. diff --git a/src/tools/cargo b/src/tools/cargo index b6c6f685b38d5..4b105b6abfb12 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit b6c6f685b38d523580813b0031677c2298f458ea +Subproject commit 4b105b6abfb12d6985ffe66670e8b2a85982291a