Skip to content

Commit 66595ff

Browse files
bjorn3gitbot
authored and
gitbot
committed
Remove support for specializing ToString outside the standard library
This is the only trait specializable outside of the standard library. Before stabilizing specialization we will probably want to remove support for this. It was originally made specializable to allow a more efficient ToString in libproc_macro back when this way the only way to get any data out of a TokenStream. We now support getting individual tokens, so proc macros no longer need to call it as often.
1 parent c4a8ffe commit 66595ff

File tree

3 files changed

+43
-109
lines changed

3 files changed

+43
-109
lines changed

alloc/src/string.rs

+32-37
Original file line numberDiff line numberDiff line change
@@ -2675,12 +2675,25 @@ pub trait ToString {
26752675
#[cfg(not(no_global_oom_handling))]
26762676
#[stable(feature = "rust1", since = "1.0.0")]
26772677
impl<T: fmt::Display + ?Sized> ToString for T {
2678+
#[inline]
2679+
fn to_string(&self) -> String {
2680+
<Self as SpecToString>::spec_to_string(self)
2681+
}
2682+
}
2683+
2684+
#[cfg(not(no_global_oom_handling))]
2685+
trait SpecToString {
2686+
fn spec_to_string(&self) -> String;
2687+
}
2688+
2689+
#[cfg(not(no_global_oom_handling))]
2690+
impl<T: fmt::Display + ?Sized> SpecToString for T {
26782691
// A common guideline is to not inline generic functions. However,
26792692
// removing `#[inline]` from this method causes non-negligible regressions.
26802693
// See <https://github.com/rust-lang/rust/pull/74852>, the last attempt
26812694
// to try to remove it.
26822695
#[inline]
2683-
default fn to_string(&self) -> String {
2696+
default fn spec_to_string(&self) -> String {
26842697
let mut buf = String::new();
26852698
let mut formatter =
26862699
core::fmt::Formatter::new(&mut buf, core::fmt::FormattingOptions::new());
@@ -2691,42 +2704,34 @@ impl<T: fmt::Display + ?Sized> ToString for T {
26912704
}
26922705
}
26932706

2694-
#[doc(hidden)]
26952707
#[cfg(not(no_global_oom_handling))]
2696-
#[unstable(feature = "ascii_char", issue = "110998")]
2697-
impl ToString for core::ascii::Char {
2708+
impl SpecToString for core::ascii::Char {
26982709
#[inline]
2699-
fn to_string(&self) -> String {
2710+
fn spec_to_string(&self) -> String {
27002711
self.as_str().to_owned()
27012712
}
27022713
}
27032714

2704-
#[doc(hidden)]
27052715
#[cfg(not(no_global_oom_handling))]
2706-
#[stable(feature = "char_to_string_specialization", since = "1.46.0")]
2707-
impl ToString for char {
2716+
impl SpecToString for char {
27082717
#[inline]
2709-
fn to_string(&self) -> String {
2718+
fn spec_to_string(&self) -> String {
27102719
String::from(self.encode_utf8(&mut [0; 4]))
27112720
}
27122721
}
27132722

2714-
#[doc(hidden)]
27152723
#[cfg(not(no_global_oom_handling))]
2716-
#[stable(feature = "bool_to_string_specialization", since = "1.68.0")]
2717-
impl ToString for bool {
2724+
impl SpecToString for bool {
27182725
#[inline]
2719-
fn to_string(&self) -> String {
2726+
fn spec_to_string(&self) -> String {
27202727
String::from(if *self { "true" } else { "false" })
27212728
}
27222729
}
27232730

2724-
#[doc(hidden)]
27252731
#[cfg(not(no_global_oom_handling))]
2726-
#[stable(feature = "u8_to_string_specialization", since = "1.54.0")]
2727-
impl ToString for u8 {
2732+
impl SpecToString for u8 {
27282733
#[inline]
2729-
fn to_string(&self) -> String {
2734+
fn spec_to_string(&self) -> String {
27302735
let mut buf = String::with_capacity(3);
27312736
let mut n = *self;
27322737
if n >= 10 {
@@ -2742,12 +2747,10 @@ impl ToString for u8 {
27422747
}
27432748
}
27442749

2745-
#[doc(hidden)]
27462750
#[cfg(not(no_global_oom_handling))]
2747-
#[stable(feature = "i8_to_string_specialization", since = "1.54.0")]
2748-
impl ToString for i8 {
2751+
impl SpecToString for i8 {
27492752
#[inline]
2750-
fn to_string(&self) -> String {
2753+
fn spec_to_string(&self) -> String {
27512754
let mut buf = String::with_capacity(4);
27522755
if self.is_negative() {
27532756
buf.push('-');
@@ -2788,11 +2791,9 @@ macro_rules! to_string_expr_wrap_in_deref {
27882791
macro_rules! to_string_str {
27892792
{$($($x:ident)*),+} => {
27902793
$(
2791-
#[doc(hidden)]
2792-
#[stable(feature = "str_to_string_specialization", since = "1.9.0")]
2793-
impl ToString for to_string_str_wrap_in_ref!($($x)*) {
2794+
impl SpecToString for to_string_str_wrap_in_ref!($($x)*) {
27942795
#[inline]
2795-
fn to_string(&self) -> String {
2796+
fn spec_to_string(&self) -> String {
27962797
String::from(to_string_expr_wrap_in_deref!(self ; $($x)*))
27972798
}
27982799
}
@@ -2816,32 +2817,26 @@ to_string_str! {
28162817
x,
28172818
}
28182819

2819-
#[doc(hidden)]
28202820
#[cfg(not(no_global_oom_handling))]
2821-
#[stable(feature = "cow_str_to_string_specialization", since = "1.17.0")]
2822-
impl ToString for Cow<'_, str> {
2821+
impl SpecToString for Cow<'_, str> {
28232822
#[inline]
2824-
fn to_string(&self) -> String {
2823+
fn spec_to_string(&self) -> String {
28252824
self[..].to_owned()
28262825
}
28272826
}
28282827

2829-
#[doc(hidden)]
28302828
#[cfg(not(no_global_oom_handling))]
2831-
#[stable(feature = "string_to_string_specialization", since = "1.17.0")]
2832-
impl ToString for String {
2829+
impl SpecToString for String {
28332830
#[inline]
2834-
fn to_string(&self) -> String {
2831+
fn spec_to_string(&self) -> String {
28352832
self.to_owned()
28362833
}
28372834
}
28382835

2839-
#[doc(hidden)]
28402836
#[cfg(not(no_global_oom_handling))]
2841-
#[stable(feature = "fmt_arguments_to_string_specialization", since = "1.71.0")]
2842-
impl ToString for fmt::Arguments<'_> {
2837+
impl SpecToString for fmt::Arguments<'_> {
28432838
#[inline]
2844-
fn to_string(&self) -> String {
2839+
fn spec_to_string(&self) -> String {
28452840
crate::fmt::format(*self)
28462841
}
28472842
}

proc_macro/src/bridge/symbol.rs

-6
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,6 @@ impl fmt::Debug for Symbol {
9191
}
9292
}
9393

94-
impl ToString for Symbol {
95-
fn to_string(&self) -> String {
96-
self.with(|s| s.to_owned())
97-
}
98-
}
99-
10094
impl fmt::Display for Symbol {
10195
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10296
self.with(|s| fmt::Display::fmt(s, f))

proc_macro/src/lib.rs

+11-66
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@
1919
)]
2020
#![doc(rust_logo)]
2121
#![feature(rustdoc_internals)]
22-
// This library is copied into rust-analyzer to allow loading rustc compiled proc macros.
23-
// Please avoid unstable features where possible to minimize the amount of changes necessary
24-
// to make it compile with rust-analyzer on stable.
2522
#![feature(staged_api)]
2623
#![feature(allow_internal_unstable)]
2724
#![feature(decl_macro)]
@@ -30,7 +27,6 @@
3027
#![feature(panic_can_unwind)]
3128
#![feature(restricted_std)]
3229
#![feature(rustc_attrs)]
33-
#![feature(min_specialization)]
3430
#![feature(extend_one)]
3531
#![recursion_limit = "256"]
3632
#![allow(internal_features)]
@@ -185,16 +181,6 @@ impl FromStr for TokenStream {
185181
}
186182
}
187183

188-
// N.B., the bridge only provides `to_string`, implement `fmt::Display`
189-
// based on it (the reverse of the usual relationship between the two).
190-
#[doc(hidden)]
191-
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
192-
impl ToString for TokenStream {
193-
fn to_string(&self) -> String {
194-
self.0.as_ref().map(|t| t.to_string()).unwrap_or_default()
195-
}
196-
}
197-
198184
/// Prints the token stream as a string that is supposed to be losslessly convertible back
199185
/// into the same token stream (modulo spans), except for possibly `TokenTree::Group`s
200186
/// with `Delimiter::None` delimiters and negative numeric literals.
@@ -210,7 +196,10 @@ impl ToString for TokenStream {
210196
impl fmt::Display for TokenStream {
211197
#[allow(clippy::recursive_format_impl)] // clippy doesn't see the specialization
212198
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213-
f.write_str(&self.to_string())
199+
match &self.0 {
200+
Some(ts) => write!(f, "{}", ts.to_string()),
201+
None => Ok(()),
202+
}
214203
}
215204
}
216205

@@ -756,21 +745,6 @@ impl From<Literal> for TokenTree {
756745
}
757746
}
758747

759-
// N.B., the bridge only provides `to_string`, implement `fmt::Display`
760-
// based on it (the reverse of the usual relationship between the two).
761-
#[doc(hidden)]
762-
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
763-
impl ToString for TokenTree {
764-
fn to_string(&self) -> String {
765-
match *self {
766-
TokenTree::Group(ref t) => t.to_string(),
767-
TokenTree::Ident(ref t) => t.to_string(),
768-
TokenTree::Punct(ref t) => t.to_string(),
769-
TokenTree::Literal(ref t) => t.to_string(),
770-
}
771-
}
772-
}
773-
774748
/// Prints the token tree as a string that is supposed to be losslessly convertible back
775749
/// into the same token tree (modulo spans), except for possibly `TokenTree::Group`s
776750
/// with `Delimiter::None` delimiters and negative numeric literals.
@@ -786,7 +760,12 @@ impl ToString for TokenTree {
786760
impl fmt::Display for TokenTree {
787761
#[allow(clippy::recursive_format_impl)] // clippy doesn't see the specialization
788762
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
789-
f.write_str(&self.to_string())
763+
match self {
764+
TokenTree::Group(t) => write!(f, "{t}"),
765+
TokenTree::Ident(t) => write!(f, "{t}"),
766+
TokenTree::Punct(t) => write!(f, "{t}"),
767+
TokenTree::Literal(t) => write!(f, "{t}"),
768+
}
790769
}
791770
}
792771

@@ -912,24 +891,14 @@ impl Group {
912891
}
913892
}
914893

915-
// N.B., the bridge only provides `to_string`, implement `fmt::Display`
916-
// based on it (the reverse of the usual relationship between the two).
917-
#[doc(hidden)]
918-
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
919-
impl ToString for Group {
920-
fn to_string(&self) -> String {
921-
TokenStream::from(TokenTree::from(self.clone())).to_string()
922-
}
923-
}
924-
925894
/// Prints the group as a string that should be losslessly convertible back
926895
/// into the same group (modulo spans), except for possibly `TokenTree::Group`s
927896
/// with `Delimiter::None` delimiters.
928897
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
929898
impl fmt::Display for Group {
930899
#[allow(clippy::recursive_format_impl)] // clippy doesn't see the specialization
931900
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
932-
f.write_str(&self.to_string())
901+
write!(f, "{}", TokenStream::from(TokenTree::from(self.clone())))
933902
}
934903
}
935904

@@ -1035,14 +1004,6 @@ impl Punct {
10351004
}
10361005
}
10371006

1038-
#[doc(hidden)]
1039-
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
1040-
impl ToString for Punct {
1041-
fn to_string(&self) -> String {
1042-
self.as_char().to_string()
1043-
}
1044-
}
1045-
10461007
/// Prints the punctuation character as a string that should be losslessly convertible
10471008
/// back into the same character.
10481009
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
@@ -1138,14 +1099,6 @@ impl Ident {
11381099
}
11391100
}
11401101

1141-
#[doc(hidden)]
1142-
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
1143-
impl ToString for Ident {
1144-
fn to_string(&self) -> String {
1145-
self.0.sym.with(|sym| if self.0.is_raw { ["r#", sym].concat() } else { sym.to_owned() })
1146-
}
1147-
}
1148-
11491102
/// Prints the identifier as a string that should be losslessly convertible back
11501103
/// into the same identifier.
11511104
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
@@ -1520,14 +1473,6 @@ impl FromStr for Literal {
15201473
}
15211474
}
15221475

1523-
#[doc(hidden)]
1524-
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
1525-
impl ToString for Literal {
1526-
fn to_string(&self) -> String {
1527-
self.with_stringify_parts(|parts| parts.concat())
1528-
}
1529-
}
1530-
15311476
/// Prints the literal as a string that should be losslessly convertible
15321477
/// back into the same literal (except for possible rounding for floating point literals).
15331478
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]

0 commit comments

Comments
 (0)