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](https://github.com/rust-lang/rust/issues/49303)). r? @eddyb CC @Centril
This commit is contained in:
commit
33b923fd44
7 changed files with 153 additions and 37 deletions
|
@ -0,0 +1,24 @@
|
|||
# `self_in_typedefs`
|
||||
|
||||
The tracking issue for this feature is: [#49303]
|
||||
|
||||
[#49303]: https://github.com/rust-lang/rust/issues/49303
|
||||
|
||||
------------------------
|
||||
|
||||
The `self_in_typedefs` feature gate lets you use the special `Self` identifier
|
||||
in `struct`, `enum`, and `union` type definitions.
|
||||
|
||||
A simple example is:
|
||||
|
||||
```rust
|
||||
#![feature(self_in_typedefs)]
|
||||
|
||||
enum List<T>
|
||||
where
|
||||
Self: PartialOrd<Self> // can write `Self` instead of `List<T>`
|
||||
{
|
||||
Nil,
|
||||
Cons(T, Box<Self>) // likewise here
|
||||
}
|
||||
```
|
|
@ -770,17 +770,18 @@ match x {
|
|||
"##,
|
||||
|
||||
E0411: r##"
|
||||
The `Self` keyword was used outside an impl or a trait.
|
||||
The `Self` keyword was used outside an impl, trait, or type definition.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0411
|
||||
<Self>::foo; // error: use of `Self` outside of an impl or trait
|
||||
<Self>::foo; // error: use of `Self` outside of an impl, trait, or type
|
||||
// definition
|
||||
```
|
||||
|
||||
The `Self` keyword represents the current type, which explains why it can only
|
||||
be used inside an impl or a trait. It gives access to the associated items of a
|
||||
type:
|
||||
be used inside an impl, trait, or type definition. It gives access to the
|
||||
associated items of a type:
|
||||
|
||||
```
|
||||
trait Foo {
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
// except according to those terms.
|
||||
|
||||
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![cfg_attr(not(stage0), feature(nll))]
|
||||
|
@ -2175,14 +2175,26 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||
debug!("(resolving item) resolving {}", name);
|
||||
|
||||
match item.node {
|
||||
ItemKind::Enum(_, ref generics) |
|
||||
ItemKind::Ty(_, ref generics) |
|
||||
ItemKind::Existential(_, ref generics) |
|
||||
ItemKind::Struct(_, ref generics) |
|
||||
ItemKind::Union(_, ref generics) |
|
||||
ItemKind::Fn(_, _, ref generics, _) => {
|
||||
ItemKind::Fn(_, _, ref generics, _) |
|
||||
ItemKind::Existential(_, ref generics) => {
|
||||
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind),
|
||||
|this| visit::walk_item(this, item));
|
||||
|this| visit::walk_item(this, item));
|
||||
}
|
||||
|
||||
ItemKind::Enum(_, ref generics) |
|
||||
ItemKind::Struct(_, ref generics) |
|
||||
ItemKind::Union(_, ref generics) => {
|
||||
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
|
||||
let item_def_id = this.definitions.local_def_id(item.id);
|
||||
if this.session.features_untracked().self_in_typedefs {
|
||||
this.with_self_rib(Def::SelfTy(None, Some(item_def_id)), |this| {
|
||||
visit::walk_item(this, item);
|
||||
});
|
||||
} else {
|
||||
visit::walk_item(this, item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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> {
|
|||
let item_def_id = this.definitions.local_def_id(item_id);
|
||||
this.with_self_rib(Def::SelfTy(trait_id, Some(item_def_id)), |this| {
|
||||
if let Some(trait_ref) = opt_trait_reference.as_ref() {
|
||||
// Resolve type arguments in trait path
|
||||
// Resolve type arguments in the trait path.
|
||||
visit::walk_trait_ref(this, trait_ref);
|
||||
}
|
||||
// Resolve the self type.
|
||||
this.visit_ty(self_type);
|
||||
// Resolve the type parameters.
|
||||
this.visit_generics(generics);
|
||||
// Resolve the items within the impl.
|
||||
this.with_current_self_type(self_type, |this| {
|
||||
for impl_item in impl_items {
|
||||
this.resolve_visibility(&impl_item.vis);
|
||||
|
@ -2491,8 +2504,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||
// If this is a trait impl, ensure the const
|
||||
// exists in trait
|
||||
this.check_trait_item(impl_item.ident,
|
||||
ValueNS,
|
||||
impl_item.span,
|
||||
ValueNS,
|
||||
impl_item.span,
|
||||
|n, s| ConstNotMemberOfTrait(n, s));
|
||||
this.with_constant_rib(|this|
|
||||
visit::walk_impl_item(this, impl_item)
|
||||
|
@ -2502,8 +2515,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||
// If this is a trait impl, ensure the method
|
||||
// exists in trait
|
||||
this.check_trait_item(impl_item.ident,
|
||||
ValueNS,
|
||||
impl_item.span,
|
||||
ValueNS,
|
||||
impl_item.span,
|
||||
|n, s| MethodNotMemberOfTrait(n, s));
|
||||
|
||||
visit::walk_impl_item(this, impl_item);
|
||||
|
@ -2512,8 +2525,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||
// If this is a trait impl, ensure the type
|
||||
// exists in trait
|
||||
this.check_trait_item(impl_item.ident,
|
||||
TypeNS,
|
||||
impl_item.span,
|
||||
TypeNS,
|
||||
impl_item.span,
|
||||
|n, s| TypeNotMemberOfTrait(n, s));
|
||||
|
||||
this.visit_ty(ty);
|
||||
|
@ -2522,8 +2535,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||
// If this is a trait impl, ensure the type
|
||||
// exists in trait
|
||||
this.check_trait_item(impl_item.ident,
|
||||
TypeNS,
|
||||
impl_item.span,
|
||||
TypeNS,
|
||||
impl_item.span,
|
||||
|n, s| TypeNotMemberOfTrait(n, s));
|
||||
|
||||
for bound in bounds {
|
||||
|
@ -2948,7 +2961,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||
if is_self_type(path, ns) {
|
||||
__diagnostic_used!(E0411);
|
||||
err.code(DiagnosticId::Error("E0411".into()));
|
||||
err.span_label(span, "`Self` is only available in traits and impls");
|
||||
let available_in = if this.session.features_untracked().self_in_typedefs {
|
||||
"impls, traits, and type definitions"
|
||||
} else {
|
||||
"traits and impls"
|
||||
};
|
||||
err.span_label(span, format!("`Self` is only available in {}", available_in));
|
||||
return (err, Vec::new());
|
||||
}
|
||||
if is_self_value(path, ns) {
|
||||
|
|
|
@ -127,7 +127,7 @@ declare_features! (
|
|||
(active, thread_local, "1.0.0", Some(29594), None),
|
||||
(active, trace_macros, "1.0.0", Some(29598), None),
|
||||
|
||||
// rustc internal, for now:
|
||||
// rustc internal, for now
|
||||
(active, intrinsics, "1.0.0", None, None),
|
||||
(active, lang_items, "1.0.0", None, None),
|
||||
(active, format_args_nl, "1.29.0", None, None),
|
||||
|
@ -157,6 +157,7 @@ declare_features! (
|
|||
(active, optin_builtin_traits, "1.0.0", Some(13231), None),
|
||||
|
||||
// Allows use of #[staged_api]
|
||||
//
|
||||
// rustc internal
|
||||
(active, staged_api, "1.0.0", None, None),
|
||||
|
||||
|
@ -234,24 +235,25 @@ declare_features! (
|
|||
// Allows associated type defaults
|
||||
(active, associated_type_defaults, "1.2.0", Some(29661), None),
|
||||
|
||||
// allow `repr(simd)`, and importing the various simd intrinsics
|
||||
// Allows `repr(simd)`, and importing the various simd intrinsics
|
||||
(active, repr_simd, "1.4.0", Some(27731), None),
|
||||
|
||||
// allow `extern "platform-intrinsic" { ... }`
|
||||
// Allows `extern "platform-intrinsic" { ... }`
|
||||
(active, platform_intrinsics, "1.4.0", Some(27731), None),
|
||||
|
||||
// allow `#[unwind(..)]`
|
||||
// Allows `#[unwind(..)]`
|
||||
// rustc internal for rust runtime
|
||||
(active, unwind_attributes, "1.4.0", None, None),
|
||||
|
||||
// allow the use of `#[naked]` on functions.
|
||||
// Allows the use of `#[naked]` on functions.
|
||||
(active, naked_functions, "1.9.0", Some(32408), None),
|
||||
|
||||
// allow `#[no_debug]`
|
||||
// Allows `#[no_debug]`
|
||||
(active, no_debug, "1.5.0", Some(29721), None),
|
||||
|
||||
// allow `#[omit_gdb_pretty_printer_section]`
|
||||
// rustc internal.
|
||||
// Allows `#[omit_gdb_pretty_printer_section]`
|
||||
//
|
||||
// rustc internal
|
||||
(active, omit_gdb_pretty_printer_section, "1.5.0", None, None),
|
||||
|
||||
// Allows cfg(target_vendor = "...").
|
||||
|
@ -281,10 +283,10 @@ declare_features! (
|
|||
// The `!` type. Does not imply exhaustive_patterns (below) any more.
|
||||
(active, never_type, "1.13.0", Some(35121), None),
|
||||
|
||||
// Allows exhaustive pattern matching on types that contain uninhabited types.
|
||||
// Allows exhaustive pattern matching on types that contain uninhabited types
|
||||
(active, exhaustive_patterns, "1.13.0", Some(51085), None),
|
||||
|
||||
// Allows all literals in attribute lists and values of key-value pairs.
|
||||
// Allows all literals in attribute lists and values of key-value pairs
|
||||
(active, attr_literals, "1.13.0", Some(34981), None),
|
||||
|
||||
// Allows untagged unions `union U { ... }`
|
||||
|
@ -321,6 +323,7 @@ declare_features! (
|
|||
(active, sanitizer_runtime, "1.17.0", None, None),
|
||||
|
||||
// Used to identify crates that contain the profiler runtime
|
||||
//
|
||||
// rustc internal
|
||||
(active, profiler_runtime, "1.18.0", None, None),
|
||||
|
||||
|
@ -378,7 +381,7 @@ declare_features! (
|
|||
// extern types
|
||||
(active, extern_types, "1.23.0", Some(43467), None),
|
||||
|
||||
// Allow trait methods with arbitrary self types
|
||||
// Allows trait methods with arbitrary self types
|
||||
(active, arbitrary_self_types, "1.23.0", Some(44874), None),
|
||||
|
||||
// `crate` in paths
|
||||
|
@ -387,7 +390,7 @@ declare_features! (
|
|||
// In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`)
|
||||
(active, in_band_lifetimes, "1.23.0", Some(44524), None),
|
||||
|
||||
// generic associated types (RFC 1598)
|
||||
// Generic associated types (RFC 1598)
|
||||
(active, generic_associated_types, "1.23.0", Some(44265), None),
|
||||
|
||||
// Resolve absolute paths as paths from other crates
|
||||
|
@ -462,7 +465,7 @@ declare_features! (
|
|||
// Scoped lints
|
||||
(active, tool_lints, "1.28.0", Some(44690), None),
|
||||
|
||||
// allow irrefutable patterns in if-let and while-let statements (RFC 2086)
|
||||
// Allows irrefutable patterns in if-let and while-let statements (RFC 2086)
|
||||
(active, irrefutable_let_patterns, "1.27.0", Some(44495), None),
|
||||
|
||||
// Allows use of the :literal macro fragment specifier (RFC 1576)
|
||||
|
@ -492,11 +495,14 @@ declare_features! (
|
|||
// impl Debug for Foo<'_>
|
||||
(active, impl_header_lifetime_elision, "1.30.0", Some(15872), Some(Edition::Edition2018)),
|
||||
|
||||
// Support for arbitrary delimited token streams in non-macro attributes.
|
||||
// Support for arbitrary delimited token streams in non-macro attributes
|
||||
(active, unrestricted_attribute_tokens, "1.30.0", Some(44690), None),
|
||||
|
||||
// Allows `use x::y;` to resolve through `self::x`, not just `::x`.
|
||||
// Allows `use x::y;` to resolve through `self::x`, not just `::x`
|
||||
(active, uniform_paths, "1.30.0", Some(53130), None),
|
||||
|
||||
// Allows `Self` in type definitions
|
||||
(active, self_in_typedefs, "1.30.0", Some(49303), None),
|
||||
);
|
||||
|
||||
declare_features! (
|
||||
|
|
40
src/test/run-pass/self-in-typedefs.rs
Normal file
40
src/test/run-pass/self-in-typedefs.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(self_in_typedefs)]
|
||||
#![feature(untagged_unions)]
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
enum A<'a, T: 'a>
|
||||
where
|
||||
Self: Send, T: PartialEq<Self>
|
||||
{
|
||||
Foo(&'a Self),
|
||||
Bar(T),
|
||||
}
|
||||
|
||||
struct B<'a, T: 'a>
|
||||
where
|
||||
Self: Send, T: PartialEq<Self>
|
||||
{
|
||||
foo: &'a Self,
|
||||
bar: T,
|
||||
}
|
||||
|
||||
union C<'a, T: 'a>
|
||||
where
|
||||
Self: Send, T: PartialEq<Self>
|
||||
{
|
||||
foo: &'a Self,
|
||||
bar: T,
|
||||
}
|
||||
|
||||
fn main() {}
|
18
src/test/ui/feature-gates/feature-gate-self-in-typedefs.rs
Normal file
18
src/test/ui/feature-gates/feature-gate-self-in-typedefs.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
enum StackList<'a, T: 'a> {
|
||||
Nil,
|
||||
Cons(T, &'a Self)
|
||||
//~^ ERROR cannot find type `Self` in this scope
|
||||
//~| `Self` is only available in traits and impls
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,9 @@
|
|||
error[E0411]: cannot find type `Self` in this scope
|
||||
--> $DIR/feature-gate-self-in-typedefs.rs:13:17
|
||||
|
|
||||
LL | Cons(T, &'a Self)
|
||||
| ^^^^ `Self` is only available in traits and impls
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0411`.
|
Loading…
Reference in a new issue