Skip to content

Commit 0fa56d7

Browse files
committed
impl Add<Output = String> for &str
Inspired by https://fasterthanli.me/articles/some-mistakes-rust-doesnt-catch.
1 parent b7cd0f7 commit 0fa56d7

File tree

4 files changed

+24
-0
lines changed

4 files changed

+24
-0
lines changed

compiler/rustc_hir/src/lang_items.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ language_item_table! {
171171
Slice, sym::slice, slice_impl, Target::Impl, GenericRequirement::None;
172172
SliceU8, sym::slice_u8, slice_u8_impl, Target::Impl, GenericRequirement::None;
173173
StrAlloc, sym::str_alloc, str_alloc_impl, Target::Impl, GenericRequirement::None;
174+
StrAllocAdd, sym::str_alloc_add, str_alloc_add_impl, Target::Impl, GenericRequirement::None;
174175
SliceAlloc, sym::slice_alloc, slice_alloc_impl, Target::Impl, GenericRequirement::None;
175176
SliceU8Alloc, sym::slice_u8_alloc, slice_u8_alloc_impl, Target::Impl, GenericRequirement::None;
176177
ConstPtr, sym::const_ptr, const_ptr_impl, Target::Impl, GenericRequirement::None;

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,6 +1330,7 @@ symbols! {
13301330
store,
13311331
str,
13321332
str_alloc,
1333+
str_alloc_add,
13331334
stringify,
13341335
stringify_macro,
13351336
struct_field_attributes,

compiler/rustc_trait_selection/src/traits/coherence.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,11 @@ pub enum OrphanCheckErr<'tcx> {
439439
pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanCheckErr<'_>> {
440440
debug!("orphan_check({:?})", impl_def_id);
441441

442+
// `alloc` breaks coherence so it can define `&str + &str = String`
443+
if Some(impl_def_id) == tcx.lang_items().str_alloc_add_impl() {
444+
return Ok(());
445+
}
446+
442447
// We only except this routine to be invoked on implementations
443448
// of a trait, not inherent implementations.
444449
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();

library/alloc/src/string.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2215,6 +2215,23 @@ impl AddAssign<&str> for String {
22152215
}
22162216
}
22172217

2218+
#[cfg(not(no_global_oom_handling))]
2219+
#[cfg(not(bootstrap))]
2220+
#[lang = "str_alloc_add"]
2221+
#[stable(feature = "stradd", since = "1.60.0")]
2222+
/// # Examples
2223+
/// ```
2224+
/// let hello: String = "hello, " + "world!";
2225+
/// println!("{}", hello);
2226+
/// ```
2227+
impl core::ops::Add<&str> for &str {
2228+
type Output = String;
2229+
2230+
fn add(self, other: &str) -> String {
2231+
String::from(self) + other
2232+
}
2233+
}
2234+
22182235
#[stable(feature = "rust1", since = "1.0.0")]
22192236
impl ops::Index<ops::Range<usize>> for String {
22202237
type Output = str;

0 commit comments

Comments
 (0)