Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1a2dbf8

Browse files
arbitrary_self_types: split the Autoderef chain
Receiver chain has been an extension of Deref chain, but the consequence has been questioned as this would admit method signatures that are deemed dubious. It is also debatable that Receiver trait which determines applicable `Self` type should have anything to do with dereference operation in general. This patch separate the two traits and isolate their use in the language. This means that in method probing, we will chase down a Deref chain for an applicable type for the variable `self`, from which we additionally chase down a Receiver chain for an applicable `Self` type from a list of methods that accepts one of these possible types of `self`.
1 parent 05abce5 commit 1a2dbf8

File tree

52 files changed

+567
-352
lines changed

Some content is hidden

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

52 files changed

+567
-352
lines changed

‎compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
#![feature(rustc_attrs)]
55
#![allow(internal_features)]
66

7-
use std::{
8-
ops::{Deref, CoerceUnsized, DispatchFromDyn},
9-
marker::Unsize,
10-
};
7+
use std::marker::Unsize;
8+
use std::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver};
119

1210
struct Ptr<T: ?Sized>(Box<T>);
1311

@@ -18,6 +16,9 @@ impl<T: ?Sized> Deref for Ptr<T> {
1816
&*self.0
1917
}
2018
}
19+
impl<T: ?Sized> Receiver for Ptr<T> {
20+
type Target = T;
21+
}
2122

2223
impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T> {}
2324
impl<T: Unsize<U> + ?Sized, U: ?Sized> DispatchFromDyn<Ptr<U>> for Ptr<T> {}
@@ -31,11 +32,13 @@ impl<T: ?Sized> Deref for Wrapper<T> {
3132
&self.0
3233
}
3334
}
35+
impl<T: ?Sized> Receiver for Wrapper<T> {
36+
type Target = T;
37+
}
3438

3539
impl<T: CoerceUnsized<U>, U> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
3640
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<Wrapper<U>> for Wrapper<T> {}
3741

38-
3942
trait Trait {
4043
fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32;
4144
fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32;

‎compiler/rustc_error_codes/src/error_codes/E0307.md

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,22 +67,16 @@ impl Trait for Foo {
6767
The nightly feature [Arbitrary self types][AST] extends the accepted
6868
set of receiver types to also include any type that implements the
6969
`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.
7270

7371
```
7472
#![feature(arbitrary_self_types)]
7573
7674
struct Foo;
7775
struct Bar;
7876
79-
// Because you can dereference `Bar` into `Foo`...
80-
impl std::ops::Deref for Bar {
77+
// Because you can set `Bar` as method receiver for `Foo`...
78+
impl std::ops::Receiver for Bar {
8179
type Target = Foo;
82-
83-
fn deref(&self) -> &Foo {
84-
&Foo
85-
}
8680
}
8781
8882
impl Foo {

‎compiler/rustc_hir_analysis/src/autoderef.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,19 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
7373
}
7474

7575
// 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.
76+
// NOTE: in the case of self.use_receiver_trait = true,
77+
// Autoderef works only with Receiver trait.
78+
// Caller is expecting us to expand the Receiver chain only.
8079
let (kind, new_ty) =
8180
if let Some(ty) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
8281
debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
8382
// NOTE: we may still need to normalize the built-in deref in case
8483
// we have some type like `&<Ty as Trait>::Assoc`, since users of
8584
// autoderef expect this type to have been structurally normalized.
85+
// NOTE: even when we follow Receiver chain we still unwrap
86+
// references and pointers here, but this is only symbolic and
87+
// we are not going to really dereferences any references or pointers.
88+
// That happens when autoderef is chasing the Deref chain.
8689
if self.infcx.next_trait_solver()
8790
&& let ty::Alias(..) = ty.kind()
8891
{
@@ -138,8 +141,8 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
138141
}
139142
}
140143

144+
#[instrument(level = "debug", skip(self), ret)]
141145
fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
142-
debug!("overloaded_deref_ty({:?})", ty);
143146
let tcx = self.infcx.tcx;
144147

145148
if ty.references_error() {
@@ -161,13 +164,13 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
161164
ty::Binder::dummy(trait_ref),
162165
);
163166
if !self.infcx.next_trait_solver() && !self.infcx.predicate_may_hold(&obligation) {
164-
debug!("overloaded_deref_ty: cannot match obligation");
167+
debug!("cannot match obligation");
165168
return None;
166169
}
167170

168171
let (normalized_ty, obligations) =
169172
self.structurally_normalize_ty(Ty::new_projection(tcx, trait_target_def_id, [ty]))?;
170-
debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})",ty, normalized_ty, obligations);
173+
debug!(?ty, ?normalized_ty, ?obligations);
171174
self.state.obligations.extend(obligations);
172175

173176
Some(self.infcx.resolve_vars_if_possible(normalized_ty))
@@ -244,11 +247,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
244247
/// Use `core::ops::Receiver` and `core::ops::Receiver::Target` as
245248
/// the trait and associated type to iterate, instead of
246249
/// `core::ops::Deref` and `core::ops::Deref::Target`
247-
pub fn use_receiver_trait(mut self) -> Self {
250+
pub fn follow_receiver_chain(mut self) -> Self {
248251
self.use_receiver_trait = true;
249252
self
250253
}
251-
252254
pub fn silence_errors(mut self) -> Self {
253255
self.silence_errors = true;
254256
self

‎compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1734,7 +1734,9 @@ fn check_method_receiver<'tcx>(
17341734
// Report error; would not have worked with `arbitrary_self_types[_pointers]`.
17351735
{
17361736
match receiver_validity_err {
1737-
ReceiverValidityError::DoesNotDeref if arbitrary_self_types_level.is_some() => {
1737+
ReceiverValidityError::DoesNotReceive
1738+
if arbitrary_self_types_level.is_some() =>
1739+
{
17381740
let hint = match receiver_ty
17391741
.builtin_deref(false)
17401742
.unwrap_or(receiver_ty)
@@ -1748,7 +1750,7 @@ fn check_method_receiver<'tcx>(
17481750

17491751
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty, hint })
17501752
}
1751-
ReceiverValidityError::DoesNotDeref => {
1753+
ReceiverValidityError::DoesNotReceive => {
17521754
tcx.dcx().emit_err(errors::InvalidReceiverTyNoArbitrarySelfTypes {
17531755
span,
17541756
receiver_ty,
@@ -1770,7 +1772,7 @@ fn check_method_receiver<'tcx>(
17701772
enum ReceiverValidityError {
17711773
/// The self type does not get to the receiver type by following the
17721774
/// autoderef chain.
1773-
DoesNotDeref,
1775+
DoesNotReceive,
17741776
/// A type was found which is a method type parameter, and that's not allowed.
17751777
MethodGenericParamUsed,
17761778
}
@@ -1828,7 +1830,9 @@ fn receiver_is_valid<'tcx>(
18281830
// types to be method receivers, as identified by following the Receiver<Target=T>
18291831
// chain.
18301832
if arbitrary_self_types_enabled.is_some() {
1831-
autoderef = autoderef.use_receiver_trait();
1833+
// We are in the wf check, so we would like to deref the references in the type head.
1834+
// However, we do not want to walk `Deref` chain.
1835+
autoderef = autoderef.follow_receiver_chain();
18321836
}
18331837

18341838
// The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`.
@@ -1882,7 +1886,7 @@ fn receiver_is_valid<'tcx>(
18821886
}
18831887

18841888
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
1885-
Err(ReceiverValidityError::DoesNotDeref)
1889+
Err(ReceiverValidityError::DoesNotReceive)
18861890
}
18871891

18881892
fn legacy_receiver_is_implemented<'tcx>(

‎compiler/rustc_hir_typeck/src/method/confirm.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::marker::PhantomData;
12
use std::ops::Deref;
23

34
use rustc_hir as hir;
@@ -352,18 +353,37 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
352353
// yield an object-type (e.g., `&Object` or `Box<Object>`
353354
// etc).
354355

355-
let mut autoderef = self.fcx.autoderef(self.span, self_ty);
356+
let fcx = self.fcx;
357+
let span = self.span;
358+
let autoderef = fcx.autoderef(span, self_ty);
356359

357360
// We don't need to gate this behind arbitrary self types
358361
// per se, but it does make things a bit more gated.
359-
if self.tcx.features().arbitrary_self_types()
360-
|| self.tcx.features().arbitrary_self_types_pointers()
361-
{
362-
autoderef = autoderef.use_receiver_trait();
363-
}
362+
let follow_receiver_chain = self.tcx.features().arbitrary_self_types()
363+
|| self.tcx.features().arbitrary_self_types_pointers();
364364

365365
autoderef
366366
.include_raw_pointers()
367+
.flat_map(|(ty, derefs)| {
368+
enum EitherIter<A, B, C> {
369+
A(A, PhantomData<fn() -> C>),
370+
B(B, PhantomData<fn() -> C>),
371+
}
372+
impl<A: Iterator<Item = C>, B: Iterator<Item = C>, C> Iterator for EitherIter<A, B, C> {
373+
type Item = C;
374+
fn next(&mut self) -> Option<Self::Item> {
375+
match self {
376+
EitherIter::A(a, _) => a.next(),
377+
EitherIter::B(b, _) => b.next(),
378+
}
379+
}
380+
}
381+
if follow_receiver_chain {
382+
EitherIter::A(fcx.autoderef(span, ty).follow_receiver_chain(), PhantomData)
383+
} else {
384+
EitherIter::B([(ty, derefs)].into_iter(), PhantomData)
385+
}
386+
})
367387
.find_map(|(ty, _)| match ty.kind() {
368388
ty::Dynamic(data, ..) => Some(closure(
369389
self,

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /