Skip to content

Commit 0f8b644

Browse files
authored
Unrolled build for rust-lang#128759
Rollup merge of rust-lang#128759 - notriddle:notriddle/spec-to-string, r=workingjubilee,compiler-errors alloc: add ToString specialization for `&&str` Fixes rust-lang#128690
2 parents e9c965d + c6fb0f3 commit 0f8b644

File tree

5 files changed

+112
-16
lines changed

5 files changed

+112
-16
lines changed

compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs

+22-9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use rustc_hir as hir;
44
use rustc_hir::def::DefKind;
55
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
66
use rustc_middle::ty::error::{ExpectedFound, TypeError};
7+
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
78
use rustc_middle::ty::print::{FmtPrinter, Printer};
89
use rustc_middle::ty::{self, suggest_constraining_type_param, Ty};
910
use rustc_span::def_id::DefId;
@@ -313,11 +314,15 @@ impl<T> Trait<T> for X {
313314
(ty::Dynamic(t, _, ty::DynKind::Dyn), _)
314315
if let Some(def_id) = t.principal_def_id() =>
315316
{
316-
let mut impl_def_ids = vec![];
317+
let mut has_matching_impl = false;
317318
tcx.for_each_relevant_impl(def_id, values.found, |did| {
318-
impl_def_ids.push(did)
319+
if DeepRejectCtxt::new(tcx, TreatParams::ForLookup)
320+
.types_may_unify(values.found, tcx.type_of(did).skip_binder())
321+
{
322+
has_matching_impl = true;
323+
}
319324
});
320-
if let [_] = &impl_def_ids[..] {
325+
if has_matching_impl {
321326
let trait_name = tcx.item_name(def_id);
322327
diag.help(format!(
323328
"`{}` implements `{trait_name}` so you could box the found value \
@@ -330,11 +335,15 @@ impl<T> Trait<T> for X {
330335
(_, ty::Dynamic(t, _, ty::DynKind::Dyn))
331336
if let Some(def_id) = t.principal_def_id() =>
332337
{
333-
let mut impl_def_ids = vec![];
338+
let mut has_matching_impl = false;
334339
tcx.for_each_relevant_impl(def_id, values.expected, |did| {
335-
impl_def_ids.push(did)
340+
if DeepRejectCtxt::new(tcx, TreatParams::ForLookup)
341+
.types_may_unify(values.expected, tcx.type_of(did).skip_binder())
342+
{
343+
has_matching_impl = true;
344+
}
336345
});
337-
if let [_] = &impl_def_ids[..] {
346+
if has_matching_impl {
338347
let trait_name = tcx.item_name(def_id);
339348
diag.help(format!(
340349
"`{}` implements `{trait_name}` so you could change the expected \
@@ -346,11 +355,15 @@ impl<T> Trait<T> for X {
346355
(ty::Dynamic(t, _, ty::DynKind::DynStar), _)
347356
if let Some(def_id) = t.principal_def_id() =>
348357
{
349-
let mut impl_def_ids = vec![];
358+
let mut has_matching_impl = false;
350359
tcx.for_each_relevant_impl(def_id, values.found, |did| {
351-
impl_def_ids.push(did)
360+
if DeepRejectCtxt::new(tcx, TreatParams::ForLookup)
361+
.types_may_unify(values.found, tcx.type_of(did).skip_binder())
362+
{
363+
has_matching_impl = true;
364+
}
352365
});
353-
if let [_] = &impl_def_ids[..] {
366+
if has_matching_impl {
354367
let trait_name = tcx.item_name(def_id);
355368
diag.help(format!(
356369
"`{}` implements `{trait_name}`, `#[feature(dyn_star)]` is likely \

library/alloc/src/string.rs

+47-7
Original file line numberDiff line numberDiff line change
@@ -2643,14 +2643,54 @@ impl ToString for i8 {
26432643
}
26442644
}
26452645

2646-
#[doc(hidden)]
2646+
// Generic/generated code can sometimes have multiple, nested references
2647+
// for strings, including `&&&str`s that would never be written
2648+
// by hand. This macro generates twelve layers of nested `&`-impl
2649+
// for primitive strings.
26472650
#[cfg(not(no_global_oom_handling))]
2648-
#[stable(feature = "str_to_string_specialization", since = "1.9.0")]
2649-
impl ToString for str {
2650-
#[inline]
2651-
fn to_string(&self) -> String {
2652-
String::from(self)
2653-
}
2651+
macro_rules! to_string_str_wrap_in_ref {
2652+
{x $($x:ident)*} => {
2653+
&to_string_str_wrap_in_ref! { $($x)* }
2654+
};
2655+
{} => { str };
2656+
}
2657+
#[cfg(not(no_global_oom_handling))]
2658+
macro_rules! to_string_expr_wrap_in_deref {
2659+
{$self:expr ; x $($x:ident)*} => {
2660+
*(to_string_expr_wrap_in_deref! { $self ; $($x)* })
2661+
};
2662+
{$self:expr ;} => { $self };
2663+
}
2664+
#[cfg(not(no_global_oom_handling))]
2665+
macro_rules! to_string_str {
2666+
{$($($x:ident)*),+} => {
2667+
$(
2668+
#[doc(hidden)]
2669+
#[stable(feature = "str_to_string_specialization", since = "1.9.0")]
2670+
impl ToString for to_string_str_wrap_in_ref!($($x)*) {
2671+
#[inline]
2672+
fn to_string(&self) -> String {
2673+
String::from(to_string_expr_wrap_in_deref!(self ; $($x)*))
2674+
}
2675+
}
2676+
)+
2677+
};
2678+
}
2679+
2680+
#[cfg(not(no_global_oom_handling))]
2681+
to_string_str! {
2682+
x x x x x x x x x x x x,
2683+
x x x x x x x x x x x,
2684+
x x x x x x x x x x,
2685+
x x x x x x x x x,
2686+
x x x x x x x x,
2687+
x x x x x x x,
2688+
x x x x x x,
2689+
x x x x x,
2690+
x x x x,
2691+
x x x,
2692+
x x,
2693+
x,
26542694
}
26552695

26562696
#[doc(hidden)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//@ compile-flags: -C opt-level=3 -Z merge-functions=disabled
2+
#![crate_type = "lib"]
3+
4+
//! Make sure str::to_string is specialized not to use fmt machinery.
5+
6+
// CHECK-LABEL: define {{(dso_local )?}}void @one_ref
7+
#[no_mangle]
8+
pub fn one_ref(input: &str) -> String {
9+
// CHECK-NOT: {{(call|invoke).*}}fmt
10+
input.to_string()
11+
}
12+
13+
// CHECK-LABEL: define {{(dso_local )?}}void @two_ref
14+
#[no_mangle]
15+
pub fn two_ref(input: &&str) -> String {
16+
// CHECK-NOT: {{(call|invoke).*}}fmt
17+
input.to_string()
18+
}
19+
20+
// CHECK-LABEL: define {{(dso_local )?}}void @thirteen_ref
21+
#[no_mangle]
22+
pub fn thirteen_ref(input: &&&&&&&&&&&&&str) -> String {
23+
// CHECK-NOT: {{(call|invoke).*}}fmt
24+
input.to_string()
25+
}
26+
27+
// This is a known performance cliff because of the macro-generated
28+
// specialized impl. If this test suddenly starts failing,
29+
// consider removing the `to_string_str!` macro in `alloc/str/string.rs`.
30+
//
31+
// CHECK-LABEL: define {{(dso_local )?}}void @fourteen_ref
32+
#[no_mangle]
33+
pub fn fourteen_ref(input: &&&&&&&&&&&&&&str) -> String {
34+
// CHECK: {{(call|invoke).*}}fmt
35+
input.to_string()
36+
}

tests/ui/cast/ptr-to-trait-obj-different-args.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ LL | let y: *const dyn Trait<Y> = x as _;
1414
|
1515
= note: expected trait object `dyn Trait<X>`
1616
found trait object `dyn Trait<Y>`
17+
= help: `dyn Trait<Y>` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
1718

1819
error[E0308]: mismatched types
1920
--> $DIR/ptr-to-trait-obj-different-args.rs:27:34
@@ -25,6 +26,7 @@ LL | let _: *const dyn Trait<T> = x as _;
2526
|
2627
= note: expected trait object `dyn Trait<X>`
2728
found trait object `dyn Trait<T>`
29+
= help: `dyn Trait<T>` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
2830

2931
error[E0308]: mismatched types
3032
--> $DIR/ptr-to-trait-obj-different-args.rs:28:34
@@ -37,6 +39,7 @@ LL | let _: *const dyn Trait<X> = t as _;
3739
|
3840
= note: expected trait object `dyn Trait<T>`
3941
found trait object `dyn Trait<X>`
42+
= help: `dyn Trait<X>` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
4043

4144
error[E0308]: mismatched types
4245
--> $DIR/ptr-to-trait-obj-different-args.rs:36:5

tests/ui/coercion/coerce-expect-unsized-ascribed.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ LL | let _ = type_ascribe!(Box::new( if true { false } else { true }), Box<d
4242
|
4343
= note: expected struct `Box<dyn Debug>`
4444
found struct `Box<bool>`
45+
= help: `bool` implements `Debug` so you could box the found value and coerce it to the trait object `Box<dyn Debug>`, you will have to change the expected type as well
4546

4647
error[E0308]: mismatched types
4748
--> $DIR/coerce-expect-unsized-ascribed.rs:16:27
@@ -51,6 +52,7 @@ LL | let _ = type_ascribe!(Box::new( match true { true => 'a', false => 'b'
5152
|
5253
= note: expected struct `Box<dyn Debug>`
5354
found struct `Box<char>`
55+
= help: `char` implements `Debug` so you could box the found value and coerce it to the trait object `Box<dyn Debug>`, you will have to change the expected type as well
5456

5557
error[E0308]: mismatched types
5658
--> $DIR/coerce-expect-unsized-ascribed.rs:18:27
@@ -96,6 +98,7 @@ LL | let _ = type_ascribe!(&if true { false } else { true }, &dyn Debug);
9698
|
9799
= note: expected reference `&dyn Debug`
98100
found reference `&bool`
101+
= help: `bool` implements `Debug` so you could box the found value and coerce it to the trait object `Box<dyn Debug>`, you will have to change the expected type as well
99102

100103
error[E0308]: mismatched types
101104
--> $DIR/coerce-expect-unsized-ascribed.rs:24:27
@@ -105,6 +108,7 @@ LL | let _ = type_ascribe!(&match true { true => 'a', false => 'b' }, &dyn D
105108
|
106109
= note: expected reference `&dyn Debug`
107110
found reference `&char`
111+
= help: `char` implements `Debug` so you could box the found value and coerce it to the trait object `Box<dyn Debug>`, you will have to change the expected type as well
108112

109113
error[E0308]: mismatched types
110114
--> $DIR/coerce-expect-unsized-ascribed.rs:26:27

0 commit comments

Comments
 (0)