Skip to content

Commit 2277c63

Browse files
committed
Auto merge of rust-lang#133570 - adetaylor:receiver_trait_with_target_for_real, r=<try>
Arbitrary self types v2: simulated stabilization, do not merge This PR is essentially the same as rust-lang#132961, but also flips the feature to being stabilized. We shouldn't merge this yet, but we want to do a crater run on this PR to check for unexpected surprises. The difference relative to rust-lang#132961 can be seen in [this comparison](adetaylor/rust@arbitrary-self-types-the-big-bit...adetaylor:rust:receiver_trait_with_target_for_real). Please *do not* review this - please add review comments on rust-lang#132961, instead. r? `@wesleywiser`
2 parents d49be02 + 9647820 commit 2277c63

File tree

108 files changed

+2099
-541
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+2099
-541
lines changed

compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Adapted from rustc run-pass test suite
22

3-
#![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)]
3+
#![feature(unsize, coerce_unsized, dispatch_from_dyn)]
44

55
use std::marker::Unsize;
66
use std::ops::{CoerceUnsized, Deref, DispatchFromDyn};

compiler/rustc_codegen_cranelift/example/mini_core.rs

-7
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,6 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
4747
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
4848
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T> {}
4949

50-
#[lang = "legacy_receiver"]
51-
pub trait LegacyReceiver {}
52-
53-
impl<T: ?Sized> LegacyReceiver for &T {}
54-
impl<T: ?Sized> LegacyReceiver for &mut T {}
55-
impl<T: ?Sized> LegacyReceiver for Box<T> {}
56-
5750
#[lang = "copy"]
5851
pub unsafe trait Copy {}
5952

compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Adapted from rustc run-pass test suite
22

3-
#![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)]
3+
#![feature(unsize, coerce_unsized, dispatch_from_dyn)]
44
#![feature(rustc_attrs)]
55
#![allow(internal_features)]
66

compiler/rustc_codegen_gcc/example/mini_core.rs

-7
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,6 @@ impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
4444
impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
4545
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U, ()>> for Box<T, ()> {}
4646

47-
#[lang = "legacy_receiver"]
48-
pub trait LegacyReceiver {}
49-
50-
impl<T: ?Sized> LegacyReceiver for &T {}
51-
impl<T: ?Sized> LegacyReceiver for &mut T {}
52-
impl<T: ?Sized, A: Allocator> LegacyReceiver for Box<T, A> {}
53-
5447
#[lang = "copy"]
5548
pub unsafe trait Copy {}
5649

compiler/rustc_error_codes/src/error_codes/E0307.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,10 @@ impl Trait for Foo {
6565
```
6666

6767
The nightly feature [Arbitrary self types][AST] extends the accepted
68-
set of receiver types to also include any type that can dereference to
69-
`Self`:
68+
set of receiver types to also include any type that implements the
69+
`Receiver` trait and can follow its chain of `Target` types to `Self`.
70+
There's a blanket implementation of `Receiver` for `T: Deref`, so any
71+
type which dereferences to `Self` can be used.
7072

7173
```
7274
#![feature(arbitrary_self_types)]

compiler/rustc_feature/src/accepted.rs

+2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ declare_features! (
6060
(accepted, adx_target_feature, "1.61.0", Some(44839)),
6161
/// Allows explicit discriminants on non-unit enum variants.
6262
(accepted, arbitrary_enum_discriminant, "1.66.0", Some(60553)),
63+
/// Allows inherent and trait methods with arbitrary self types.
64+
(accepted, arbitrary_self_types, "CURRENT_RUSTC_VERSION", Some(44874)),
6365
/// Allows using `const` operands in inline assembly.
6466
(accepted, asm_const, "1.82.0", Some(93332)),
6567
/// Allows using `sym` operands in inline assembly.

compiler/rustc_feature/src/unstable.rs

-2
Original file line numberDiff line numberDiff line change
@@ -370,8 +370,6 @@ declare_features! (
370370
(unstable, adt_const_params, "1.56.0", Some(95174)),
371371
/// Allows defining an `#[alloc_error_handler]`.
372372
(unstable, alloc_error_handler, "1.29.0", Some(51540)),
373-
/// Allows inherent and trait methods with arbitrary self types.
374-
(unstable, arbitrary_self_types, "1.23.0", Some(44874)),
375373
/// Allows inherent and trait methods with arbitrary self types that are raw pointers.
376374
(unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)),
377375
/// Enables experimental inline assembly support for additional architectures.

compiler/rustc_hir/src/lang_items.rs

-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,6 @@ language_item_table! {
243243
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
244244
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
245245
ReceiverTarget, sym::receiver_target, receiver_target, Target::AssocTy, GenericRequirement::None;
246-
LegacyReceiver, sym::legacy_receiver, legacy_receiver_trait, Target::Trait, GenericRequirement::None;
247246

248247
Fn, kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);
249248
FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);

compiler/rustc_hir_analysis/messages.ftl

+6-2
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,14 @@ hir_analysis_invalid_generic_receiver_ty_help =
241241
use a concrete type such as `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
242242
243243
hir_analysis_invalid_receiver_ty = invalid `self` parameter type: `{$receiver_ty}`
244-
.note = type of `self` must be `Self` or a type that dereferences to it
244+
.note = type of `self` must be `Self` or some type implementing Receiver
245245
246246
hir_analysis_invalid_receiver_ty_help =
247-
consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
247+
consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
248+
249+
hir_analysis_invalid_receiver_ty_help_pointer_note =
250+
Raw pointers do not implement Receiver. Consider wrapping your pointer in
251+
a newtype wrapper for which you implement Receiver
248252
249253
hir_analysis_invalid_union_field =
250254
field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union

compiler/rustc_hir_analysis/src/autoderef.rs

+28-9
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ pub enum AutoderefKind {
1818
/// A type which must dispatch to a `Deref` implementation.
1919
Overloaded,
2020
}
21-
2221
struct AutoderefSnapshot<'tcx> {
2322
at_start: bool,
2423
reached_recursion_limit: bool,
@@ -27,6 +26,10 @@ struct AutoderefSnapshot<'tcx> {
2726
obligations: PredicateObligations<'tcx>,
2827
}
2928

29+
/// Recursively dereference a type, considering both built-in
30+
/// dereferences (`*`) and the `Deref` trait.
31+
/// Although called `Autoderef` it can be configured to use the
32+
/// `Receiver` trait instead of the `Deref` trait.
3033
pub struct Autoderef<'a, 'tcx> {
3134
// Meta infos:
3235
infcx: &'a InferCtxt<'tcx>,
@@ -39,6 +42,7 @@ pub struct Autoderef<'a, 'tcx> {
3942

4043
// Configurations:
4144
include_raw_pointers: bool,
45+
use_receiver_trait: bool,
4246
silence_errors: bool,
4347
}
4448

@@ -69,6 +73,10 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
6973
}
7074

7175
// Otherwise, deref if type is derefable:
76+
// NOTE: in the case of self.use_receiver_trait = true, you might think it would
77+
// be better to skip this clause and use the Overloaded case only, since &T
78+
// and &mut T implement Receiver. But built-in derefs apply equally to Receiver
79+
// and Deref, and this has benefits for const and the emitted MIR.
7280
let (kind, new_ty) =
7381
if let Some(ty) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
7482
debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
@@ -111,7 +119,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
111119
body_def_id: LocalDefId,
112120
span: Span,
113121
base_ty: Ty<'tcx>,
114-
) -> Autoderef<'a, 'tcx> {
122+
) -> Self {
115123
Autoderef {
116124
infcx,
117125
span,
@@ -125,6 +133,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
125133
reached_recursion_limit: false,
126134
},
127135
include_raw_pointers: false,
136+
use_receiver_trait: false,
128137
silence_errors: false,
129138
}
130139
}
@@ -137,8 +146,13 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
137146
return None;
138147
}
139148

140-
// <ty as Deref>
141-
let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
149+
// <ty as Deref>, or whatever the equivalent trait is that we've been asked to walk.
150+
let (trait_def_id, trait_target_def_id) = if self.use_receiver_trait {
151+
(tcx.lang_items().receiver_trait()?, tcx.lang_items().receiver_target()?)
152+
} else {
153+
(tcx.lang_items().deref_trait()?, tcx.lang_items().deref_target()?)
154+
};
155+
let trait_ref = ty::TraitRef::new(tcx, trait_def_id, [ty]);
142156
let cause = traits::ObligationCause::misc(self.span, self.body_id);
143157
let obligation = traits::Obligation::new(
144158
tcx,
@@ -151,11 +165,8 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
151165
return None;
152166
}
153167

154-
let (normalized_ty, obligations) = self.structurally_normalize(Ty::new_projection(
155-
tcx,
156-
tcx.lang_items().deref_target()?,
157-
[ty],
158-
))?;
168+
let (normalized_ty, obligations) =
169+
self.structurally_normalize(Ty::new_projection(tcx, trait_target_def_id, [ty]))?;
159170
debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
160171
self.state.obligations.extend(obligations);
161172

@@ -234,6 +245,14 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
234245
self
235246
}
236247

248+
/// Use `core::ops::Receiver` and `core::ops::Receiver::Target` as
249+
/// the trait and associated type to iterate, instead of
250+
/// `core::ops::Deref` and `core::ops::Deref::Target`
251+
pub fn use_receiver_trait(mut self) -> Self {
252+
self.use_receiver_trait = true;
253+
self
254+
}
255+
237256
pub fn silence_errors(mut self) -> Self {
238257
self.silence_errors = true;
239258
self

0 commit comments

Comments
 (0)