From 1c12b1be330dd9c3de0b4fe599686d7c0c45e720 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Mon, 24 Jun 2019 22:58:53 +0200 Subject: [PATCH 1/9] call out explicitly that general read needs to be called with an initialized buffer --- src/libstd/io/mod.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 917199f8ea8d0..7fba844897ffe 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -506,9 +506,18 @@ pub trait Read { /// /// No guarantees are provided about the contents of `buf` when this /// function is called, implementations cannot rely on any property of the - /// contents of `buf` being true. It is recommended that implementations + /// contents of `buf` being true. It is recommended that *implementations* /// only write data to `buf` instead of reading its contents. /// + /// Correspondingly, however, *users* of this trait may not assume any guarantees + /// about how the implementation uses `buf`. The trait is safe to implement, + /// so it is perfectly possible that the implementation might inspect that data. + /// As a caller, it is your responsibility to make sure that `buf` is initialized + /// before calling `read`. Calling `read` with an uninitialized `buf` (of the kind one + /// obtains via [`MaybeUninit<T>`]) is not safe, and can lead to undefined behavior. + /// + /// [`MaybeUninit<T>`]: ../mem/union.MaybeUninit.html + /// /// # Errors /// /// If this function encounters any form of I/O or other error, an error From c877989655d151972cd6a9c60450951a2efa0513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com> Date: Tue, 25 Jun 2019 04:00:03 +0200 Subject: [PATCH 2/9] Add some #[inline] attributes --- src/libsyntax_pos/symbol.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 756bc8c29d828..18c379f61f8d2 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -1131,6 +1131,7 @@ impl LocalInternedString { } } + #[inline] pub fn get(&self) -> &str { // This returns a valid string since we ensure that `self` outlives the interner // by creating the interner on a thread which outlives threads which can access it. @@ -1144,6 +1145,7 @@ impl<U: ?Sized> std::convert::AsRef<U> for LocalInternedString where str: std::convert::AsRef<U> { + #[inline] fn as_ref(&self) -> &U { self.string.as_ref() } @@ -1184,6 +1186,7 @@ impl !Sync for LocalInternedString {} impl std::ops::Deref for LocalInternedString { type Target = str; + #[inline] fn deref(&self) -> &str { self.string } } From 11221d120f8f79ff8e6ad35256874f30a942908b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com> Date: Tue, 25 Jun 2019 01:41:16 +0200 Subject: [PATCH 3/9] Inform the query system about properties of queries at compile time --- src/librustc/dep_graph/dep_node.rs | 4 --- src/librustc/ty/query/config.rs | 7 +++- src/librustc/ty/query/mod.rs | 2 +- src/librustc/ty/query/plumbing.rs | 57 +++++++++++++++++++++++------- src/librustc_macros/src/query.rs | 20 ++++------- 5 files changed, 58 insertions(+), 32 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 82b0e50b50c48..3d5e7dd0af121 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -142,9 +142,6 @@ macro_rules! define_dep_nodes { } } - // FIXME: Make `is_anon`, `is_eval_always` and `has_params` properties - // of queries - #[inline(always)] pub fn is_anon(&self) -> bool { match *self { $( @@ -163,7 +160,6 @@ macro_rules! define_dep_nodes { } #[allow(unreachable_code)] - #[inline(always)] pub fn has_params(&self) -> bool { match *self { $( diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index 13d93f173e845..6ad4ecb3e980c 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -1,5 +1,5 @@ use crate::dep_graph::SerializedDepNodeIndex; -use crate::dep_graph::DepNode; +use crate::dep_graph::{DepKind, DepNode}; use crate::hir::def_id::{CrateNum, DefId}; use crate::ty::TyCtxt; use crate::ty::query::queries; @@ -28,6 +28,9 @@ pub trait QueryConfig<'tcx> { } pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> { + const ANON: bool; + const EVAL_ALWAYS: bool; + fn query(key: Self::Key) -> Query<'tcx>; // Don't use this method to access query results, instead use the methods on TyCtxt @@ -35,6 +38,8 @@ pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> { fn to_dep_node(tcx: TyCtxt<'tcx>, key: &Self::Key) -> DepNode; + fn dep_kind() -> DepKind; + // Don't use this method to compute query results, instead use the methods on TyCtxt fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value; diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index e595b52876f4c..e788628bc58e2 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -101,6 +101,6 @@ pub use self::on_disk_cache::OnDiskCache; rustc_query_append! { [define_queries!][ <'tcx> Other { /// Runs analysis passes on the crate. - [] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>, + [eval_always] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>, }, ]} diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 7d5f984c1b6f2..553c701c3aaa0 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -376,15 +376,13 @@ impl<'tcx> TyCtxt<'tcx> { return self.force_query_with_job::<Q>(key, job, null_dep_node).0; } - let dep_node = Q::to_dep_node(self, &key); - - if dep_node.kind.is_anon() { + if Q::ANON { profq_msg!(self, ProfileQueriesMsg::ProviderBegin); self.sess.profiler(|p| p.start_query(Q::NAME)); let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { self.start_query(job.job.clone(), diagnostics, |tcx| { - tcx.dep_graph.with_anon_task(dep_node.kind, || { + tcx.dep_graph.with_anon_task(Q::dep_kind(), || { Q::compute(tcx.global_tcx(), key) }) }) @@ -405,7 +403,9 @@ impl<'tcx> TyCtxt<'tcx> { return result; } - if !dep_node.kind.is_eval_always() { + let dep_node = Q::to_dep_node(self, &key); + + if !Q::EVAL_ALWAYS { // The diagnostics for this query will be // promoted to the current session during // try_mark_green(), so we can ignore them here. @@ -546,7 +546,7 @@ impl<'tcx> TyCtxt<'tcx> { let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { self.start_query(job.job.clone(), diagnostics, |tcx| { - if dep_node.kind.is_eval_always() { + if Q::EVAL_ALWAYS { tcx.dep_graph.with_eval_always_task(dep_node, tcx, key, @@ -569,8 +569,8 @@ impl<'tcx> TyCtxt<'tcx> { self.dep_graph.mark_loaded_from_cache(dep_node_index, false); } - if dep_node.kind != crate::dep_graph::DepKind::Null { - if unlikely!(!diagnostics.is_empty()) { + if unlikely!(!diagnostics.is_empty()) { + if dep_node.kind != crate::dep_graph::DepKind::Null { self.queries.on_disk_cache .store_diagnostics(dep_node_index, diagnostics); } @@ -589,15 +589,16 @@ impl<'tcx> TyCtxt<'tcx> { /// /// Note: The optimization is only available during incr. comp. pub(super) fn ensure_query<Q: QueryDescription<'tcx>>(self, key: Q::Key) -> () { - let dep_node = Q::to_dep_node(self, &key); - - if dep_node.kind.is_eval_always() { + if Q::EVAL_ALWAYS { let _ = self.get_query::<Q>(DUMMY_SP, key); return; } // Ensuring an anonymous query makes no sense - assert!(!dep_node.kind.is_anon()); + assert!(!Q::ANON); + + let dep_node = Q::to_dep_node(self, &key); + if self.dep_graph.try_mark_green_and_read(self, &dep_node).is_none() { // A None return from `try_mark_green_and_read` means that this is either // a new dep node or that the dep node has already been marked red. @@ -653,6 +654,30 @@ macro_rules! handle_cycle_error { }; } +macro_rules! is_anon { + ([]) => {{ + false + }}; + ([anon$(, $modifiers:ident)*]) => {{ + true + }}; + ([$other:ident$(, $modifiers:ident)*]) => { + is_anon!([$($modifiers),*]) + }; +} + +macro_rules! is_eval_always { + ([]) => {{ + false + }}; + ([eval_always$(, $modifiers:ident)*]) => {{ + true + }}; + ([$other:ident$(, $modifiers:ident)*]) => { + is_eval_always!([$($modifiers),*]) + }; +} + macro_rules! hash_result { ([][$hcx:expr, $result:expr]) => {{ dep_graph::hash_result($hcx, &$result) @@ -933,6 +958,9 @@ macro_rules! define_queries_inner { } impl<$tcx> QueryAccessors<$tcx> for queries::$name<$tcx> { + const ANON: bool = is_anon!([$($modifiers)*]); + const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]); + #[inline(always)] fn query(key: Self::Key) -> Query<'tcx> { Query::$name(key) @@ -951,6 +979,11 @@ macro_rules! define_queries_inner { DepNode::new(tcx, $node(*key)) } + #[inline(always)] + fn dep_kind() -> dep_graph::DepKind { + dep_graph::DepKind::$node + } + #[inline] fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value { __query_compute::$name(move || { diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs index 0474d2a2e3b3a..2cf364b562766 100644 --- a/src/librustc_macros/src/query.rs +++ b/src/librustc_macros/src/query.rs @@ -423,20 +423,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { if modifiers.no_hash { attributes.push(quote! { no_hash }); }; - - let mut attribute_stream = quote! {}; - - for e in attributes.into_iter().intersperse(quote! {,}) { - attribute_stream.extend(e); - } - - // Add the query to the group - group_stream.extend(quote! { - [#attribute_stream] fn #name: #name(#arg) #result, - }); - - let mut attributes = Vec::new(); - // Pass on the anon modifier if modifiers.anon { attributes.push(quote! { anon }); @@ -450,6 +436,12 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { for e in attributes.into_iter().intersperse(quote! {,}) { attribute_stream.extend(e); } + + // Add the query to the group + group_stream.extend(quote! { + [#attribute_stream] fn #name: #name(#arg) #result, + }); + // Create a dep node for the query dep_node_def_stream.extend(quote! { [#attribute_stream] #name(#arg), From 85ea4a1bf4a05ff18d6634db35eb41c3a6bca637 Mon Sep 17 00:00:00 2001 From: Yuki Okushi <huyuumi.dev@gmail.com> Date: Tue, 25 Jun 2019 23:09:25 +0900 Subject: [PATCH 4/9] Update new_debug_unreachable --- Cargo.lock | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eaec52a7a150c..98dd10955d57d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1030,7 +1030,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1760,11 +1760,8 @@ dependencies = [ [[package]] name = "new_debug_unreachable" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "nodrop" @@ -3450,7 +3447,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4038,14 +4035,6 @@ name = "unicode_categories" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "unstable-book-gen" version = "0.1.0" @@ -4124,11 +4113,6 @@ name = "version_check" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "vte" version = "0.3.3" @@ -4388,7 +4372,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4" +"checksum new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8af1847c907c2f04d7bfd572fb25bbb4385c637fe5be163cf2f8c5d778fe1e7d" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" @@ -4552,7 +4536,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" "checksum utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c" @@ -4562,7 +4545,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6aba5e34f93dc7051dfad05b98a18e9156f27e7b431fe1d2398cb6061c0a1dba" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum vte 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f42f536e22f7fcbb407639765c8fd78707a33109301f834a594758bedd6e8cf" "checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" From b75021b31e43d59eb2b91fe45cfffcb7d25fb141 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov <aleksey.kladov@gmail.com> Date: Tue, 25 Jun 2019 21:02:19 +0300 Subject: [PATCH 5/9] refactor lexer to use idiomatic borrowing --- src/libsyntax/parse/lexer/mod.rs | 225 ++++++++++++++----------------- 1 file changed, 104 insertions(+), 121 deletions(-) diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index ead5d543bec7d..7b9e3bc4d5102 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -321,33 +321,29 @@ impl<'a> StringReader<'a> { (pos - self.source_file.start_pos).to_usize() } - /// Calls `f` with a string slice of the source text spanning from `start` - /// up to but excluding `self.pos`, meaning the slice does not include - /// the character `self.ch`. - fn with_str_from<T, F>(&self, start: BytePos, f: F) -> T - where F: FnOnce(&str) -> T + /// Slice of the source text from `start` up to but excluding `self.pos`, + /// meaning the slice does not include the character `self.ch`. + fn str_from(&self, start: BytePos) -> &str { - self.with_str_from_to(start, self.pos, f) + self.str_from_to(start, self.pos) } /// Creates a Name from a given offset to the current offset. fn name_from(&self, start: BytePos) -> ast::Name { debug!("taking an ident from {:?} to {:?}", start, self.pos); - self.with_str_from(start, Symbol::intern) + Symbol::intern(self.str_from(start)) } /// As name_from, with an explicit endpoint. fn name_from_to(&self, start: BytePos, end: BytePos) -> ast::Name { debug!("taking an ident from {:?} to {:?}", start, end); - self.with_str_from_to(start, end, Symbol::intern) + Symbol::intern(self.str_from_to(start, end)) } - /// Calls `f` with a string slice of the source text spanning from `start` - /// up to but excluding `end`. - fn with_str_from_to<T, F>(&self, start: BytePos, end: BytePos, f: F) -> T - where F: FnOnce(&str) -> T + /// Slice of the source text spanning from `start` up to but excluding `end`. + fn str_from_to(&self, start: BytePos, end: BytePos) -> &str { - f(&self.src[self.src_index(start)..self.src_index(end)]) + &self.src[self.src_index(start)..self.src_index(end)] } /// Converts CRLF to LF in the given string, raising an error on bare CR. @@ -456,8 +452,8 @@ impl<'a> StringReader<'a> { self.bump(); } - self.with_str_from(start, |string| { - if string == "_" { + match self.str_from(start) { + "_" => { self.sess.span_diagnostic .struct_span_warn(self.mk_sp(start, self.pos), "underscore literal suffix is not allowed") @@ -468,10 +464,9 @@ impl<'a> StringReader<'a> { <https://github.com/rust-lang/rust/issues/42326>") .emit(); None - } else { - Some(Symbol::intern(string)) } - }) + name => Some(Symbol::intern(name)) + } } /// PRECONDITION: self.ch is not whitespace @@ -513,9 +508,7 @@ impl<'a> StringReader<'a> { } let kind = if doc_comment { - self.with_str_from(start_bpos, |string| { - token::DocComment(Symbol::intern(string)) - }) + token::DocComment(self.name_from(start_bpos)) } else { token::Comment }; @@ -615,23 +608,22 @@ impl<'a> StringReader<'a> { self.bump(); } - self.with_str_from(start_bpos, |string| { - // but comments with only "*"s between two "/"s are not - let kind = if is_block_doc_comment(string) { - let string = if has_cr { - self.translate_crlf(start_bpos, - string, - "bare CR not allowed in block doc-comment") - } else { - string.into() - }; - token::DocComment(Symbol::intern(&string[..])) + let string = self.str_from(start_bpos); + // but comments with only "*"s between two "/"s are not + let kind = if is_block_doc_comment(string) { + let string = if has_cr { + self.translate_crlf(start_bpos, + string, + "bare CR not allowed in block doc-comment") } else { - token::Comment + string.into() }; + token::DocComment(Symbol::intern(&string[..])) + } else { + token::Comment + }; - Some(Token::new(kind, self.mk_sp(start_bpos, self.pos))) - }) + Some(Token::new(kind, self.mk_sp(start_bpos, self.pos))) } /// Scan through any digits (base `scan_radix`) or underscores, @@ -838,20 +830,17 @@ impl<'a> StringReader<'a> { self.bump(); } - return Ok(self.with_str_from(start, |string| { - // FIXME: perform NFKC normalization here. (Issue #2253) - let name = ast::Name::intern(string); - - if is_raw_ident { - let span = self.mk_sp(raw_start, self.pos); - if !name.can_be_raw() { - self.err_span(span, &format!("`{}` cannot be a raw identifier", name)); - } - self.sess.raw_identifier_spans.borrow_mut().push(span); + // FIXME: perform NFKC normalization here. (Issue #2253) + let name = self.name_from(start); + if is_raw_ident { + let span = self.mk_sp(raw_start, self.pos); + if !name.can_be_raw() { + self.err_span(span, &format!("`{}` cannot be a raw identifier", name)); } + self.sess.raw_identifier_spans.borrow_mut().push(span); + } - token::Ident(name, is_raw_ident) - })); + return Ok(token::Ident(name, is_raw_ident)); } } @@ -1300,101 +1289,95 @@ impl<'a> StringReader<'a> { } fn validate_char_escape(&self, start_with_quote: BytePos) { - self.with_str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1), |lit| { - if let Err((off, err)) = unescape::unescape_char(lit) { + let lit = self.str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1)); + if let Err((off, err)) = unescape::unescape_char(lit) { + emit_unescape_error( + &self.sess.span_diagnostic, + lit, + self.mk_sp(start_with_quote, self.pos), + unescape::Mode::Char, + 0..off, + err, + ) + } + } + + fn validate_byte_escape(&self, start_with_quote: BytePos) { + let lit = self.str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1)); + if let Err((off, err)) = unescape::unescape_byte(lit) { + emit_unescape_error( + &self.sess.span_diagnostic, + lit, + self.mk_sp(start_with_quote, self.pos), + unescape::Mode::Byte, + 0..off, + err, + ) + } + } + + fn validate_str_escape(&self, start_with_quote: BytePos) { + let lit = self.str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1)); + unescape::unescape_str(lit, &mut |range, c| { + if let Err(err) = c { emit_unescape_error( &self.sess.span_diagnostic, lit, self.mk_sp(start_with_quote, self.pos), - unescape::Mode::Char, - 0..off, + unescape::Mode::Str, + range, err, ) } - }); + }) } - fn validate_byte_escape(&self, start_with_quote: BytePos) { - self.with_str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1), |lit| { - if let Err((off, err)) = unescape::unescape_byte(lit) { + fn validate_raw_str_escape(&self, content_start: BytePos, content_end: BytePos) { + let lit = self.str_from_to(content_start, content_end); + unescape::unescape_raw_str(lit, &mut |range, c| { + if let Err(err) = c { emit_unescape_error( &self.sess.span_diagnostic, lit, - self.mk_sp(start_with_quote, self.pos), - unescape::Mode::Byte, - 0..off, + self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)), + unescape::Mode::Str, + range, err, ) } - }); - } - - fn validate_str_escape(&self, start_with_quote: BytePos) { - self.with_str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1), |lit| { - unescape::unescape_str(lit, &mut |range, c| { - if let Err(err) = c { - emit_unescape_error( - &self.sess.span_diagnostic, - lit, - self.mk_sp(start_with_quote, self.pos), - unescape::Mode::Str, - range, - err, - ) - } - }) - }); - } - - fn validate_raw_str_escape(&self, content_start: BytePos, content_end: BytePos) { - self.with_str_from_to(content_start, content_end, |lit: &str| { - unescape::unescape_raw_str(lit, &mut |range, c| { - if let Err(err) = c { - emit_unescape_error( - &self.sess.span_diagnostic, - lit, - self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)), - unescape::Mode::Str, - range, - err, - ) - } - }) - }); + }) } fn validate_raw_byte_str_escape(&self, content_start: BytePos, content_end: BytePos) { - self.with_str_from_to(content_start, content_end, |lit: &str| { - unescape::unescape_raw_byte_str(lit, &mut |range, c| { - if let Err(err) = c { - emit_unescape_error( - &self.sess.span_diagnostic, - lit, - self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)), - unescape::Mode::ByteStr, - range, - err, - ) - } - }) - }); + let lit = self.str_from_to(content_start, content_end); + unescape::unescape_raw_byte_str(lit, &mut |range, c| { + if let Err(err) = c { + emit_unescape_error( + &self.sess.span_diagnostic, + lit, + self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)), + unescape::Mode::ByteStr, + range, + err, + ) + } + }) } fn validate_byte_str_escape(&self, start_with_quote: BytePos) { - self.with_str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1), |lit| { - unescape::unescape_byte_str(lit, &mut |range, c| { - if let Err(err) = c { - emit_unescape_error( - &self.sess.span_diagnostic, - lit, - self.mk_sp(start_with_quote, self.pos), - unescape::Mode::ByteStr, - range, - err, - ) - } - }) - }); + let lit = self.str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1)); + unescape::unescape_byte_str(lit, &mut |range, c| { + if let Err(err) = c { + emit_unescape_error( + &self.sess.span_diagnostic, + lit, + self.mk_sp(start_with_quote, self.pos), + unescape::Mode::ByteStr, + range, + err, + ) + } + }) } } From 0f34d7a7e5f068683097e0e664249bd6a417032f Mon Sep 17 00:00:00 2001 From: Erin Power <xampprocky@gmail.com> Date: Sun, 23 Jun 2019 11:45:06 +0200 Subject: [PATCH 6/9] Updated RELEASES.md for 1.36.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Taiki Endo <te316e89@gmail.com> Co-Authored-By: Jonas Schievink <jonasschievink@gmail.com> Co-Authored-By: Torbjørn Birch Moltu <t.b.moltu@lyse.net> --- RELEASES.md | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 91e3c5f721952..b6e2171f6eef9 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,104 @@ +Version 1.36.0 (2019-07-04) +========================== + +Language +-------- +- [Non-Lexical Lifetimes are now enabled on the 2015 edition.][59114] +- [The order of traits in trait objects no longer affects the semantics of that + object.][59445] e.g. `dyn Send + fmt::Debug` is now equivalent to + `dyn fmt::Debug + Send`, where this was previously not the case. + +Libraries +--------- +- [`HashMap`'s implementation has been replaced with `hashbrown::HashMap` implementation.][58623] +- [`TryFromSliceError` now implements `From<Infallible>`.][60318] +- [`mem::needs_drop` is now available as a const fn.][60364] +- [`alloc::Layout::from_size_align_unchecked` is now available as a const fn.][60370] +- [`String` now implements `BorrowMut<str>`.][60404] +- [`io::Cursor` now implements `Default`.][60234] +- [Both `NonNull::{dangling, cast}` are now const fns.][60244] +- [The `alloc` crate is now stable.][59675] `alloc` allows you to use a subset + of `std` (e.g. `Vec`, `Box`, `Arc`) in `#![no_std]` environments if the + environment has access to heap memory allocation. +- [`String` now implements `From<&String>`.][59825] +- [You can now pass multiple arguments to the `dbg!` macro.][59826] `dbg!` will + return a tuple of each argument when there is multiple arguments. +- [`Result::{is_err, is_ok}` are now `#[must_use]` and will produce a warning if + not used.][59648] + +Stabilized APIs +--------------- +- [`VecDeque::rotate_left`] +- [`VecDeque::rotate_right`] +- [`Iterator::copied`] +- [`io::IoSlice`] +- [`io::IoSliceMut`] +- [`Read::read_vectored`] +- [`Write::write_vectored`] +- [`str::as_mut_ptr`] +- [`mem::MaybeUninit`] +- [`pointer::align_offset`] +- [`future::Future`] +- [`task::Context`] +- [`task::RawWaker`] +- [`task::RawWakerVTable`] +- [`task::Waker`] +- [`task::Poll`] + +Cargo +----- +- [Cargo will now produce an error if you attempt to use the name of a required dependency as a feature.][cargo/6860] +- [You can now pass the `--offline` flag to run cargo without accessing the network.][cargo/6934] + +You can find further change's in [Cargo's 1.36.0 release notes][cargo-1-36-0]. + +Clippy +------ +There have been numerous additions and fixes to clippy, see [Clippy's 1.36.0 release notes][clippy-1-36-0] for more details. + +Misc +---- + +Compatibility Notes +------------------- +- With the stabilisation of `mem::MaybeUninit`, `mem::uninitialized` use is no + longer recommended, and will be deprecated in 1.38.0. + +[60318]: https://github.com/rust-lang/rust/pull/60318/ +[60364]: https://github.com/rust-lang/rust/pull/60364/ +[60370]: https://github.com/rust-lang/rust/pull/60370/ +[60404]: https://github.com/rust-lang/rust/pull/60404/ +[60234]: https://github.com/rust-lang/rust/pull/60234/ +[60244]: https://github.com/rust-lang/rust/pull/60244/ +[58623]: https://github.com/rust-lang/rust/pull/58623/ +[59648]: https://github.com/rust-lang/rust/pull/59648/ +[59675]: https://github.com/rust-lang/rust/pull/59675/ +[59825]: https://github.com/rust-lang/rust/pull/59825/ +[59826]: https://github.com/rust-lang/rust/pull/59826/ +[59445]: https://github.com/rust-lang/rust/pull/59445/ +[59114]: https://github.com/rust-lang/rust/pull/59114/ +[cargo/6860]: https://github.com/rust-lang/cargo/pull/6860/ +[cargo/6934]: https://github.com/rust-lang/cargo/pull/6934/ +[`VecDeque::rotate_left`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.rotate_left +[`VecDeque::rotate_right`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.rotate_right +[`Iterator::copied`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.copied +[`io::IoSlice`]: https://doc.rust-lang.org/std/io/struct.IoSlice.html +[`io::IoSliceMut`]: https://doc.rust-lang.org/std/io/struct.IoSliceMut.html +[`Read::read_vectored`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_vectored +[`Write::write_vectored`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_vectored +[`str::as_mut_ptr`]: https://doc.rust-lang.org/std/primitive.str.html#method.as_mut_ptr +[`mem::MaybeUninit`]: https://doc.rust-lang.org/std/mem/union.MaybeUninit.html +[`pointer::align_offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.align_offset +[`future::Future`]: https://doc.rust-lang.org/std/future/trait.Future.html +[`task::Context`]: https://doc.rust-lang.org/beta/std/task/struct.Context.html +[`task::RawWaker`]: https://doc.rust-lang.org/beta/std/task/struct.RawWaker.html +[`task::RawWakerVTable`]: https://doc.rust-lang.org/beta/std/task/struct.RawWakerVTable.html +[`task::Waker`]: https://doc.rust-lang.org/beta/std/task/struct.Waker.html +[`task::Poll`]: https://doc.rust-lang.org/beta/std/task/enum.Poll.html +[clippy-1-36-0]: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md#rust-136 +[cargo-1-36-0]: https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-136-2019-07-04 + + Version 1.35.0 (2019-05-23) ========================== @@ -62,7 +163,7 @@ Cargo - [You can now set `cargo:rustc-cdylib-link-arg` at build time to pass custom linker arguments when building a `cdylib`.][cargo/6298] Its usage is highly platform specific. - + Misc ---- - [The Rust toolchain is now available natively for musl based distros.][58575] From ba12e7862c58df2155011bb165a8ae1186828bc4 Mon Sep 17 00:00:00 2001 From: Taylor Cramer <cramertj@google.com> Date: Mon, 24 Jun 2019 17:48:21 -0700 Subject: [PATCH 7/9] Add more tests for async/await --- src/test/ui/async-await/async-fn-nonsend.rs | 59 ++++++++++++ .../ui/async-await/async-fn-nonsend.stderr | 87 ++++++++++++++++++ .../async-await/async-fn-send-uses-nonsend.rs | 59 ++++++++++++ .../ui/async-await/generics-and-bounds.rs | 90 +++++++++++++++++++ src/test/ui/async-await/no-async-const.rs | 8 ++ src/test/ui/async-await/no-async-const.stderr | 8 ++ src/test/ui/async-await/no-const-async.rs | 9 ++ src/test/ui/async-await/no-const-async.stderr | 18 ++++ 8 files changed, 338 insertions(+) create mode 100644 src/test/ui/async-await/async-fn-nonsend.rs create mode 100644 src/test/ui/async-await/async-fn-nonsend.stderr create mode 100644 src/test/ui/async-await/async-fn-send-uses-nonsend.rs create mode 100644 src/test/ui/async-await/generics-and-bounds.rs create mode 100644 src/test/ui/async-await/no-async-const.rs create mode 100644 src/test/ui/async-await/no-async-const.stderr create mode 100644 src/test/ui/async-await/no-const-async.rs create mode 100644 src/test/ui/async-await/no-const-async.stderr diff --git a/src/test/ui/async-await/async-fn-nonsend.rs b/src/test/ui/async-await/async-fn-nonsend.rs new file mode 100644 index 0000000000000..612c1e29d82bd --- /dev/null +++ b/src/test/ui/async-await/async-fn-nonsend.rs @@ -0,0 +1,59 @@ +// compile-fail +// edition:2018 +// compile-flags: --crate-type lib + +#![feature(async_await)] + +use std::{ + cell::RefCell, + fmt::Debug, + rc::Rc, +}; + +fn non_sync() -> impl Debug { RefCell::new(()) } + +fn non_send() -> impl Debug { Rc::new(()) } + +fn take_ref<T>(_: &T) {} + +async fn fut() {} + +async fn fut_arg<T>(_: T) {} + +async fn local_dropped_before_await() { + // FIXME: it'd be nice for this to be allowed in a `Send` `async fn` + let x = non_send(); + drop(x); + fut().await; +} + +async fn non_send_temporary_in_match() { + // We could theoretically make this work as well (produce a `Send` future) + // for scrutinees / temporaries that can or will + // be dropped prior to the match body + // (e.g. `Copy` types). + match Some(non_send()) { + Some(_) => fut().await, + None => {} + } +} + +async fn non_sync_with_method_call() { + // FIXME: it'd be nice for this to work. + let f: &mut std::fmt::Formatter = panic!(); + if non_sync().fmt(f).unwrap() == () { + fut().await; + } +} + +fn assert_send(_: impl Send) {} + +pub fn pass_assert() { + assert_send(local_dropped_before_await()); + //~^ ERROR `std::rc::Rc<()>` cannot be sent between threads safely + assert_send(non_send_temporary_in_match()); + //~^ ERROR `std::rc::Rc<()>` cannot be sent between threads safely + assert_send(non_sync_with_method_call()); + //~^ ERROR `dyn std::fmt::Write` cannot be sent between threads safely + //~^^ ERROR `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely +} diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr new file mode 100644 index 0000000000000..7776a36a28f2b --- /dev/null +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -0,0 +1,87 @@ +error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely + --> $DIR/async-fn-nonsend.rs:52:5 + | +LL | assert_send(local_dropped_before_await()); + | ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely + | + = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` + = note: required because it appears within the type `impl std::fmt::Debug` + = note: required because it appears within the type `{impl std::fmt::Debug, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:23:39: 28:2 {impl std::fmt::Debug, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:23:39: 28:2 {impl std::fmt::Debug, impl std::future::Future, ()}]>` + = note: required because it appears within the type `impl std::future::Future` + = note: required because it appears within the type `impl std::future::Future` +note: required by `assert_send` + --> $DIR/async-fn-nonsend.rs:49:1 + | +LL | fn assert_send(_: impl Send) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely + --> $DIR/async-fn-nonsend.rs:54:5 + | +LL | assert_send(non_send_temporary_in_match()); + | ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely + | + = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` + = note: required because it appears within the type `impl std::fmt::Debug` + = note: required because it appears within the type `{fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:30:40: 39:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:30:40: 39:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}]>` + = note: required because it appears within the type `impl std::future::Future` + = note: required because it appears within the type `impl std::future::Future` +note: required by `assert_send` + --> $DIR/async-fn-nonsend.rs:49:1 + | +LL | fn assert_send(_: impl Send) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `dyn std::fmt::Write` cannot be sent between threads safely + --> $DIR/async-fn-nonsend.rs:56:5 + | +LL | assert_send(non_sync_with_method_call()); + | ^^^^^^^^^^^ `dyn std::fmt::Write` cannot be sent between threads safely + | + = help: the trait `std::marker::Send` is not implemented for `dyn std::fmt::Write` + = note: required because of the requirements on the impl of `std::marker::Send` for `&mut dyn std::fmt::Write` + = note: required because it appears within the type `std::fmt::Formatter<'_>` + = note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>` + = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>` + = note: required because it appears within the type `impl std::future::Future` + = note: required because it appears within the type `impl std::future::Future` +note: required by `assert_send` + --> $DIR/async-fn-nonsend.rs:49:1 + | +LL | fn assert_send(_: impl Send) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely + --> $DIR/async-fn-nonsend.rs:56:5 + | +LL | assert_send(non_sync_with_method_call()); + | ^^^^^^^^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely + | + = help: within `std::fmt::ArgumentV1<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)` + = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>` + = note: required because it appears within the type `core::fmt::Void` + = note: required because it appears within the type `&core::fmt::Void` + = note: required because it appears within the type `std::fmt::ArgumentV1<'_>` + = note: required because of the requirements on the impl of `std::marker::Send` for `std::slice::Iter<'_, std::fmt::ArgumentV1<'_>>` + = note: required because it appears within the type `std::fmt::Formatter<'_>` + = note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>` + = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>` + = note: required because it appears within the type `impl std::future::Future` + = note: required because it appears within the type `impl std::future::Future` +note: required by `assert_send` + --> $DIR/async-fn-nonsend.rs:49:1 + | +LL | fn assert_send(_: impl Send) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/async-fn-send-uses-nonsend.rs b/src/test/ui/async-await/async-fn-send-uses-nonsend.rs new file mode 100644 index 0000000000000..f07fc2fceb5b6 --- /dev/null +++ b/src/test/ui/async-await/async-fn-send-uses-nonsend.rs @@ -0,0 +1,59 @@ +// compile-pass +// edition:2018 +// compile-flags: --crate-type lib + +#![feature(async_await)] + +use std::{ + cell::RefCell, + fmt::Debug, + rc::Rc, +}; + +fn non_sync() -> impl Debug { RefCell::new(()) } + +fn non_send() -> impl Debug { Rc::new(()) } + +fn take_ref<T>(_: &T) {} + +async fn fut() {} + +async fn fut_arg<T>(_: T) {} + +async fn still_send() { + fut().await; + println!("{:?} {:?}", non_send(), non_sync()); + fut().await; + drop(non_send()); + drop(non_sync()); + fut().await; + fut_arg(non_sync()).await; + + // Note: all temporaries in `if let` and `match` scrutinee + // are dropped at the *end* of the blocks, so using `non_send()` + // in either of those positions with an await in the middle will + // cause a `!Send` future. It might be nice in the future to allow + // this for `Copy` types, since they can be "dropped" early without + // affecting the end user. + if let Some(_) = Some(non_sync()) { + fut().await; + } + match Some(non_sync()) { + Some(_) => fut().await, + None => fut().await, + } + + let _ = non_send(); + fut().await; + + { + let _x = non_send(); + } + fut().await; +} + +fn assert_send(_: impl Send) {} + +pub fn pass_assert() { + assert_send(still_send()); +} diff --git a/src/test/ui/async-await/generics-and-bounds.rs b/src/test/ui/async-await/generics-and-bounds.rs new file mode 100644 index 0000000000000..913f1435c6adf --- /dev/null +++ b/src/test/ui/async-await/generics-and-bounds.rs @@ -0,0 +1,90 @@ +// compile-pass +// edition:2018 +// compile-flags: --crate-type lib + +#![feature(async_await)] + +use std::future::Future; + +pub async fn simple_generic<T>() {} + +pub trait Foo { + fn foo(&self) {} +} + +struct FooType; +impl Foo for FooType {} + +pub async fn call_generic_bound<F: Foo>(f: F) { + f.foo() +} + +pub async fn call_where_clause<F>(f: F) +where + F: Foo, +{ + f.foo() +} + +pub async fn call_impl_trait(f: impl Foo) { + f.foo() +} + +pub async fn call_with_ref(f: &impl Foo) { + f.foo() +} + +pub fn async_fn_with_same_generic_params_unifies() { + let mut a = call_generic_bound(FooType); + a = call_generic_bound(FooType); + + let mut b = call_where_clause(FooType); + b = call_where_clause(FooType); + + let mut c = call_impl_trait(FooType); + c = call_impl_trait(FooType); + + let f_one = FooType; + let f_two = FooType; + let mut d = call_with_ref(&f_one); + d = call_with_ref(&f_two); +} + +pub fn simple_generic_block<T>() -> impl Future<Output = ()> { + async move {} +} + +pub fn call_generic_bound_block<F: Foo>(f: F) -> impl Future<Output = ()> { + async move { f.foo() } +} + +pub fn call_where_clause_block<F>(f: F) -> impl Future<Output = ()> +where + F: Foo, +{ + async move { f.foo() } +} + +pub fn call_impl_trait_block(f: impl Foo) -> impl Future<Output = ()> { + async move { f.foo() } +} + +pub fn call_with_ref_block<'a>(f: &'a (impl Foo + 'a)) -> impl Future<Output = ()> + 'a { + async move { f.foo() } +} + +pub fn async_block_with_same_generic_params_unifies() { + let mut a = call_generic_bound_block(FooType); + a = call_generic_bound_block(FooType); + + let mut b = call_where_clause_block(FooType); + b = call_where_clause_block(FooType); + + let mut c = call_impl_trait_block(FooType); + c = call_impl_trait_block(FooType); + + let f_one = FooType; + let f_two = FooType; + let mut d = call_with_ref_block(&f_one); + d = call_with_ref_block(&f_two); +} diff --git a/src/test/ui/async-await/no-async-const.rs b/src/test/ui/async-await/no-async-const.rs new file mode 100644 index 0000000000000..1db314a5aa208 --- /dev/null +++ b/src/test/ui/async-await/no-async-const.rs @@ -0,0 +1,8 @@ +// compile-fail +// edition:2018 +// compile-flags: --crate-type lib + +#![feature(async_await)] + +pub async const fn x() {} +//~^ ERROR expected one of `fn` or `unsafe`, found `const` diff --git a/src/test/ui/async-await/no-async-const.stderr b/src/test/ui/async-await/no-async-const.stderr new file mode 100644 index 0000000000000..cdb1c6e2d7bd9 --- /dev/null +++ b/src/test/ui/async-await/no-async-const.stderr @@ -0,0 +1,8 @@ +error: expected one of `fn` or `unsafe`, found `const` + --> $DIR/no-async-const.rs:7:11 + | +LL | pub async const fn x() {} + | ^^^^^ expected one of `fn` or `unsafe` here + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/no-const-async.rs b/src/test/ui/async-await/no-const-async.rs new file mode 100644 index 0000000000000..9f09d2188c7c0 --- /dev/null +++ b/src/test/ui/async-await/no-const-async.rs @@ -0,0 +1,9 @@ +// compile-fail +// edition:2018 +// compile-flags: --crate-type lib + +#![feature(async_await)] + +pub const async fn x() {} +//~^ ERROR expected identifier, found reserved keyword `async` +//~^^ expected `:`, found keyword `fn` diff --git a/src/test/ui/async-await/no-const-async.stderr b/src/test/ui/async-await/no-const-async.stderr new file mode 100644 index 0000000000000..693fbf186f913 --- /dev/null +++ b/src/test/ui/async-await/no-const-async.stderr @@ -0,0 +1,18 @@ +error: expected identifier, found reserved keyword `async` + --> $DIR/no-const-async.rs:7:11 + | +LL | pub const async fn x() {} + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | pub const r#async fn x() {} + | ^^^^^^^ + +error: expected `:`, found keyword `fn` + --> $DIR/no-const-async.rs:7:17 + | +LL | pub const async fn x() {} + | ^^ expected `:` + +error: aborting due to 2 previous errors + From 57db25e614dfc3ea3c407374a562501471eb1c5d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov <aleksey.kladov@gmail.com> Date: Tue, 25 Jun 2019 21:37:25 +0300 Subject: [PATCH 8/9] cleanup: rename name_from to symbol_from Lexer uses Symbols for a lot of stuff, not only for identifiers, so the "name" terminology is just confusing. --- src/libsyntax/parse/lexer/mod.rs | 39 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 7b9e3bc4d5102..4e4fe4256c9b0 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1,4 +1,3 @@ -use crate::ast; use crate::parse::ParseSess; use crate::parse::token::{self, Token, TokenKind}; use crate::symbol::{sym, Symbol}; @@ -328,14 +327,14 @@ impl<'a> StringReader<'a> { self.str_from_to(start, self.pos) } - /// Creates a Name from a given offset to the current offset. - fn name_from(&self, start: BytePos) -> ast::Name { + /// Creates a Symbol from a given offset to the current offset. + fn symbol_from(&self, start: BytePos) -> Symbol { debug!("taking an ident from {:?} to {:?}", start, self.pos); Symbol::intern(self.str_from(start)) } - /// As name_from, with an explicit endpoint. - fn name_from_to(&self, start: BytePos, end: BytePos) -> ast::Name { + /// As symbol_from, with an explicit endpoint. + fn symbol_from_to(&self, start: BytePos, end: BytePos) -> Symbol { debug!("taking an ident from {:?} to {:?}", start, end); Symbol::intern(self.str_from_to(start, end)) } @@ -440,7 +439,7 @@ impl<'a> StringReader<'a> { } /// Eats <XID_start><XID_continue>*, if possible. - fn scan_optional_raw_name(&mut self) -> Option<ast::Name> { + fn scan_optional_raw_name(&mut self) -> Option<Symbol> { if !ident_start(self.ch) { return None; } @@ -508,7 +507,7 @@ impl<'a> StringReader<'a> { } let kind = if doc_comment { - token::DocComment(self.name_from(start_bpos)) + token::DocComment(self.symbol_from(start_bpos)) } else { token::Comment }; @@ -537,7 +536,7 @@ impl<'a> StringReader<'a> { self.bump(); } return Some(Token::new( - token::Shebang(self.name_from(start)), + token::Shebang(self.symbol_from(start)), self.mk_sp(start, self.pos), )); } @@ -719,17 +718,17 @@ impl<'a> StringReader<'a> { let pos = self.pos; self.check_float_base(start_bpos, pos, base); - (token::Float, self.name_from(start_bpos)) + (token::Float, self.symbol_from(start_bpos)) } else { // it might be a float if it has an exponent if self.ch_is('e') || self.ch_is('E') { self.scan_float_exponent(); let pos = self.pos; self.check_float_base(start_bpos, pos, base); - return (token::Float, self.name_from(start_bpos)); + return (token::Float, self.symbol_from(start_bpos)); } // but we certainly have an integer! - (token::Integer, self.name_from(start_bpos)) + (token::Integer, self.symbol_from(start_bpos)) } } @@ -831,7 +830,7 @@ impl<'a> StringReader<'a> { } // FIXME: perform NFKC normalization here. (Issue #2253) - let name = self.name_from(start); + let name = self.symbol_from(start); if is_raw_ident { let span = self.mk_sp(raw_start, self.pos); if !name.can_be_raw() { @@ -1006,7 +1005,7 @@ impl<'a> StringReader<'a> { // lifetimes shouldn't end with a single quote // if we find one, then this is an invalid character literal if self.ch_is('\'') { - let symbol = self.name_from(start); + let symbol = self.symbol_from(start); self.bump(); self.validate_char_escape(start_with_quote); return Ok(TokenKind::lit(token::Char, symbol, None)); @@ -1024,7 +1023,7 @@ impl<'a> StringReader<'a> { // Include the leading `'` in the real identifier, for macro // expansion purposes. See #12512 for the gory details of why // this is necessary. - return Ok(token::Lifetime(self.name_from(start_with_quote))); + return Ok(token::Lifetime(self.symbol_from(start_with_quote))); } let msg = "unterminated character literal"; let symbol = self.scan_single_quoted_string(start_with_quote, msg); @@ -1052,7 +1051,7 @@ impl<'a> StringReader<'a> { }, Some('r') => { let (start, end, hash_count) = self.scan_raw_string(); - let symbol = self.name_from_to(start, end); + let symbol = self.symbol_from_to(start, end); self.validate_raw_byte_str_escape(start, end); (token::ByteStrRaw(hash_count), symbol) @@ -1073,7 +1072,7 @@ impl<'a> StringReader<'a> { } 'r' => { let (start, end, hash_count) = self.scan_raw_string(); - let symbol = self.name_from_to(start, end); + let symbol = self.symbol_from_to(start, end); self.validate_raw_str_escape(start, end); let suffix = self.scan_optional_raw_name(); @@ -1174,7 +1173,7 @@ impl<'a> StringReader<'a> { fn scan_single_quoted_string(&mut self, start_with_quote: BytePos, - unterminated_msg: &str) -> ast::Name { + unterminated_msg: &str) -> Symbol { // assumes that first `'` is consumed let start = self.pos; // lex `'''` as a single char, for recovery @@ -1206,12 +1205,12 @@ impl<'a> StringReader<'a> { } } - let id = self.name_from(start); + let id = self.symbol_from(start); self.bump(); id } - fn scan_double_quoted_string(&mut self, unterminated_msg: &str) -> ast::Name { + fn scan_double_quoted_string(&mut self, unterminated_msg: &str) -> Symbol { debug_assert!(self.ch_is('\"')); let start_with_quote = self.pos; self.bump(); @@ -1226,7 +1225,7 @@ impl<'a> StringReader<'a> { } self.bump(); } - let id = self.name_from(start); + let id = self.symbol_from(start); self.bump(); id } From 390f717a0af5851271792da9ff235c95f3db2556 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Tue, 25 Jun 2019 22:59:00 +0200 Subject: [PATCH 9/9] tweak wording --- src/libstd/io/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 7fba844897ffe..3d0568c16cdf6 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -509,10 +509,10 @@ pub trait Read { /// contents of `buf` being true. It is recommended that *implementations* /// only write data to `buf` instead of reading its contents. /// - /// Correspondingly, however, *users* of this trait may not assume any guarantees + /// Correspondingly, however, *callers* of this method may not assume any guarantees /// about how the implementation uses `buf`. The trait is safe to implement, - /// so it is perfectly possible that the implementation might inspect that data. - /// As a caller, it is your responsibility to make sure that `buf` is initialized + // so it is possible that the code that's supposed to write to the buffer might also read + // from it. It is your responsibility to make sure that `buf` is initialized /// before calling `read`. Calling `read` with an uninitialized `buf` (of the kind one /// obtains via [`MaybeUninit<T>`]) is not safe, and can lead to undefined behavior. ///