Skip to content

Commit 58fcf8a

Browse files
committed
Reject generic self types using impl defid: do not merge.
The RFC for arbitrary self types v2 declares that we should reject "generic" self types. This commit does so. The definition of "generic" was unclear in the RFC, but has been explored in rust-lang#129147 and the conclusion is that "generic" means any `self` type which is a type parameter defined on the method itself, or references to such a type. This approach was chosen because other definitions of "generic" don't work. Specifically, * we can't filter out generic type _arguments_, because that would filter out Rc<Self> and all the other types of smart pointer we want to support; * we can't filter out all type params, because Self itself is a type param, and because existing Rust code depends on other type params declared on the type (as opposed to the method). This PR is a second attempt at achieving this, based on producing a new well-formedness checking context which is only aware of the type params of the impl block, not of the method itself. It doesn't currently work because it turns out we do need some method params under some circumstances, but raising it for completeness. This PR adds lots of extra tests to arbitrary-self-from-method-substs. Most of these are ways to trigger a "type mismatch" error which https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519 hopes can be minimized by filtering out generics in this way. We remove a FIXME from confirm.rs suggesting that we make this change. It's still possible to cause type mismatch errors, and a subsequent PR may be able to improve diagnostics in this area, but it's harder to cause these errors without contrived uses of the turbofish. This is a part of the arbitrary self types v2 project, rust-lang/rfcs#3519 rust-lang#44874 r? @wesleywiser
1 parent 7f4b270 commit 58fcf8a

10 files changed

+486
-100
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+57-52
Original file line numberDiff line numberDiff line change
@@ -903,7 +903,6 @@ fn check_impl_item<'tcx>(
903903
hir::ImplItemKind::Type(ty) if ty.span != DUMMY_SP => (None, ty.span),
904904
_ => (None, impl_item.span),
905905
};
906-
907906
check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig)
908907
}
909908

@@ -1699,62 +1698,68 @@ fn check_method_receiver<'tcx>(
16991698
None
17001699
};
17011700

1702-
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level) {
1703-
return Err(match arbitrary_self_types_level {
1704-
// Wherever possible, emit a message advising folks that the features
1705-
// `arbitrary_self_types` or `arbitrary_self_types_pointers` might
1706-
// have helped.
1707-
None if receiver_is_valid(
1708-
wfcx,
1709-
span,
1710-
receiver_ty,
1711-
self_ty,
1712-
Some(ArbitrarySelfTypesLevel::Basic),
1713-
) =>
1714-
{
1715-
// Report error; would have worked with `arbitrary_self_types`.
1716-
feature_err(
1717-
&tcx.sess,
1718-
sym::arbitrary_self_types,
1719-
span,
1720-
format!(
1721-
"`{receiver_ty}` cannot be used as the type of `self` without \
1722-
the `arbitrary_self_types` feature",
1723-
),
1724-
)
1725-
.with_help(fluent::hir_analysis_invalid_receiver_ty_help)
1726-
.emit()
1727-
}
1728-
None | Some(ArbitrarySelfTypesLevel::Basic)
1729-
if receiver_is_valid(
1701+
let impl_block_def_id =
1702+
tcx.impl_of_method(method.def_id).unwrap_or(method.def_id).expect_local();
1703+
1704+
let receiver_validity = enter_wf_checking_ctxt(tcx, span, impl_block_def_id, |wfcx| {
1705+
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level) {
1706+
return Err(match arbitrary_self_types_level {
1707+
// Wherever possible, emit a message advising folks that the features
1708+
// `arbitrary_self_types` or `arbitrary_self_types_pointers` might
1709+
// have helped.
1710+
None if receiver_is_valid(
17301711
wfcx,
17311712
span,
17321713
receiver_ty,
17331714
self_ty,
1734-
Some(ArbitrarySelfTypesLevel::WithPointers),
1715+
Some(ArbitrarySelfTypesLevel::Basic),
17351716
) =>
1736-
{
1737-
// Report error; would have worked with `arbitrary_self_types_pointers`.
1738-
feature_err(
1739-
&tcx.sess,
1740-
sym::arbitrary_self_types_pointers,
1741-
span,
1742-
format!(
1743-
"`{receiver_ty}` cannot be used as the type of `self` without \
1744-
the `arbitrary_self_types_pointers` feature",
1745-
),
1746-
)
1747-
.with_help(fluent::hir_analysis_invalid_receiver_ty_help)
1748-
.emit()
1749-
}
1750-
_ =>
1751-
// Report error; would not have worked with `arbitrary_self_types[_pointers]`.
1752-
{
1753-
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
1754-
}
1755-
});
1756-
}
1757-
Ok(())
1717+
{
1718+
// Report error; would have worked with `arbitrary_self_types`.
1719+
feature_err(
1720+
&tcx.sess,
1721+
sym::arbitrary_self_types,
1722+
span,
1723+
format!(
1724+
"`{receiver_ty}` cannot be used as the type of `self` without \
1725+
the `arbitrary_self_types` feature",
1726+
),
1727+
)
1728+
.with_help(fluent::hir_analysis_invalid_receiver_ty_help)
1729+
.emit()
1730+
}
1731+
None | Some(ArbitrarySelfTypesLevel::Basic)
1732+
if receiver_is_valid(
1733+
wfcx,
1734+
span,
1735+
receiver_ty,
1736+
self_ty,
1737+
Some(ArbitrarySelfTypesLevel::WithPointers),
1738+
) =>
1739+
{
1740+
// Report error; would have worked with `arbitrary_self_types_pointers`.
1741+
feature_err(
1742+
&tcx.sess,
1743+
sym::arbitrary_self_types_pointers,
1744+
span,
1745+
format!(
1746+
"`{receiver_ty}` cannot be used as the type of `self` without \
1747+
the `arbitrary_self_types_pointers` feature",
1748+
),
1749+
)
1750+
.with_help(fluent::hir_analysis_invalid_receiver_ty_help)
1751+
.emit()
1752+
}
1753+
_ =>
1754+
// Report error; would not have worked with `arbitrary_self_types[_pointers]`.
1755+
{
1756+
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
1757+
}
1758+
});
1759+
}
1760+
Ok(())
1761+
});
1762+
receiver_validity
17581763
}
17591764

17601765
/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If

compiler/rustc_hir_typeck/src/method/confirm.rs

-3
Original file line numberDiff line numberDiff line change
@@ -516,9 +516,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
516516
self.register_predicates(obligations);
517517
}
518518
Err(terr) => {
519-
// FIXME(arbitrary_self_types): We probably should limit the
520-
// situations where this can occur by adding additional restrictions
521-
// to the feature, like the self type can't reference method args.
522519
if self.tcx.features().arbitrary_self_types {
523520
self.err_ctxt()
524521
.report_mismatched_types(&cause, method_self_ty, self_ty, terr)

src/tools/tidy/src/issues.txt

-1
Original file line numberDiff line numberDiff line change
@@ -4122,7 +4122,6 @@ ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
41224122
ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs
41234123
ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs
41244124
ui/type-alias-impl-trait/issue-57611-trait-alias.rs
4125-
ui/type-alias-impl-trait/issue-57700.rs
41264125
ui/type-alias-impl-trait/issue-57807-associated-type.rs
41274126
ui/type-alias-impl-trait/issue-57961.rs
41284127
ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs

tests/ui/self/arbitrary-self-from-method-substs-ice.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::ops::Deref;
88
struct Foo(u32);
99
impl Foo {
1010
const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
11-
//~^ ERROR: `R` cannot be used as the type of `self`
11+
//~^ ERROR invalid generic `self` parameter type
1212
//~| ERROR destructor of `R` cannot be evaluated at compile-time
1313
self.0
1414
//~^ ERROR cannot borrow here, since the borrowed element may contain interior mutability

tests/ui/self/arbitrary-self-from-method-substs-ice.stderr

+4-6
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,16 @@ LL | const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
2929
LL | }
3030
| - value is dropped here
3131

32-
error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
32+
error[E0799]: invalid generic `self` parameter type: `R`
3333
--> $DIR/arbitrary-self-from-method-substs-ice.rs:10:49
3434
|
3535
LL | const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
3636
| ^
3737
|
38-
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
39-
= help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
40-
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
41-
= help: 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`)
38+
= note: type of `self` must not be a method generic parameter type
39+
= help: 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`)
4240

4341
error: aborting due to 4 previous errors
4442

45-
Some errors have detailed explanations: E0015, E0493, E0658.
43+
Some errors have detailed explanations: E0015, E0493, E0658, E0799.
4644
For more information about an error, try `rustc --explain E0015`.
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,168 @@
1-
error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
2-
--> $DIR/arbitrary-self-from-method-substs.rs:8:43
1+
error[E0799]: invalid generic `self` parameter type: `R`
2+
--> $DIR/arbitrary-self-from-method-substs.rs:9:43
33
|
44
LL | fn get<R: Deref<Target = Self>>(self: R) -> u32 {
55
| ^
66
|
7+
= note: type of `self` must not be a method generic parameter type
8+
= help: 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`)
9+
10+
error[E0799]: invalid generic `self` parameter type: `&R`
11+
--> $DIR/arbitrary-self-from-method-substs.rs:13:44
12+
|
13+
LL | fn get1<R: Deref<Target = Self>>(self: &R) -> u32 {
14+
| ^^
15+
|
16+
= note: type of `self` must not be a method generic parameter type
17+
= help: 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`)
18+
19+
error[E0799]: invalid generic `self` parameter type: `&mut R`
20+
--> $DIR/arbitrary-self-from-method-substs.rs:17:44
21+
|
22+
LL | fn get2<R: Deref<Target = Self>>(self: &mut R) -> u32 {
23+
| ^^^^^^
24+
|
25+
= note: type of `self` must not be a method generic parameter type
26+
= help: 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`)
27+
28+
error[E0799]: invalid generic `self` parameter type: `Rc<R>`
29+
--> $DIR/arbitrary-self-from-method-substs.rs:21:44
30+
|
31+
LL | fn get3<R: Deref<Target = Self>>(self: std::rc::Rc<R>) -> u32 {
32+
| ^^^^^^^^^^^^^^
33+
|
34+
= note: type of `self` must not be a method generic parameter type
35+
= help: 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`)
36+
37+
error[E0799]: invalid generic `self` parameter type: `&Rc<R>`
38+
--> $DIR/arbitrary-self-from-method-substs.rs:25:44
39+
|
40+
LL | fn get4<R: Deref<Target = Self>>(self: &std::rc::Rc<R>) -> u32 {
41+
| ^^^^^^^^^^^^^^^
42+
|
43+
= note: type of `self` must not be a method generic parameter type
44+
= help: 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`)
45+
46+
error[E0799]: invalid generic `self` parameter type: `Rc<&R>`
47+
--> $DIR/arbitrary-self-from-method-substs.rs:29:44
48+
|
49+
LL | fn get5<R: Deref<Target = Self>>(self: std::rc::Rc<&R>) -> u32 {
50+
| ^^^^^^^^^^^^^^^
51+
|
52+
= note: type of `self` must not be a method generic parameter type
53+
= help: 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`)
54+
55+
error[E0658]: `<FR as FindReceiver>::Receiver` cannot be used as the type of `self` without the `arbitrary_self_types` feature
56+
--> $DIR/arbitrary-self-from-method-substs.rs:33:37
57+
|
58+
LL | fn get6<FR: FindReceiver>(self: FR::Receiver, other: FR) -> u32 {
59+
| ^^^^^^^^^^^^
60+
|
761
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
862
= help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
963
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
1064
= help: 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`)
1165

12-
error: aborting due to 1 previous error
66+
error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
67+
--> $DIR/arbitrary-self-from-method-substs.rs:61:18
68+
|
69+
LL | fn get(self: R) {}
70+
| ^
71+
|
72+
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
73+
= help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
74+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
75+
= help: 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`)
76+
77+
error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
78+
--> $DIR/arbitrary-self-from-method-substs.rs:92:9
79+
|
80+
LL | foo.get6(Silly);
81+
| ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
82+
|
83+
note: expected this to be `Rc<Foo>`
84+
--> $DIR/arbitrary-self-from-method-substs.rs:71:21
85+
|
86+
LL | type Receiver = std::rc::Rc<Foo>;
87+
| ^^^^^^^^^^^^^^^^
88+
= note: expected struct `Rc<Foo>`
89+
found struct `Foo`
90+
91+
error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
92+
--> $DIR/arbitrary-self-from-method-substs.rs:96:9
93+
|
94+
LL | foo.get6(Silly);
95+
| ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
96+
|
97+
note: expected this to be `Rc<Foo>`
98+
--> $DIR/arbitrary-self-from-method-substs.rs:71:21
99+
|
100+
LL | type Receiver = std::rc::Rc<Foo>;
101+
| ^^^^^^^^^^^^^^^^
102+
= note: expected struct `Rc<Foo>`
103+
found reference `&Foo`
104+
105+
error[E0599]: the method `get` exists for struct `Rc<Bar<_>>`, but its trait bounds were not satisfied
106+
--> $DIR/arbitrary-self-from-method-substs.rs:100:7
107+
|
108+
LL | struct Bar<R>(std::marker::PhantomData<R>);
109+
| ------------- doesn't satisfy `Bar<_>: Deref`
110+
...
111+
LL | t.get();
112+
| ^^^ method cannot be called on `Rc<Bar<_>>` due to unsatisfied trait bounds
113+
|
114+
note: the following trait bounds were not satisfied:
115+
`<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
116+
`<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
117+
`<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
118+
`<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
119+
`<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
120+
`Bar<_>: Deref`
121+
--> $DIR/arbitrary-self-from-method-substs.rs:60:9
122+
|
123+
LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
124+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------
125+
| | |
126+
| | unsatisfied trait bound introduced here
127+
| unsatisfied trait bound introduced here
128+
note: the trait `Deref` must be implemented
129+
--> $SRC_DIR/core/src/ops/deref.rs:LL:COL
130+
= help: items from traits can only be used if the trait is implemented and in scope
131+
= note: the following trait defines an item `get`, perhaps you need to implement it:
132+
candidate #1: `SliceIndex`
133+
134+
error[E0599]: the method `get` exists for reference `&Rc<Bar<_>>`, but its trait bounds were not satisfied
135+
--> $DIR/arbitrary-self-from-method-substs.rs:108:7
136+
|
137+
LL | struct Bar<R>(std::marker::PhantomData<R>);
138+
| ------------- doesn't satisfy `Bar<_>: Deref`
139+
...
140+
LL | t.get();
141+
| ^^^ method cannot be called on `&Rc<Bar<_>>` due to unsatisfied trait bounds
142+
|
143+
note: the following trait bounds were not satisfied:
144+
`<&&Rc<Bar<_>> as Deref>::Target = Bar<&&Rc<Bar<_>>>`
145+
`<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
146+
`<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
147+
`<&mut &Rc<Bar<_>> as Deref>::Target = Bar<&mut &Rc<Bar<_>>>`
148+
`<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
149+
`<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
150+
`<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
151+
`Bar<_>: Deref`
152+
--> $DIR/arbitrary-self-from-method-substs.rs:60:9
153+
|
154+
LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
155+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------
156+
| | |
157+
| | unsatisfied trait bound introduced here
158+
| unsatisfied trait bound introduced here
159+
note: the trait `Deref` must be implemented
160+
--> $SRC_DIR/core/src/ops/deref.rs:LL:COL
161+
= help: items from traits can only be used if the trait is implemented and in scope
162+
= note: the following trait defines an item `get`, perhaps you need to implement it:
163+
candidate #1: `SliceIndex`
164+
165+
error: aborting due to 12 previous errors
13166

14-
For more information about this error, try `rustc --explain E0658`.
167+
Some errors have detailed explanations: E0271, E0599, E0658, E0799.
168+
For more information about an error, try `rustc --explain E0271`.

0 commit comments

Comments
 (0)