Skip to content

Commit 176bf24

Browse files
authored
Rollup merge of rust-lang#64325 - cramertj:nested-self-types, r=mikeyhew
Stabilize nested self receivers in 1.40.0 Previously, only `Self`, `&Self`, `&mut Self`, `Arc<Self>`, `Rc<Self>`, and `Box<Self>` were available as stable method receivers. This commit stabilizes nested uses of all the above types. However, nested receivers remain non-object-safe.
2 parents 87cbf0a + 772b84a commit 176bf24

Some content is hidden

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

49 files changed

+140
-122
lines changed

src/librustc_typeck/check/wfcheck.rs

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::check::{Inherited, FnCtxt};
22
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
33

44
use crate::hir::def_id::DefId;
5-
use rustc::traits::{self, ObligationCauseCode};
5+
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
66
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable, ToPredicate};
77
use rustc::ty::subst::{Subst, InternalSubsts};
88
use rustc::util::nodemap::{FxHashSet, FxHashMap};
@@ -893,6 +893,11 @@ fn receiver_is_valid<'fcx, 'tcx>(
893893
// The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
894894
autoderef.next();
895895

896+
let receiver_trait_def_id = fcx.tcx.require_lang_item(
897+
lang_items::ReceiverTraitLangItem,
898+
None,
899+
);
900+
896901
// Keep dereferencing `receiver_ty` until we get to `self_ty`.
897902
loop {
898903
if let Some((potential_self_ty, _)) = autoderef.next() {
@@ -909,6 +914,19 @@ fn receiver_is_valid<'fcx, 'tcx>(
909914
}
910915

911916
break
917+
} else {
918+
// Without `feature(arbitrary_self_types)`, we require that each step in the
919+
// deref chain implement `receiver`
920+
if !arbitrary_self_types_enabled
921+
&& !receiver_is_implemented(
922+
fcx,
923+
receiver_trait_def_id,
924+
cause.clone(),
925+
potential_self_ty,
926+
)
927+
{
928+
return false
929+
}
912930
}
913931
} else {
914932
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`",
@@ -917,43 +935,42 @@ fn receiver_is_valid<'fcx, 'tcx>(
917935
// unecessary errors (#58712).
918936
return receiver_ty.references_error();
919937
}
920-
921-
// Without the `arbitrary_self_types` feature, `receiver_ty` must directly deref to
922-
// `self_ty`. Enforce this by only doing one iteration of the loop.
923-
if !arbitrary_self_types_enabled {
924-
return false
925-
}
926938
}
927939

928940
// Without `feature(arbitrary_self_types)`, we require that `receiver_ty` implements `Receiver`.
929-
if !arbitrary_self_types_enabled {
930-
let trait_def_id = match fcx.tcx.lang_items().receiver_trait() {
931-
Some(did) => did,
932-
None => {
933-
debug!("receiver_is_valid: missing Receiver trait");
934-
return false
935-
}
936-
};
941+
if !arbitrary_self_types_enabled
942+
&& !receiver_is_implemented(fcx, receiver_trait_def_id, cause.clone(), receiver_ty)
943+
{
944+
return false
945+
}
937946

938-
let trait_ref = ty::TraitRef{
939-
def_id: trait_def_id,
940-
substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]),
941-
};
947+
true
948+
}
949+
950+
fn receiver_is_implemented(
951+
fcx: &FnCtxt<'_, 'tcx>,
952+
receiver_trait_def_id: DefId,
953+
cause: ObligationCause<'tcx>,
954+
receiver_ty: Ty<'tcx>,
955+
) -> bool {
956+
let trait_ref = ty::TraitRef{
957+
def_id: receiver_trait_def_id,
958+
substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]),
959+
};
942960

943-
let obligation = traits::Obligation::new(
944-
cause,
945-
fcx.param_env,
946-
trait_ref.to_predicate()
947-
);
961+
let obligation = traits::Obligation::new(
962+
cause,
963+
fcx.param_env,
964+
trait_ref.to_predicate()
965+
);
948966

949-
if !fcx.predicate_must_hold_modulo_regions(&obligation) {
950-
debug!("receiver_is_valid: type `{:?}` does not implement `Receiver` trait",
951-
receiver_ty);
952-
return false
953-
}
967+
if fcx.predicate_must_hold_modulo_regions(&obligation) {
968+
true
969+
} else {
970+
debug!("receiver_is_implemented: type `{:?}` does not implement `Receiver` trait",
971+
receiver_ty);
972+
false
954973
}
955-
956-
true
957974
}
958975

959976
fn check_variances_for_type_defn<'tcx>(

src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0038]: the trait `Foo` cannot be made into an object
2-
--> $DIR/arbitrary-self-types-not-object-safe.rs:34:32
2+
--> $DIR/arbitrary-self-types-not-object-safe.rs:33:32
33
|
44
LL | fn foo(self: &Rc<Self>) -> usize;
55
| --- method `foo`'s `self` parameter cannot be dispatched on
@@ -8,7 +8,7 @@ LL | let x = Rc::new(5usize) as Rc<dyn Foo>;
88
| ^^^^^^^^^^^ the trait `Foo` cannot be made into an object
99

1010
error[E0038]: the trait `Foo` cannot be made into an object
11-
--> $DIR/arbitrary-self-types-not-object-safe.rs:34:13
11+
--> $DIR/arbitrary-self-types-not-object-safe.rs:33:13
1212
|
1313
LL | fn foo(self: &Rc<Self>) -> usize;
1414
| --- method `foo`'s `self` parameter cannot be dispatched on

src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0038]: the trait `Foo` cannot be made into an object
2-
--> $DIR/arbitrary-self-types-not-object-safe.rs:34:13
2+
--> $DIR/arbitrary-self-types-not-object-safe.rs:33:13
33
|
44
LL | fn foo(self: &Rc<Self>) -> usize;
55
| --- method `foo`'s `self` parameter cannot be dispatched on

src/test/ui/self/arbitrary-self-types-not-object-safe.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// revisions: curr object_safe_for_dispatch
22

33
#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
4-
#![feature(arbitrary_self_types)]
54

65
use std::rc::Rc;
76

src/test/ui/self/arbitrary-self-types-not-object-safe.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0038]: the trait `Foo` cannot be made into an object
2-
--> $DIR/arbitrary-self-types-not-object-safe.rs:31:32
2+
--> $DIR/arbitrary-self-types-not-object-safe.rs:29:32
33
|
44
LL | fn foo(self: &Rc<Self>) -> usize;
55
| --- method `foo`'s `self` parameter cannot be dispatched on
@@ -8,7 +8,7 @@ LL | let x = Rc::new(5usize) as Rc<dyn Foo>;
88
| ^^^^^^^^^^^ the trait `Foo` cannot be made into an object
99

1010
error[E0038]: the trait `Foo` cannot be made into an object
11-
--> $DIR/arbitrary-self-types-not-object-safe.rs:31:13
11+
--> $DIR/arbitrary-self-types-not-object-safe.rs:29:13
1212
|
1313
LL | fn foo(self: &Rc<Self>) -> usize;
1414
| --- method `foo`'s `self` parameter cannot be dispatched on
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// run-pass
2+
3+
use {
4+
std::{
5+
rc::Rc,
6+
sync::Arc,
7+
},
8+
};
9+
10+
#[derive(Default)]
11+
struct Ty;
12+
13+
trait Trait {
14+
fn receive_trait(self: &Arc<Rc<Box<Self>>>) -> u32;
15+
}
16+
17+
const TRAIT_MAGIC: u32 = 42;
18+
const INHERENT_MAGIC: u32 = 1995;
19+
20+
impl Trait for Ty {
21+
fn receive_trait(self: &Arc<Rc<Box<Self>>>) -> u32 {
22+
TRAIT_MAGIC
23+
}
24+
}
25+
26+
impl Ty {
27+
fn receive_inherent(self: &Arc<Rc<Box<Self>>>) -> u32 {
28+
INHERENT_MAGIC
29+
}
30+
}
31+
32+
fn main() {
33+
let ty = <Arc<Rc<Box<Ty>>>>::default();
34+
assert_eq!(TRAIT_MAGIC, ty.receive_trait());
35+
assert_eq!(INHERENT_MAGIC, ty.receive_inherent());
36+
}

src/test/ui/self/arbitrary_self_types_struct.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// run-pass
2-
#![feature(arbitrary_self_types)]
32

43
use std::rc::Rc;
54

src/test/ui/self/arbitrary_self_types_trait.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// run-pass
2-
#![feature(arbitrary_self_types)]
32

43
use std::rc::Rc;
54

src/test/ui/self/arbitrary_self_types_unsized_struct.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// run-pass
2-
#![feature(arbitrary_self_types)]
32

43
use std::rc::Rc;
54

src/test/ui/self/elision/alias-async.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// check-pass
22
// edition:2018
33

4-
#![feature(arbitrary_self_types)]
54
#![allow(non_snake_case)]
65

76
use std::rc::Rc;

src/test/ui/self/elision/alias.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// check-pass
22

3-
#![feature(arbitrary_self_types)]
43
#![allow(non_snake_case)]
54

65
use std::rc::Rc;

src/test/ui/self/elision/assoc-async.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// check-pass
22
// edition:2018
33

4-
#![feature(arbitrary_self_types)]
54
#![allow(non_snake_case)]
65

76
use std::rc::Rc;

src/test/ui/self/elision/assoc.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// check-pass
22

3-
#![feature(arbitrary_self_types)]
43
#![allow(non_snake_case)]
54

65
use std::rc::Rc;

src/test/ui/self/elision/lt-alias-async.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// check-pass
22
// edition:2018
33

4-
#![feature(arbitrary_self_types)]
54
#![allow(non_snake_case)]
65

76
use std::rc::Rc;

src/test/ui/self/elision/lt-alias.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// check-pass
22

3-
#![feature(arbitrary_self_types)]
43
#![allow(non_snake_case)]
54

65
use std::rc::Rc;

src/test/ui/self/elision/lt-assoc-async.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// check-pass
22
// edition:2018
33

4-
#![feature(arbitrary_self_types)]
54
#![allow(non_snake_case)]
65

76
use std::rc::Rc;

src/test/ui/self/elision/lt-assoc.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// check-pass
22

3-
#![feature(arbitrary_self_types)]
43
#![allow(non_snake_case)]
54

65
use std::rc::Rc;

src/test/ui/self/elision/lt-ref-self-async.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// edition:2018
22

3-
#![feature(arbitrary_self_types)]
43
#![allow(non_snake_case)]
54

65
use std::pin::Pin;

src/test/ui/self/elision/lt-ref-self-async.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0623]: lifetime mismatch
2-
--> $DIR/lt-ref-self-async.rs:14:9
2+
--> $DIR/lt-ref-self-async.rs:13:9
33
|
44
LL | async fn ref_self(&self, f: &u32) -> &u32 {
55
| ----- ----
@@ -9,7 +9,7 @@ LL | f
99
| ^ ...but data from `f` is returned here
1010

1111
error[E0623]: lifetime mismatch
12-
--> $DIR/lt-ref-self-async.rs:20:9
12+
--> $DIR/lt-ref-self-async.rs:19:9
1313
|
1414
LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
1515
| ----- ----
@@ -19,7 +19,7 @@ LL | f
1919
| ^ ...but data from `f` is returned here
2020

2121
error[E0623]: lifetime mismatch
22-
--> $DIR/lt-ref-self-async.rs:24:9
22+
--> $DIR/lt-ref-self-async.rs:23:9
2323
|
2424
LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
2525
| ----- ----
@@ -29,7 +29,7 @@ LL | f
2929
| ^ ...but data from `f` is returned here
3030

3131
error[E0623]: lifetime mismatch
32-
--> $DIR/lt-ref-self-async.rs:28:9
32+
--> $DIR/lt-ref-self-async.rs:27:9
3333
|
3434
LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
3535
| ----- ----
@@ -39,7 +39,7 @@ LL | f
3939
| ^ ...but data from `f` is returned here
4040

4141
error[E0623]: lifetime mismatch
42-
--> $DIR/lt-ref-self-async.rs:32:9
42+
--> $DIR/lt-ref-self-async.rs:31:9
4343
|
4444
LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
4545
| ----- ----
@@ -49,7 +49,7 @@ LL | f
4949
| ^ ...but data from `f` is returned here
5050

5151
error[E0623]: lifetime mismatch
52-
--> $DIR/lt-ref-self-async.rs:36:9
52+
--> $DIR/lt-ref-self-async.rs:35:9
5353
|
5454
LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
5555
| ----- ----

src/test/ui/self/elision/lt-ref-self.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#![feature(arbitrary_self_types)]
21
#![allow(non_snake_case)]
32

43
use std::pin::Pin;

src/test/ui/self/elision/lt-ref-self.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0623]: lifetime mismatch
2-
--> $DIR/lt-ref-self.rs:12:9
2+
--> $DIR/lt-ref-self.rs:11:9
33
|
44
LL | fn ref_self(&self, f: &u32) -> &u32 {
55
| ---- ----
@@ -9,7 +9,7 @@ LL | f
99
| ^ ...but data from `f` is returned here
1010

1111
error[E0623]: lifetime mismatch
12-
--> $DIR/lt-ref-self.rs:18:9
12+
--> $DIR/lt-ref-self.rs:17:9
1313
|
1414
LL | fn ref_Self(self: &Self, f: &u32) -> &u32 {
1515
| ---- ----
@@ -19,7 +19,7 @@ LL | f
1919
| ^ ...but data from `f` is returned here
2020

2121
error[E0623]: lifetime mismatch
22-
--> $DIR/lt-ref-self.rs:22:9
22+
--> $DIR/lt-ref-self.rs:21:9
2323
|
2424
LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
2525
| ---- ----
@@ -29,7 +29,7 @@ LL | f
2929
| ^ ...but data from `f` is returned here
3030

3131
error[E0623]: lifetime mismatch
32-
--> $DIR/lt-ref-self.rs:26:9
32+
--> $DIR/lt-ref-self.rs:25:9
3333
|
3434
LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
3535
| ---- ----
@@ -39,7 +39,7 @@ LL | f
3939
| ^ ...but data from `f` is returned here
4040

4141
error[E0623]: lifetime mismatch
42-
--> $DIR/lt-ref-self.rs:30:9
42+
--> $DIR/lt-ref-self.rs:29:9
4343
|
4444
LL | fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
4545
| ---- ----
@@ -49,7 +49,7 @@ LL | f
4949
| ^ ...but data from `f` is returned here
5050

5151
error[E0623]: lifetime mismatch
52-
--> $DIR/lt-ref-self.rs:34:9
52+
--> $DIR/lt-ref-self.rs:33:9
5353
|
5454
LL | fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
5555
| ---- ----

src/test/ui/self/elision/lt-self-async.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// check-pass
22
// edition:2018
33

4-
#![feature(arbitrary_self_types)]
54
#![allow(non_snake_case)]
65

76
use std::pin::Pin;

0 commit comments

Comments
 (0)