Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hide ToString specializations behind a private trait #89253

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 34 additions & 19 deletions library/alloc/src/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2375,7 +2375,22 @@ impl<T: fmt::Display + ?Sized> ToString for T {
// See <https://github.com/rust-lang/rust/pull/74852>, the last attempt
// to try to remove it.
#[inline]
default fn to_string(&self) -> String {
fn to_string(&self) -> String {
SpecToString::spec_to_string(self)
}
}

#[unstable(issue = "none", feature = "spec_to_string")]
#[doc(hidden)]
pub trait SpecToString {
fn spec_to_string(&self) -> String;
}

#[cfg(not(no_global_oom_handling))]
#[unstable(issue = "none", feature = "spec_to_string")]
impl<T: fmt::Display + ?Sized> SpecToString for T {
#[inline]
default fn spec_to_string(&self) -> String {
let mut buf = String::new();
let mut formatter = core::fmt::Formatter::new(&mut buf);
// Bypass format_args!() to avoid write_str with zero-length strs
Expand All @@ -2386,19 +2401,19 @@ impl<T: fmt::Display + ?Sized> ToString for T {
}

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "char_to_string_specialization", since = "1.46.0")]
impl ToString for char {
#[unstable(issue = "none", feature = "spec_to_string")]
impl SpecToString for char {
#[inline]
fn to_string(&self) -> String {
fn spec_to_string(&self) -> String {
String::from(self.encode_utf8(&mut [0; 4]))
}
}

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "u8_to_string_specialization", since = "1.54.0")]
impl ToString for u8 {
#[unstable(issue = "none", feature = "spec_to_string")]
impl SpecToString for u8 {
#[inline]
fn to_string(&self) -> String {
fn spec_to_string(&self) -> String {
let mut buf = String::with_capacity(3);
let mut n = *self;
if n >= 10 {
Expand All @@ -2415,10 +2430,10 @@ impl ToString for u8 {
}

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "i8_to_string_specialization", since = "1.54.0")]
impl ToString for i8 {
#[unstable(issue = "none", feature = "spec_to_string")]
impl SpecToString for i8 {
#[inline]
fn to_string(&self) -> String {
fn spec_to_string(&self) -> String {
let mut buf = String::with_capacity(4);
if self.is_negative() {
buf.push('-');
Expand All @@ -2438,28 +2453,28 @@ impl ToString for i8 {
}

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "str_to_string_specialization", since = "1.9.0")]
impl ToString for str {
#[unstable(issue = "none", feature = "spec_to_string")]
impl SpecToString for str {
#[inline]
fn to_string(&self) -> String {
fn spec_to_string(&self) -> String {
String::from(self)
}
}

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "cow_str_to_string_specialization", since = "1.17.0")]
impl ToString for Cow<'_, str> {
#[unstable(issue = "none", feature = "spec_to_string")]
impl SpecToString for Cow<'_, str> {
#[inline]
fn to_string(&self) -> String {
fn spec_to_string(&self) -> String {
self[..].to_owned()
}
}

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "string_to_string_specialization", since = "1.17.0")]
impl ToString for String {
#[unstable(issue = "none", feature = "spec_to_string")]
impl SpecToString for String {
#[inline]
fn to_string(&self) -> String {
fn spec_to_string(&self) -> String {
self.to_owned()
}
}
Expand Down
40 changes: 21 additions & 19 deletions library/proc_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#![feature(restricted_std)]
#![feature(rustc_attrs)]
#![feature(min_specialization)]
#![feature(spec_to_string)]
#![recursion_limit = "256"]

#[unstable(feature = "proc_macro_internals", issue = "27812")]
Expand All @@ -46,6 +47,7 @@ use std::cmp::Ordering;
use std::ops::RangeBounds;
use std::path::PathBuf;
use std::str::FromStr;
use std::string::SpecToString;
use std::{error, fmt, iter, mem};

/// Determines whether proc_macro has been made accessible to the currently
Expand Down Expand Up @@ -141,9 +143,9 @@ impl FromStr for TokenStream {

// 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")]
impl ToString for TokenStream {
fn to_string(&self) -> String {
#[unstable(issue = "none", feature = "spec_to_string")]
impl SpecToString for TokenStream {
fn spec_to_string(&self) -> String {
self.0.to_string()
}
}
Expand Down Expand Up @@ -624,9 +626,9 @@ impl From<Literal> for TokenTree {

// 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")]
impl ToString for TokenTree {
fn to_string(&self) -> String {
#[unstable(issue = "none", feature = "spec_to_string")]
impl SpecToString for TokenTree {
fn spec_to_string(&self) -> String {
match *self {
TokenTree::Group(ref t) => t.to_string(),
TokenTree::Ident(ref t) => t.to_string(),
Expand Down Expand Up @@ -754,9 +756,9 @@ impl Group {

// 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")]
impl ToString for Group {
fn to_string(&self) -> String {
#[unstable(issue = "none", feature = "spec_to_string")]
impl SpecToString for Group {
fn spec_to_string(&self) -> String {
TokenStream::from(TokenTree::from(self.clone())).to_string()
}
}
Expand Down Expand Up @@ -854,9 +856,9 @@ impl Punct {

// 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")]
impl ToString for Punct {
fn to_string(&self) -> String {
#[unstable(issue = "none", feature = "spec_to_string")]
impl SpecToString for Punct {
fn spec_to_string(&self) -> String {
TokenStream::from(TokenTree::from(self.clone())).to_string()
}
}
Expand Down Expand Up @@ -935,7 +937,7 @@ impl Ident {
}

/// Returns the span of this `Ident`, encompassing the entire string returned
/// by [`to_string`](Self::to_string).
/// by [`to_string`](ToString::to_string).
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn span(&self) -> Span {
Span(self.0.span())
Expand All @@ -950,9 +952,9 @@ impl Ident {

// 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")]
impl ToString for Ident {
fn to_string(&self) -> String {
#[unstable(issue = "none", feature = "spec_to_string")]
impl SpecToString for Ident {
fn spec_to_string(&self) -> String {
TokenStream::from(TokenTree::from(self.clone())).to_string()
}
}
Expand Down Expand Up @@ -1210,9 +1212,9 @@ impl FromStr for Literal {

// 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")]
impl ToString for Literal {
fn to_string(&self) -> String {
#[unstable(issue = "none", feature = "spec_to_string")]
impl SpecToString for Literal {
fn spec_to_string(&self) -> String {
self.0.to_string()
}
}
Expand Down