Skip to content

Commit 33b923f

Browse files
committed
Auto merge of #53324 - alexreg:self_in_typedefs, r=eddyb
`Self` in type definitions (self_in_typedefs) This implements the [`self_in_typedefs` feature](https://github.com/rust-lang/rfcs/blob/master/text/2300-self-in-typedefs.md) ([tracking issue 49303](#49303)). r? @eddyb CC @Centril
2 parents f034141 + 4e7d3f5 commit 33b923f

File tree

7 files changed

+153
-37
lines changed

7 files changed

+153
-37
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# `self_in_typedefs`
2+
3+
The tracking issue for this feature is: [#49303]
4+
5+
[#49303]: https://github.com/rust-lang/rust/issues/49303
6+
7+
------------------------
8+
9+
The `self_in_typedefs` feature gate lets you use the special `Self` identifier
10+
in `struct`, `enum`, and `union` type definitions.
11+
12+
A simple example is:
13+
14+
```rust
15+
#![feature(self_in_typedefs)]
16+
17+
enum List<T>
18+
where
19+
Self: PartialOrd<Self> // can write `Self` instead of `List<T>`
20+
{
21+
Nil,
22+
Cons(T, Box<Self>) // likewise here
23+
}
24+
```

src/librustc_resolve/diagnostics.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -770,17 +770,18 @@ match x {
770770
"##,
771771

772772
E0411: r##"
773-
The `Self` keyword was used outside an impl or a trait.
773+
The `Self` keyword was used outside an impl, trait, or type definition.
774774
775775
Erroneous code example:
776776
777777
```compile_fail,E0411
778-
<Self>::foo; // error: use of `Self` outside of an impl or trait
778+
<Self>::foo; // error: use of `Self` outside of an impl, trait, or type
779+
// definition
779780
```
780781
781782
The `Self` keyword represents the current type, which explains why it can only
782-
be used inside an impl or a trait. It gives access to the associated items of a
783-
type:
783+
be used inside an impl, trait, or type definition. It gives access to the
784+
associated items of a type:
784785
785786
```
786787
trait Foo {

src/librustc_resolve/lib.rs

+36-18
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
// except according to those terms.
1010

1111
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
12-
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
13-
html_root_url = "https://doc.rust-lang.org/nightly/")]
12+
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
13+
html_root_url = "https://doc.rust-lang.org/nightly/")]
1414

1515
#![feature(crate_visibility_modifier)]
1616
#![cfg_attr(not(stage0), feature(nll))]
@@ -2175,14 +2175,26 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
21752175
debug!("(resolving item) resolving {}", name);
21762176

21772177
match item.node {
2178-
ItemKind::Enum(_, ref generics) |
21792178
ItemKind::Ty(_, ref generics) |
2180-
ItemKind::Existential(_, ref generics) |
2181-
ItemKind::Struct(_, ref generics) |
2182-
ItemKind::Union(_, ref generics) |
2183-
ItemKind::Fn(_, _, ref generics, _) => {
2179+
ItemKind::Fn(_, _, ref generics, _) |
2180+
ItemKind::Existential(_, ref generics) => {
21842181
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind),
2185-
|this| visit::walk_item(this, item));
2182+
|this| visit::walk_item(this, item));
2183+
}
2184+
2185+
ItemKind::Enum(_, ref generics) |
2186+
ItemKind::Struct(_, ref generics) |
2187+
ItemKind::Union(_, ref generics) => {
2188+
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
2189+
let item_def_id = this.definitions.local_def_id(item.id);
2190+
if this.session.features_untracked().self_in_typedefs {
2191+
this.with_self_rib(Def::SelfTy(None, Some(item_def_id)), |this| {
2192+
visit::walk_item(this, item);
2193+
});
2194+
} else {
2195+
visit::walk_item(this, item);
2196+
}
2197+
});
21862198
}
21872199

21882200
ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
@@ -2470,13 +2482,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
24702482
let item_def_id = this.definitions.local_def_id(item_id);
24712483
this.with_self_rib(Def::SelfTy(trait_id, Some(item_def_id)), |this| {
24722484
if let Some(trait_ref) = opt_trait_reference.as_ref() {
2473-
// Resolve type arguments in trait path
2485+
// Resolve type arguments in the trait path.
24742486
visit::walk_trait_ref(this, trait_ref);
24752487
}
24762488
// Resolve the self type.
24772489
this.visit_ty(self_type);
24782490
// Resolve the type parameters.
24792491
this.visit_generics(generics);
2492+
// Resolve the items within the impl.
24802493
this.with_current_self_type(self_type, |this| {
24812494
for impl_item in impl_items {
24822495
this.resolve_visibility(&impl_item.vis);
@@ -2491,8 +2504,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
24912504
// If this is a trait impl, ensure the const
24922505
// exists in trait
24932506
this.check_trait_item(impl_item.ident,
2494-
ValueNS,
2495-
impl_item.span,
2507+
ValueNS,
2508+
impl_item.span,
24962509
|n, s| ConstNotMemberOfTrait(n, s));
24972510
this.with_constant_rib(|this|
24982511
visit::walk_impl_item(this, impl_item)
@@ -2502,8 +2515,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
25022515
// If this is a trait impl, ensure the method
25032516
// exists in trait
25042517
this.check_trait_item(impl_item.ident,
2505-
ValueNS,
2506-
impl_item.span,
2518+
ValueNS,
2519+
impl_item.span,
25072520
|n, s| MethodNotMemberOfTrait(n, s));
25082521

25092522
visit::walk_impl_item(this, impl_item);
@@ -2512,8 +2525,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
25122525
// If this is a trait impl, ensure the type
25132526
// exists in trait
25142527
this.check_trait_item(impl_item.ident,
2515-
TypeNS,
2516-
impl_item.span,
2528+
TypeNS,
2529+
impl_item.span,
25172530
|n, s| TypeNotMemberOfTrait(n, s));
25182531

25192532
this.visit_ty(ty);
@@ -2522,8 +2535,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
25222535
// If this is a trait impl, ensure the type
25232536
// exists in trait
25242537
this.check_trait_item(impl_item.ident,
2525-
TypeNS,
2526-
impl_item.span,
2538+
TypeNS,
2539+
impl_item.span,
25272540
|n, s| TypeNotMemberOfTrait(n, s));
25282541

25292542
for bound in bounds {
@@ -2948,7 +2961,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
29482961
if is_self_type(path, ns) {
29492962
__diagnostic_used!(E0411);
29502963
err.code(DiagnosticId::Error("E0411".into()));
2951-
err.span_label(span, "`Self` is only available in traits and impls");
2964+
let available_in = if this.session.features_untracked().self_in_typedefs {
2965+
"impls, traits, and type definitions"
2966+
} else {
2967+
"traits and impls"
2968+
};
2969+
err.span_label(span, format!("`Self` is only available in {}", available_in));
29522970
return (err, Vec::new());
29532971
}
29542972
if is_self_value(path, ns) {

src/libsyntax/feature_gate.rs

+21-15
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ declare_features! (
127127
(active, thread_local, "1.0.0", Some(29594), None),
128128
(active, trace_macros, "1.0.0", Some(29598), None),
129129

130-
// rustc internal, for now:
130+
// rustc internal, for now
131131
(active, intrinsics, "1.0.0", None, None),
132132
(active, lang_items, "1.0.0", None, None),
133133
(active, format_args_nl, "1.29.0", None, None),
@@ -157,6 +157,7 @@ declare_features! (
157157
(active, optin_builtin_traits, "1.0.0", Some(13231), None),
158158

159159
// Allows use of #[staged_api]
160+
//
160161
// rustc internal
161162
(active, staged_api, "1.0.0", None, None),
162163

@@ -234,24 +235,25 @@ declare_features! (
234235
// Allows associated type defaults
235236
(active, associated_type_defaults, "1.2.0", Some(29661), None),
236237

237-
// allow `repr(simd)`, and importing the various simd intrinsics
238+
// Allows `repr(simd)`, and importing the various simd intrinsics
238239
(active, repr_simd, "1.4.0", Some(27731), None),
239240

240-
// allow `extern "platform-intrinsic" { ... }`
241+
// Allows `extern "platform-intrinsic" { ... }`
241242
(active, platform_intrinsics, "1.4.0", Some(27731), None),
242243

243-
// allow `#[unwind(..)]`
244+
// Allows `#[unwind(..)]`
244245
// rustc internal for rust runtime
245246
(active, unwind_attributes, "1.4.0", None, None),
246247

247-
// allow the use of `#[naked]` on functions.
248+
// Allows the use of `#[naked]` on functions.
248249
(active, naked_functions, "1.9.0", Some(32408), None),
249250

250-
// allow `#[no_debug]`
251+
// Allows `#[no_debug]`
251252
(active, no_debug, "1.5.0", Some(29721), None),
252253

253-
// allow `#[omit_gdb_pretty_printer_section]`
254-
// rustc internal.
254+
// Allows `#[omit_gdb_pretty_printer_section]`
255+
//
256+
// rustc internal
255257
(active, omit_gdb_pretty_printer_section, "1.5.0", None, None),
256258

257259
// Allows cfg(target_vendor = "...").
@@ -281,10 +283,10 @@ declare_features! (
281283
// The `!` type. Does not imply exhaustive_patterns (below) any more.
282284
(active, never_type, "1.13.0", Some(35121), None),
283285

284-
// Allows exhaustive pattern matching on types that contain uninhabited types.
286+
// Allows exhaustive pattern matching on types that contain uninhabited types
285287
(active, exhaustive_patterns, "1.13.0", Some(51085), None),
286288

287-
// Allows all literals in attribute lists and values of key-value pairs.
289+
// Allows all literals in attribute lists and values of key-value pairs
288290
(active, attr_literals, "1.13.0", Some(34981), None),
289291

290292
// Allows untagged unions `union U { ... }`
@@ -321,6 +323,7 @@ declare_features! (
321323
(active, sanitizer_runtime, "1.17.0", None, None),
322324

323325
// Used to identify crates that contain the profiler runtime
326+
//
324327
// rustc internal
325328
(active, profiler_runtime, "1.18.0", None, None),
326329

@@ -378,7 +381,7 @@ declare_features! (
378381
// extern types
379382
(active, extern_types, "1.23.0", Some(43467), None),
380383

381-
// Allow trait methods with arbitrary self types
384+
// Allows trait methods with arbitrary self types
382385
(active, arbitrary_self_types, "1.23.0", Some(44874), None),
383386

384387
// `crate` in paths
@@ -387,7 +390,7 @@ declare_features! (
387390
// In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`)
388391
(active, in_band_lifetimes, "1.23.0", Some(44524), None),
389392

390-
// generic associated types (RFC 1598)
393+
// Generic associated types (RFC 1598)
391394
(active, generic_associated_types, "1.23.0", Some(44265), None),
392395

393396
// Resolve absolute paths as paths from other crates
@@ -462,7 +465,7 @@ declare_features! (
462465
// Scoped lints
463466
(active, tool_lints, "1.28.0", Some(44690), None),
464467

465-
// allow irrefutable patterns in if-let and while-let statements (RFC 2086)
468+
// Allows irrefutable patterns in if-let and while-let statements (RFC 2086)
466469
(active, irrefutable_let_patterns, "1.27.0", Some(44495), None),
467470

468471
// Allows use of the :literal macro fragment specifier (RFC 1576)
@@ -492,11 +495,14 @@ declare_features! (
492495
// impl Debug for Foo<'_>
493496
(active, impl_header_lifetime_elision, "1.30.0", Some(15872), Some(Edition::Edition2018)),
494497

495-
// Support for arbitrary delimited token streams in non-macro attributes.
498+
// Support for arbitrary delimited token streams in non-macro attributes
496499
(active, unrestricted_attribute_tokens, "1.30.0", Some(44690), None),
497500

498-
// Allows `use x::y;` to resolve through `self::x`, not just `::x`.
501+
// Allows `use x::y;` to resolve through `self::x`, not just `::x`
499502
(active, uniform_paths, "1.30.0", Some(53130), None),
503+
504+
// Allows `Self` in type definitions
505+
(active, self_in_typedefs, "1.30.0", Some(49303), None),
500506
);
501507

502508
declare_features! (

src/test/run-pass/self-in-typedefs.rs

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(self_in_typedefs)]
12+
#![feature(untagged_unions)]
13+
14+
#![allow(dead_code)]
15+
16+
enum A<'a, T: 'a>
17+
where
18+
Self: Send, T: PartialEq<Self>
19+
{
20+
Foo(&'a Self),
21+
Bar(T),
22+
}
23+
24+
struct B<'a, T: 'a>
25+
where
26+
Self: Send, T: PartialEq<Self>
27+
{
28+
foo: &'a Self,
29+
bar: T,
30+
}
31+
32+
union C<'a, T: 'a>
33+
where
34+
Self: Send, T: PartialEq<Self>
35+
{
36+
foo: &'a Self,
37+
bar: T,
38+
}
39+
40+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
enum StackList<'a, T: 'a> {
12+
Nil,
13+
Cons(T, &'a Self)
14+
//~^ ERROR cannot find type `Self` in this scope
15+
//~| `Self` is only available in traits and impls
16+
}
17+
18+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0411]: cannot find type `Self` in this scope
2+
--> $DIR/feature-gate-self-in-typedefs.rs:13:17
3+
|
4+
LL | Cons(T, &'a Self)
5+
| ^^^^ `Self` is only available in traits and impls
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0411`.

0 commit comments

Comments
 (0)