From a99a7b7f35e3b30862058cc28ed4b0cf51638cf4 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 22 Jun 2019 06:59:27 +0200 Subject: [PATCH 01/16] Remove FnBox. --- .../src/language-features/unsized-locals.md | 4 +- .../src/library-features/fnbox.md | 32 -------- src/liballoc/boxed.rs | 79 ------------------- src/libstd/lib.rs | 1 - .../run-pass/unsized-locals/fnbox-compat.rs | 13 --- 5 files changed, 1 insertion(+), 128 deletions(-) delete mode 100644 src/doc/unstable-book/src/library-features/fnbox.md delete mode 100644 src/test/run-pass/unsized-locals/fnbox-compat.rs diff --git a/src/doc/unstable-book/src/language-features/unsized-locals.md b/src/doc/unstable-book/src/language-features/unsized-locals.md index edc039f896b2c..343084b7db501 100644 --- a/src/doc/unstable-book/src/language-features/unsized-locals.md +++ b/src/doc/unstable-book/src/language-features/unsized-locals.md @@ -117,9 +117,7 @@ fn main () { } ``` -One of the objectives of this feature is to allow `Box`, instead of `Box` in the future. See [#28796] for details. - -[#28796]: https://github.com/rust-lang/rust/issues/28796 +One of the objectives of this feature is to allow `Box`. ## Variable length arrays diff --git a/src/doc/unstable-book/src/library-features/fnbox.md b/src/doc/unstable-book/src/library-features/fnbox.md deleted file mode 100644 index 97e32cc0acb12..0000000000000 --- a/src/doc/unstable-book/src/library-features/fnbox.md +++ /dev/null @@ -1,32 +0,0 @@ -# `fnbox` - -The tracking issue for this feature is [#28796] - -[#28796]: https://github.com/rust-lang/rust/issues/28796 - ------------------------- - -This had been a temporary alternative to the following impls: - -```rust,ignore -impl FnOnce for Box where F: FnOnce + ?Sized {} -impl FnMut for Box where F: FnMut + ?Sized {} -impl Fn for Box where F: Fn + ?Sized {} -``` - -The impls are parallel to these (relatively old) impls: - -```rust,ignore -impl FnOnce for &mut F where F: FnMut + ?Sized {} -impl FnMut for &mut F where F: FnMut + ?Sized {} -impl Fn for &mut F where F: Fn + ?Sized {} -impl FnOnce for &F where F: Fn + ?Sized {} -impl FnMut for &F where F: Fn + ?Sized {} -impl Fn for &F where F: Fn + ?Sized {} -``` - -Before the introduction of [`unsized_locals`][unsized_locals], we had been unable to provide the former impls. That means, unlike `&dyn Fn()` or `&mut dyn FnMut()` we could not use `Box` at that time. - -[unsized_locals]: ../language-features/unsized-locals.md - -`FnBox()` is an alternative approach to `Box` is delegated to `FnBox::call_box` which doesn't need unsized locals. As we now have `Box` working, the `fnbox` feature is going to be removed. diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 76b660fba685c..9109a730cce2d 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -761,85 +761,6 @@ impl + ?Sized> Fn for Box { } } -/// `FnBox` is deprecated and will be removed. -/// `Box` can be called directly, since Rust 1.35.0. -/// -/// `FnBox` is a version of the `FnOnce` intended for use with boxed -/// closure objects. The idea was that where one would normally store a -/// `Box` in a data structure, you whould use -/// `Box`. The two traits behave essentially the same, except -/// that a `FnBox` closure can only be called if it is boxed. -/// -/// # Examples -/// -/// Here is a snippet of code which creates a hashmap full of boxed -/// once closures and then removes them one by one, calling each -/// closure as it is removed. Note that the type of the closures -/// stored in the map is `Box i32>` and not `Box i32>`. -/// -/// ``` -/// #![feature(fnbox)] -/// #![allow(deprecated)] -/// -/// use std::boxed::FnBox; -/// use std::collections::HashMap; -/// -/// fn make_map() -> HashMap i32>> { -/// let mut map: HashMap i32>> = HashMap::new(); -/// map.insert(1, Box::new(|| 22)); -/// map.insert(2, Box::new(|| 44)); -/// map -/// } -/// -/// fn main() { -/// let mut map = make_map(); -/// for i in &[1, 2] { -/// let f = map.remove(&i).unwrap(); -/// assert_eq!(f(), i * 22); -/// } -/// } -/// ``` -/// -/// In Rust 1.35.0 or later, use `FnOnce`, `FnMut`, or `Fn` instead: -/// -/// ``` -/// use std::collections::HashMap; -/// -/// fn make_map() -> HashMap i32>> { -/// let mut map: HashMap i32>> = HashMap::new(); -/// map.insert(1, Box::new(|| 22)); -/// map.insert(2, Box::new(|| 44)); -/// map -/// } -/// -/// fn main() { -/// let mut map = make_map(); -/// for i in &[1, 2] { -/// let f = map.remove(&i).unwrap(); -/// assert_eq!(f(), i * 22); -/// } -/// } -/// ``` -#[rustc_paren_sugar] -#[unstable(feature = "fnbox", issue = "28796")] -#[rustc_deprecated(reason = "use `FnOnce`, `FnMut`, or `Fn` instead", since = "1.37.0")] -pub trait FnBox: FnOnce { - /// Performs the call operation. - fn call_box(self: Box, args: A) -> Self::Output; -} - -#[unstable(feature = "fnbox", issue = "28796")] -#[rustc_deprecated(reason = "use `FnOnce`, `FnMut`, or `Fn` instead", since = "1.37.0")] -#[allow(deprecated, deprecated_in_future)] -impl FnBox for F - where F: FnOnce -{ - fn call_box(self: Box, args: A) -> F::Output { - self.call_once(args) - } -} - #[unstable(feature = "coerce_unsized", issue = "27732")] impl, U: ?Sized> CoerceUnsized> for Box {} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index e0ffc9ba92f11..60e06139eba99 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -262,7 +262,6 @@ #![feature(exhaustive_patterns)] #![feature(external_doc)] #![feature(fn_traits)] -#![feature(fnbox)] #![feature(generator_trait)] #![feature(hash_raw_entry)] #![feature(hashmap_internals)] diff --git a/src/test/run-pass/unsized-locals/fnbox-compat.rs b/src/test/run-pass/unsized-locals/fnbox-compat.rs deleted file mode 100644 index 74a4dd5d8515b..0000000000000 --- a/src/test/run-pass/unsized-locals/fnbox-compat.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![feature(fnbox)] -#![allow(deprecated, deprecated_in_future)] - -use std::boxed::FnBox; - -fn call_it(f: Box T>) -> T { - f() -} - -fn main() { - let s = "hello".to_owned(); - assert_eq!(&call_it(Box::new(|| s)) as &str, "hello"); -} From 1c12b1be330dd9c3de0b4fe599686d7c0c45e720 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 24 Jun 2019 22:58:53 +0200 Subject: [PATCH 02/16] 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`]) is not safe, and can lead to undefined behavior. + /// + /// [`MaybeUninit`]: ../mem/union.MaybeUninit.html + /// /// # Errors /// /// If this function encounters any form of I/O or other error, an error From bb26e07dd59088fc3a308ad7a56283ba4e53b5f8 Mon Sep 17 00:00:00 2001 From: Valentin Tolmer Date: Wed, 27 Feb 2019 17:10:59 +0100 Subject: [PATCH 03/16] Add debug assertions to write_bytes and copy* --- src/libcore/intrinsics.rs | 33 ++++++++++++++++++++++++++++++++- src/libcore/slice/mod.rs | 6 +++--- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index b30eff8baa9c8..93450cb4798a7 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -41,6 +41,8 @@ since = "1.18.0")] pub use crate::ptr::drop_in_place; +use crate::mem; + extern "rust-intrinsic" { // N.B., these intrinsics take raw pointers because they mutate aliased // memory, which is not valid for either `&` or `&mut`. @@ -1331,6 +1333,26 @@ extern "rust-intrinsic" { // (`transmute` also falls into this category, but it cannot be wrapped due to the // check that `T` and `U` have the same size.) +/// Checks whether `ptr` is properly aligned with respect to +/// `align_of::()`. +pub(crate) fn is_aligned_and_not_null(ptr: *const T) -> bool { + return !ptr.is_null() && ptr as usize % mem::align_of::() == 0; +} + +/// Checks whether the regions of memory starting at `src` and `dst` of size +/// `count * size_of::()` overlap. +fn overlaps(src: *const T, dst: *const T, count: usize) -> bool { + let src_usize = src as usize; + let dst_usize = dst as usize; + let size = mem::size_of::().checked_mul(count).unwrap(); + let diff = if src_usize > dst_usize { + src_usize - dst_usize + } else { + dst_usize - src_usize + }; + size > diff +} + /// Copies `count * size_of::()` bytes from `src` to `dst`. The source /// and destination must *not* overlap. /// @@ -1420,7 +1442,11 @@ pub unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); } - copy_nonoverlapping(src, dst, count); + + debug_assert!(is_aligned_and_not_null(src), "attempt to copy from unaligned or null pointer"); + debug_assert!(is_aligned_and_not_null(dst), "attempt to copy to unaligned or null pointer"); + debug_assert!(!overlaps(src, dst, count), "attempt to copy to overlapping memory"); + copy_nonoverlapping(src, dst, count) } /// Copies `count * size_of::()` bytes from `src` to `dst`. The source @@ -1480,6 +1506,9 @@ pub unsafe fn copy(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { fn copy(src: *const T, dst: *mut T, count: usize); } + + debug_assert!(is_aligned_and_not_null(src), "attempt to copy from unaligned or null pointer"); + debug_assert!(is_aligned_and_not_null(dst), "attempt to copy to unaligned or null pointer"); copy(src, dst, count) } @@ -1561,6 +1590,8 @@ pub unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { extern "rust-intrinsic" { fn write_bytes(dst: *mut T, val: u8, count: usize); } + + debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer"); write_bytes(dst, val, count) } diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index c6d44324ef5ee..dba9a1445e84c 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -25,7 +25,7 @@ use crate::cmp::Ordering::{self, Less, Equal, Greater}; use crate::cmp; use crate::fmt; -use crate::intrinsics::{assume, exact_div, unchecked_sub}; +use crate::intrinsics::{assume, exact_div, unchecked_sub, is_aligned_and_not_null}; use crate::isize; use crate::iter::*; use crate::ops::{FnMut, Try, self}; @@ -5213,7 +5213,7 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { - debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); + debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice"); debug_assert!(mem::size_of::().saturating_mul(len) <= isize::MAX as usize, "attempt to create slice covering half the address space"); &*ptr::slice_from_raw_parts(data, len) @@ -5234,7 +5234,7 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { - debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); + debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice"); debug_assert!(mem::size_of::().saturating_mul(len) <= isize::MAX as usize, "attempt to create slice covering half the address space"); &mut *ptr::slice_from_raw_parts_mut(data, len) From 0533f129ecfb54ecae7e329949d7b1572368d0ae Mon Sep 17 00:00:00 2001 From: Valentin Tolmer Date: Wed, 27 Mar 2019 15:57:14 +0100 Subject: [PATCH 04/16] Handle null from LLVMRustGetSectionName --- src/librustc_codegen_llvm/llvm/ffi.rs | 4 +++- src/librustc_codegen_llvm/metadata.rs | 11 +++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index a5c295cd4525c..708ba79ec3ab2 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -1736,7 +1736,9 @@ extern "C" { pub fn LLVMRustArchiveIteratorFree(AIR: &'a mut ArchiveIterator<'a>); pub fn LLVMRustDestroyArchive(AR: &'static mut Archive); - pub fn LLVMRustGetSectionName(SI: &SectionIterator<'_>, data: &mut *const c_char) -> size_t; + #[allow(improper_ctypes)] + pub fn LLVMRustGetSectionName(SI: &SectionIterator<'_>, + data: &mut Option>) -> size_t; #[allow(improper_ctypes)] pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString); diff --git a/src/librustc_codegen_llvm/metadata.rs b/src/librustc_codegen_llvm/metadata.rs index 7cf497cb5d036..9bddd29d2e88f 100644 --- a/src/librustc_codegen_llvm/metadata.rs +++ b/src/librustc_codegen_llvm/metadata.rs @@ -8,7 +8,6 @@ use rustc_data_structures::owning_ref::OwningRef; use rustc_codegen_ssa::METADATA_FILENAME; use std::path::Path; -use std::ptr; use std::slice; use rustc_fs_util::path_to_c_string; @@ -67,10 +66,14 @@ fn search_meta_section<'a>(of: &'a ObjectFile, unsafe { let si = mk_section_iter(of.llof); while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False { - let mut name_buf = ptr::null(); + let mut name_buf = None; let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf); - let name = slice::from_raw_parts(name_buf as *const u8, name_len as usize).to_vec(); - let name = String::from_utf8(name).unwrap(); + let name = name_buf.map_or( + "".to_string(), + |buf| String::from_utf8( + slice::from_raw_parts(buf.as_ptr() as *const u8, + name_len as usize) + .to_vec()).unwrap()); debug!("get_metadata_section: name {}", name); if read_metadata_section_name(target) == name { let cbuf = llvm::LLVMGetSectionContents(si.llsi); From 8a4573f841f219df32c97d25f400effee94e2474 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 24 Jun 2019 23:15:37 +0200 Subject: [PATCH 05/16] format a bit --- src/librustc_codegen_llvm/metadata.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_llvm/metadata.rs b/src/librustc_codegen_llvm/metadata.rs index 9bddd29d2e88f..42e91ef408f9d 100644 --- a/src/librustc_codegen_llvm/metadata.rs +++ b/src/librustc_codegen_llvm/metadata.rs @@ -69,11 +69,13 @@ fn search_meta_section<'a>(of: &'a ObjectFile, let mut name_buf = None; let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf); let name = name_buf.map_or( - "".to_string(), + String::new(), // we got a NULL ptr, ignore `name_len` |buf| String::from_utf8( slice::from_raw_parts(buf.as_ptr() as *const u8, name_len as usize) - .to_vec()).unwrap()); + .to_vec() + ).unwrap() + ); debug!("get_metadata_section: name {}", name); if read_metadata_section_name(target) == name { let cbuf = llvm::LLVMGetSectionContents(si.llsi); From 4159b27c61e991c0abe7e87ad381bd0c07077dfc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 24 Jun 2019 23:19:04 +0200 Subject: [PATCH 06/16] order things more traditionally --- src/libcore/intrinsics.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 93450cb4798a7..2d47f08d70154 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -36,13 +36,13 @@ issue = "0")] #![allow(missing_docs)] +use crate::mem; + #[stable(feature = "drop_in_place", since = "1.8.0")] #[rustc_deprecated(reason = "no longer an intrinsic - use `ptr::drop_in_place` directly", since = "1.18.0")] pub use crate::ptr::drop_in_place; -use crate::mem; - extern "rust-intrinsic" { // N.B., these intrinsics take raw pointers because they mutate aliased // memory, which is not valid for either `&` or `&mut`. From c877989655d151972cd6a9c60450951a2efa0513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 25 Jun 2019 04:00:03 +0200 Subject: [PATCH 07/16] 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 std::convert::AsRef for LocalInternedString where str: std::convert::AsRef { + #[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?= Date: Tue, 25 Jun 2019 01:41:16 +0200 Subject: [PATCH 08/16] 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::(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>(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::(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 a68afc56bdf61b2ddd4f38ba4e3cabd7a4399c9b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 25 Jun 2019 09:40:50 +0200 Subject: [PATCH 09/16] ignore some codegen tests in debug mode --- src/test/codegen/issue-45222.rs | 1 + src/test/codegen/issue-45466.rs | 1 + src/test/codegen/swap-small-types.rs | 1 + 3 files changed, 3 insertions(+) diff --git a/src/test/codegen/issue-45222.rs b/src/test/codegen/issue-45222.rs index da65f2dfca5d1..7f99ca724cf73 100644 --- a/src/test/codegen/issue-45222.rs +++ b/src/test/codegen/issue-45222.rs @@ -1,4 +1,5 @@ // compile-flags: -O +// ignore-debug: the debug assertions get in the way #![crate_type = "lib"] diff --git a/src/test/codegen/issue-45466.rs b/src/test/codegen/issue-45466.rs index 7d6e31cc740f5..c79542767774a 100644 --- a/src/test/codegen/issue-45466.rs +++ b/src/test/codegen/issue-45466.rs @@ -1,4 +1,5 @@ // compile-flags: -O +// ignore-debug: the debug assertions get in the way #![crate_type="rlib"] diff --git a/src/test/codegen/swap-small-types.rs b/src/test/codegen/swap-small-types.rs index c8466fed7d1bd..6205e6a6559c9 100644 --- a/src/test/codegen/swap-small-types.rs +++ b/src/test/codegen/swap-small-types.rs @@ -1,5 +1,6 @@ // compile-flags: -O // only-x86_64 +// ignore-debug: the debug assertions get in the way #![crate_type = "lib"] From d3e1bf96dacab3e5c7c86321eb79fc916b28db87 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 25 Jun 2019 09:42:25 +0200 Subject: [PATCH 10/16] nits --- src/libcore/intrinsics.rs | 2 +- src/librustc_codegen_llvm/metadata.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 2d47f08d70154..d9b68612785e9 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1336,7 +1336,7 @@ extern "rust-intrinsic" { /// Checks whether `ptr` is properly aligned with respect to /// `align_of::()`. pub(crate) fn is_aligned_and_not_null(ptr: *const T) -> bool { - return !ptr.is_null() && ptr as usize % mem::align_of::() == 0; + !ptr.is_null() && ptr as usize % mem::align_of::() == 0 } /// Checks whether the regions of memory starting at `src` and `dst` of size diff --git a/src/librustc_codegen_llvm/metadata.rs b/src/librustc_codegen_llvm/metadata.rs index 42e91ef408f9d..cd7255888118c 100644 --- a/src/librustc_codegen_llvm/metadata.rs +++ b/src/librustc_codegen_llvm/metadata.rs @@ -69,7 +69,7 @@ fn search_meta_section<'a>(of: &'a ObjectFile, let mut name_buf = None; let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf); let name = name_buf.map_or( - String::new(), // we got a NULL ptr, ignore `name_len` + String::new(), // We got a NULL ptr, ignore `name_len`. |buf| String::from_utf8( slice::from_raw_parts(buf.as_ptr() as *const u8, name_len as usize) From 85ea4a1bf4a05ff18d6634db35eb41c3a6bca637 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 25 Jun 2019 23:09:25 +0900 Subject: [PATCH 11/16] 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 Date: Tue, 25 Jun 2019 21:02:19 +0300 Subject: [PATCH 12/16] 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(&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(&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> { ") .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 Date: Sun, 23 Jun 2019 11:45:06 +0200 Subject: [PATCH 13/16] 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 Co-Authored-By: Jonas Schievink Co-Authored-By: Torbjørn Birch Moltu --- 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`.][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`.][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 Date: Mon, 24 Jun 2019 17:48:21 -0700 Subject: [PATCH 14/16] 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) {} + +async fn fut() {} + +async fn fut_arg(_: 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 {std::option::Option::::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option, 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 {std::option::Option::::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option, 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 {std::option::Option::::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option, 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) {} + +async fn fut() {} + +async fn fut_arg(_: 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() {} + +pub trait Foo { + fn foo(&self) {} +} + +struct FooType; +impl Foo for FooType {} + +pub async fn call_generic_bound(f: F) { + f.foo() +} + +pub async fn call_where_clause(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() -> impl Future { + async move {} +} + +pub fn call_generic_bound_block(f: F) -> impl Future { + async move { f.foo() } +} + +pub fn call_where_clause_block(f: F) -> impl Future +where + F: Foo, +{ + async move { f.foo() } +} + +pub fn call_impl_trait_block(f: impl Foo) -> impl Future { + async move { f.foo() } +} + +pub fn call_with_ref_block<'a>(f: &'a (impl Foo + 'a)) -> impl Future + '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 Date: Tue, 25 Jun 2019 21:37:25 +0300 Subject: [PATCH 15/16] 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 *, if possible. - fn scan_optional_raw_name(&mut self) -> Option { + fn scan_optional_raw_name(&mut self) -> Option { 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 Date: Tue, 25 Jun 2019 22:59:00 +0200 Subject: [PATCH 16/16] 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`]) is not safe, and can lead to undefined behavior. ///