From 67e8f1230745785bc08ec4d3d882f61b1d3516af Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Fri, 14 May 2021 13:28:56 +0100 Subject: [PATCH 01/13] Expose `Concurrent` (private type in public i'face) --- library/test/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 9adc099aaa5..bda5ed888d7 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -49,7 +49,7 @@ pub mod test { cli::{parse_opts, TestOpts}, filter_tests, helpers::metrics::{Metric, MetricMap}, - options::{Options, RunIgnored, RunStrategy, ShouldPanic}, + options::{Concurrent, Options, RunIgnored, RunStrategy, ShouldPanic}, run_test, test_main, test_main_static, test_result::{TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk}, time::{TestExecTime, TestTimeOptions}, From 196050305c6f34aa3c945b1b07935c101f1a6755 Mon Sep 17 00:00:00 2001 From: Satyarth Agrahari Date: Sat, 15 May 2021 10:50:02 +0530 Subject: [PATCH 02/13] adding time complexity for partition_in_place iter method --- library/core/src/iter/traits/iterator.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index da9e5fde7cc..43d60a4ed76 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1849,6 +1849,8 @@ pub trait Iterator { /// /// The relative order of partitioned items is not maintained. /// + /// Time Complexity: *O*(*N*) + /// /// See also [`is_partitioned()`] and [`partition()`]. /// /// [`is_partitioned()`]: Iterator::is_partitioned From 85e417718403cc0a8b058585fb8633b4698ea3e2 Mon Sep 17 00:00:00 2001 From: Satyarth Agrahari Date: Tue, 18 May 2021 07:59:16 +0530 Subject: [PATCH 03/13] adding algorithm explanation for partition_in_place iter method and bounding complexity to current implementation --- library/core/src/iter/traits/iterator.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 43d60a4ed76..7ba2dfc9941 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1849,6 +1849,10 @@ pub trait Iterator { /// /// The relative order of partitioned items is not maintained. /// + /// # Current implementation + /// Current algorithms tries finding the first element for which the predicate evaluates + /// to false, and the last element for which it evaluates to true and repeatedly swaps them. + /// /// Time Complexity: *O*(*N*) /// /// See also [`is_partitioned()`] and [`partition()`]. From d730cc66460c1cad2f7c5d1951a06666bb8b78de Mon Sep 17 00:00:00 2001 From: Mateusz Gacek <96mateusz.gacek@gmail.com> Date: Tue, 18 May 2021 15:33:38 +0200 Subject: [PATCH 04/13] Add diagnostic item to `CStr` --- compiler/rustc_span/src/symbol.rs | 1 + library/std/src/ffi/c_str.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 03a8f2be156..a5dc6785488 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -131,6 +131,7 @@ symbols! { BinaryHeap, Borrow, C, + CStr, CString, Center, Clone, diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index 2f9845d7536..302f12af6a0 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -185,6 +185,7 @@ pub struct CString { /// /// [`&str`]: prim@str #[derive(Hash)] +#[cfg_attr(not(test), rustc_diagnostic_item = "CStr")] #[stable(feature = "rust1", since = "1.0.0")] // FIXME: // `fn from` in `impl From<&CStr> for Box` current implementation relies From 24480ded58c9867439cfabba4198e1877c1fd166 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Mon, 10 May 2021 16:41:41 -0700 Subject: [PATCH 05/13] Add method-toggle to
for methods. The makes the code for handling "auto-hide" settings more consistent. --- src/librustdoc/html/render/mod.rs | 9 ++++++--- src/librustdoc/html/static/main.js | 16 ++++------------ 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index a288b43722a..318e1b44f86 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1352,8 +1352,11 @@ fn render_impl( } let w = if short_documented && trait_.is_some() { interesting } else { boring }; - if !doc_buffer.is_empty() { - w.write_str("
"); + let toggled = !doc_buffer.is_empty(); + if toggled { + let method_toggle_class = + if item_type == ItemType::Method { " method-toggle" } else { "" }; + write!(w, "
", method_toggle_class); } match *item.kind { clean::MethodItem(..) | clean::TyMethodItem(_) => { @@ -1453,7 +1456,7 @@ fn render_impl( } w.push_buffer(info_buffer); - if !doc_buffer.is_empty() { + if toggled { w.write_str(""); w.push_buffer(doc_buffer); w.push_str("
"); diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 307ce9ac375..83e6a529b0a 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -924,24 +924,16 @@ function hideThemeButtonState() { }); } - if (hideMethodDocs) { - onEachLazy(document.getElementsByClassName("method"), function(e) { - var toggle = e.parentNode; - if (toggle) { - toggle = toggle.parentNode; - } - if (toggle && toggle.tagName === "DETAILS") { - toggle.open = false; - } - }); - } - onEachLazy(document.getElementsByTagName("details"), function (e) { var showLargeItem = !hideLargeItemContents && hasClass(e, "type-contents-toggle"); var showImplementor = !hideImplementors && hasClass(e, "implementors-toggle"); if (showLargeItem || showImplementor) { e.open = true; } + if (hideMethodDocs && hasClass(e, "method-toggle")) { + e.open = false; + } + }); var currentType = document.getElementsByClassName("type-decl")[0]; From f9752b493086fd3063c9aef83d2622d322bbc51c Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Wed, 19 May 2021 12:33:10 +0200 Subject: [PATCH 06/13] Fix UB in documented example for `ptr::swap` --- library/core/src/ptr/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 2c324b15a1a..214d7c8bc15 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -342,10 +342,12 @@ pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { /// ``` /// use std::ptr; /// -/// let mut array = [0, 1, 2, 3]; +/// let mut array: [i32; 4] = [0, 1, 2, 3]; /// -/// let x = array[0..].as_mut_ptr() as *mut [u32; 3]; // this is `array[0..3]` -/// let y = array[1..].as_mut_ptr() as *mut [u32; 3]; // this is `array[1..4]` +/// let array_ptr: *mut i32 = array.as_mut_ptr(); +/// +/// let x = array_ptr as *mut [i32; 3]; // this is `array[0..3]` +/// let y = unsafe { array_ptr.add(1) } as *mut [i32; 3]; // this is `array[1..4]` /// /// unsafe { /// ptr::swap(x, y); From ec32bcf3fdb4fd3e36a48a5e9c11df0f3f7cd222 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 19 May 2021 15:37:10 +0200 Subject: [PATCH 07/13] Fix invalid CSS rules for a:hover --- src/librustdoc/html/static/themes/ayu.css | 7 ++----- src/librustdoc/html/static/themes/dark.css | 4 ++-- src/librustdoc/html/static/themes/light.css | 4 ++-- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css index 989ea7140c5..e59909ffdf0 100644 --- a/src/librustdoc/html/static/themes/ayu.css +++ b/src/librustdoc/html/static/themes/ayu.css @@ -151,17 +151,14 @@ pre, .rustdoc.source .example-wrap { color: #c5c5c5; } -.content a:hover { +.search-results a:hover { background-color: #777; } -.content a:focus { +.search-results a:focus { color: #000 !important; background-color: #c6afb3; } -.content a:focus { - color: #000 !important; -} .search-results a { color: #0096cf; } diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index e6bd16ddd11..a2bcb43f44e 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -109,11 +109,11 @@ pre, .rustdoc.source .example-wrap { color: #ddd; } -.content a:hover { +.search-results a:hover { background-color: #777; } -.content a:focus { +.search-results a:focus { color: #eee !important; background-color: #616161; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 5481b348aa2..2ad3551d900 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -109,11 +109,11 @@ pre, .rustdoc.source .example-wrap { color: #4E4C4C; } -.content a:hover { +.search-results a:hover { background-color: #ddd; } -.content a:focus { +.search-results a:focus { color: #000 !important; background-color: #ccc; } From 50a9f008f266bc7e81926309e3a0a2e36860a305 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 19 May 2021 16:37:17 +0200 Subject: [PATCH 08/13] CTFE Machine: do not expose Allocation --- compiler/rustc_mir/src/interpret/machine.rs | 7 ++++--- compiler/rustc_mir/src/interpret/memory.rs | 13 +++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_mir/src/interpret/machine.rs b/compiler/rustc_mir/src/interpret/machine.rs index e6b3b1daf5a..e7d7c38cc8f 100644 --- a/compiler/rustc_mir/src/interpret/machine.rs +++ b/compiler/rustc_mir/src/interpret/machine.rs @@ -313,7 +313,7 @@ pub trait Machine<'mir, 'tcx>: Sized { #[inline(always)] fn memory_read( _memory_extra: &Self::MemoryExtra, - _alloc: &Allocation, + _alloc_extra: &Self::AllocExtra, _ptr: Pointer, _size: Size, ) -> InterpResult<'tcx> { @@ -324,7 +324,7 @@ pub trait Machine<'mir, 'tcx>: Sized { #[inline(always)] fn memory_written( _memory_extra: &mut Self::MemoryExtra, - _alloc: &mut Allocation, + _alloc_extra: &mut Self::AllocExtra, _ptr: Pointer, _size: Size, ) -> InterpResult<'tcx> { @@ -335,8 +335,9 @@ pub trait Machine<'mir, 'tcx>: Sized { #[inline(always)] fn memory_deallocated( _memory_extra: &mut Self::MemoryExtra, - _alloc: &mut Allocation, + _alloc_extra: &mut Self::AllocExtra, _ptr: Pointer, + _size: Size, ) -> InterpResult<'tcx> { Ok(()) } diff --git a/compiler/rustc_mir/src/interpret/memory.rs b/compiler/rustc_mir/src/interpret/memory.rs index 37aaa834aff..7fb7c51b0b5 100644 --- a/compiler/rustc_mir/src/interpret/memory.rs +++ b/compiler/rustc_mir/src/interpret/memory.rs @@ -343,10 +343,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } // Let the machine take some extra action - M::memory_deallocated(&mut self.extra, &mut alloc, ptr)?; + let size = alloc.size(); + M::memory_deallocated(&mut self.extra, &mut alloc.extra, ptr, size)?; // Don't forget to remember size and align of this now-dead allocation - let old = self.dead_alloc_map.insert(ptr.alloc_id, (alloc.size(), alloc.align)); + let old = self.dead_alloc_map.insert(ptr.alloc_id, (size, alloc.align)); if old.is_some() { bug!("Nothing can be deallocated twice"); } @@ -591,7 +592,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { }, )?; if let Some((ptr, alloc)) = ptr_and_alloc { - M::memory_read(&self.extra, alloc, ptr, size)?; + M::memory_read(&self.extra, &alloc.extra, ptr, size)?; let range = alloc_range(ptr.offset, size); Ok(Some(AllocRef { alloc, range, tcx: self.tcx, alloc_id: ptr.alloc_id })) } else { @@ -660,7 +661,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // FIXME: can we somehow avoid looking up the allocation twice here? // We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`. let (alloc, extra) = self.get_raw_mut(ptr.alloc_id)?; - M::memory_written(extra, alloc, ptr, size)?; + M::memory_written(extra, &mut alloc.extra, ptr, size)?; let range = alloc_range(ptr.offset, size); Ok(Some(AllocRefMut { alloc, range, tcx, alloc_id: ptr.alloc_id })) } else { @@ -1029,7 +1030,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { Some(src_ptr) => src_ptr, }; let src_alloc = self.get_raw(src.alloc_id)?; - M::memory_read(&self.extra, src_alloc, src, size)?; + M::memory_read(&self.extra, &src_alloc.extra, src, size)?; // We need the `dest` ptr for the next operation, so we get it now. // We already did the source checks and called the hooks so we are good to return early. let dest = match dest { @@ -1058,7 +1059,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // Destination alloc preparations and access hooks. let (dest_alloc, extra) = self.get_raw_mut(dest.alloc_id)?; - M::memory_written(extra, dest_alloc, dest, size * num_copies)?; + M::memory_written(extra, &mut dest_alloc.extra, dest, size * num_copies)?; let dest_bytes = dest_alloc .get_bytes_mut_ptr(&tcx, alloc_range(dest.offset, size * num_copies)) .as_mut_ptr(); From 39441bb2c1030884d0f1d200de0a65b146ba6b6d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 29 Apr 2021 11:10:14 -0700 Subject: [PATCH 09/13] Make a ui test to take the role of libproc_macro #[test] tests --- src/test/ui/proc-macro/auxiliary/api/mod.rs | 16 ++++++++++++++++ src/test/ui/proc-macro/test.rs | 12 ++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/test/ui/proc-macro/auxiliary/api/mod.rs create mode 100644 src/test/ui/proc-macro/test.rs diff --git a/src/test/ui/proc-macro/auxiliary/api/mod.rs b/src/test/ui/proc-macro/auxiliary/api/mod.rs new file mode 100644 index 00000000000..72b02ad554e --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/api/mod.rs @@ -0,0 +1,16 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![crate_name = "proc_macro_api_tests"] +#![deny(dead_code)] // catch if a test function is never called + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn run(input: TokenStream) -> TokenStream { + assert!(input.is_empty()); + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/test.rs b/src/test/ui/proc-macro/test.rs new file mode 100644 index 00000000000..c96aa73175f --- /dev/null +++ b/src/test/ui/proc-macro/test.rs @@ -0,0 +1,12 @@ +// check-pass +// aux-build:api/mod.rs + +//! This is for everything that *would* be a #[test] inside of libproc_macro, +//! except for the fact that proc_macro objects are not capable of existing +//! inside of an ordinary Rust test execution, only inside a macro. + +extern crate proc_macro_api_tests; + +proc_macro_api_tests::run!(); + +fn main() {} From 3c16c0e1df61755db2267897392529eb9451aa62 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 29 Apr 2021 11:17:44 -0700 Subject: [PATCH 10/13] Move proc_macro tests to ui test --- .../test/ui/proc-macro/auxiliary/api/cmp.rs | 9 +++++---- src/test/ui/proc-macro/auxiliary/api/mod.rs | 4 ++++ 2 files changed, 9 insertions(+), 4 deletions(-) rename library/proc_macro/tests/test.rs => src/test/ui/proc-macro/auxiliary/api/cmp.rs (88%) diff --git a/library/proc_macro/tests/test.rs b/src/test/ui/proc-macro/auxiliary/api/cmp.rs similarity index 88% rename from library/proc_macro/tests/test.rs rename to src/test/ui/proc-macro/auxiliary/api/cmp.rs index d2e6b0bb809..3d17e9e350e 100644 --- a/library/proc_macro/tests/test.rs +++ b/src/test/ui/proc-macro/auxiliary/api/cmp.rs @@ -1,8 +1,10 @@ -#![feature(proc_macro_span)] - use proc_macro::{LineColumn, Punct}; -#[test] +pub fn test() { + test_line_column_ord(); + test_punct_eq(); +} + fn test_line_column_ord() { let line0_column0 = LineColumn { line: 0, column: 0 }; let line0_column1 = LineColumn { line: 0, column: 1 }; @@ -11,7 +13,6 @@ fn test_line_column_ord() { assert!(line0_column1 < line1_column0); } -#[test] fn test_punct_eq() { // Good enough if it typechecks, since proc_macro::Punct can't exist in a test. fn _check(punct: Punct) { diff --git a/src/test/ui/proc-macro/auxiliary/api/mod.rs b/src/test/ui/proc-macro/auxiliary/api/mod.rs index 72b02ad554e..019fb2e7ec8 100644 --- a/src/test/ui/proc-macro/auxiliary/api/mod.rs +++ b/src/test/ui/proc-macro/auxiliary/api/mod.rs @@ -3,14 +3,18 @@ #![crate_type = "proc-macro"] #![crate_name = "proc_macro_api_tests"] +#![feature(proc_macro_span)] #![deny(dead_code)] // catch if a test function is never called extern crate proc_macro; +mod cmp; + use proc_macro::TokenStream; #[proc_macro] pub fn run(input: TokenStream) -> TokenStream { assert!(input.is_empty()); + cmp::test(); TokenStream::new() } From faad7e209deee6d09d335ca00c06d9f41bc040b5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 29 Apr 2021 11:20:27 -0700 Subject: [PATCH 11/13] Make a more meaningful test for Punct eq --- src/test/ui/proc-macro/auxiliary/api/cmp.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/ui/proc-macro/auxiliary/api/cmp.rs b/src/test/ui/proc-macro/auxiliary/api/cmp.rs index 3d17e9e350e..5784a6e5d94 100644 --- a/src/test/ui/proc-macro/auxiliary/api/cmp.rs +++ b/src/test/ui/proc-macro/auxiliary/api/cmp.rs @@ -1,4 +1,4 @@ -use proc_macro::{LineColumn, Punct}; +use proc_macro::{LineColumn, Punct, Spacing}; pub fn test() { test_line_column_ord(); @@ -14,8 +14,8 @@ fn test_line_column_ord() { } fn test_punct_eq() { - // Good enough if it typechecks, since proc_macro::Punct can't exist in a test. - fn _check(punct: Punct) { - let _ = punct == ':'; - } + let colon_alone = Punct::new(':', Spacing::Alone); + assert_eq!(colon_alone, ':'); + let colon_joint = Punct::new(':', Spacing::Joint); + assert_eq!(colon_joint, ':'); } From 965bce48348bbcc3c86898bdb5e18d4c57c35d00 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 29 Apr 2021 12:03:35 -0700 Subject: [PATCH 12/13] Add proc macro Literal parse test --- src/test/ui/proc-macro/auxiliary/api/mod.rs | 4 ++++ src/test/ui/proc-macro/auxiliary/api/parse.rs | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/test/ui/proc-macro/auxiliary/api/parse.rs diff --git a/src/test/ui/proc-macro/auxiliary/api/mod.rs b/src/test/ui/proc-macro/auxiliary/api/mod.rs index 019fb2e7ec8..739c25132e7 100644 --- a/src/test/ui/proc-macro/auxiliary/api/mod.rs +++ b/src/test/ui/proc-macro/auxiliary/api/mod.rs @@ -9,12 +9,16 @@ extern crate proc_macro; mod cmp; +mod parse; use proc_macro::TokenStream; #[proc_macro] pub fn run(input: TokenStream) -> TokenStream { assert!(input.is_empty()); + cmp::test(); + parse::test(); + TokenStream::new() } diff --git a/src/test/ui/proc-macro/auxiliary/api/parse.rs b/src/test/ui/proc-macro/auxiliary/api/parse.rs new file mode 100644 index 00000000000..4105236b7f2 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/api/parse.rs @@ -0,0 +1,23 @@ +use proc_macro::Literal; + +pub fn test() { + test_parse_literal(); +} + +fn test_parse_literal() { + assert_eq!("1".parse::().unwrap().to_string(), "1"); + assert_eq!("1.0".parse::().unwrap().to_string(), "1.0"); + assert_eq!("'a'".parse::().unwrap().to_string(), "'a'"); + assert_eq!("\"\n\"".parse::().unwrap().to_string(), "\"\n\""); + assert_eq!("b\"\"".parse::().unwrap().to_string(), "b\"\""); + assert_eq!("r##\"\"##".parse::().unwrap().to_string(), "r##\"\"##"); + assert_eq!("10ulong".parse::().unwrap().to_string(), "10ulong"); + + assert!("0 1".parse::().is_err()); + assert!("'a".parse::().is_err()); + assert!(" 0".parse::().is_err()); + assert!("0 ".parse::().is_err()); + assert!("/* comment */0".parse::().is_err()); + assert!("0/* comment */".parse::().is_err()); + assert!("0// comment".parse::().is_err()); +} From 34585cb678bc492be7e48ff48a2633f4ce1dc5ae Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 29 Apr 2021 12:08:35 -0700 Subject: [PATCH 13/13] impl FromStr for proc_macro::Literal --- .../rustc_expand/src/proc_macro_server.rs | 31 +++++++++++++++++-- library/proc_macro/src/bridge/mod.rs | 14 +++++++++ library/proc_macro/src/lib.rs | 28 +++++++++++++++++ 3 files changed, 70 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 7bf6502c976..92315c4d4f6 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -1,9 +1,7 @@ use crate::base::{ExtCtxt, ResolverExpand}; use rustc_ast as ast; -use rustc_ast::token; -use rustc_ast::token::Nonterminal; -use rustc_ast::token::NtIdent; +use rustc_ast::token::{self, Nonterminal, NtIdent, TokenKind}; use rustc_ast::tokenstream::{self, CanSynthesizeMissingTokens}; use rustc_ast::tokenstream::{DelimSpan, Spacing::*, TokenStream, TreeAndSpacing}; use rustc_ast_pretty::pprust; @@ -541,6 +539,33 @@ impl server::Ident for Rustc<'_> { } impl server::Literal for Rustc<'_> { + fn from_str(&mut self, s: &str) -> Result { + let override_span = None; + let stream = parse_stream_from_source_str( + FileName::proc_macro_source_code(s), + s.to_owned(), + self.sess, + override_span, + ); + if stream.len() != 1 { + return Err(()); + } + let tree = stream.into_trees().next().unwrap(); + let token = match tree { + tokenstream::TokenTree::Token(token) => token, + tokenstream::TokenTree::Delimited { .. } => return Err(()), + }; + let span_data = token.span.data(); + if (span_data.hi.0 - span_data.lo.0) as usize != s.len() { + // There is a comment or whitespace adjacent to the literal. + return Err(()); + } + let lit = match token.kind { + TokenKind::Literal(lit) => lit, + _ => return Err(()), + }; + Ok(Literal { lit, span: self.call_site }) + } fn debug_kind(&mut self, literal: &Self::Literal) -> String { format!("{:?}", literal.lit.kind) } diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 355ad1f9f88..a2953b68564 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -107,6 +107,7 @@ macro_rules! with_api { Literal { fn drop($self: $S::Literal); fn clone($self: &$S::Literal) -> $S::Literal; + fn from_str(s: &str) -> Result<$S::Literal, ()>; fn debug_kind($self: &$S::Literal) -> String; fn symbol($self: &$S::Literal) -> String; fn suffix($self: &$S::Literal) -> Option; @@ -315,6 +316,19 @@ impl Unmark for Option { } } +impl Mark for Result { + type Unmarked = Result; + fn mark(unmarked: Self::Unmarked) -> Self { + unmarked.map(T::mark).map_err(E::mark) + } +} +impl Unmark for Result { + type Unmarked = Result; + fn unmark(self) -> Self::Unmarked { + self.map(T::unmark).map_err(E::unmark) + } +} + macro_rules! mark_noop { ($($ty:ty),* $(,)?) => { $( diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 525fd0fbe34..281999fe715 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -91,6 +91,12 @@ pub struct LexError { _inner: (), } +impl LexError { + fn new() -> Self { + LexError { _inner: () } + } +} + #[stable(feature = "proc_macro_lexerror_impls", since = "1.44.0")] impl fmt::Display for LexError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -1171,6 +1177,28 @@ impl Literal { } } +/// Parse a single literal from its stringified representation. +/// +/// In order to parse successfully, the input string must not contain anything +/// but the literal token. Specifically, it must not contain whitespace or +/// comments in addition to the literal. +/// +/// The resulting literal token will have a `Span::call_site()` span. +/// +/// NOTE: some errors may cause panics instead of returning `LexError`. We +/// reserve the right to change these errors into `LexError`s later. +#[stable(feature = "proc_macro_literal_parse", since = "1.54.0")] +impl FromStr for Literal { + type Err = LexError; + + fn from_str(src: &str) -> Result { + match bridge::client::Literal::from_str(src) { + Ok(literal) => Ok(Literal(literal)), + Err(()) => Err(LexError::new()), + } + } +} + // N.B., the bridge only provides `to_string`, implement `fmt::Display` // based on it (the reverse of the usual relationship between the two). #[stable(feature = "proc_macro_lib", since = "1.15.0")]