From 856e84f9a315ec7e6bb7069710c9c9e9b8b7a076 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Tue, 14 Aug 2018 02:49:06 +0100 Subject: [PATCH 1/5] Resolve `Self` within type definitions. Currently type definitions include `struct`, `enum`, `union`, `existential type`. --- src/librustc_resolve/lib.rs | 39 +++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 992ea12ffa2b1..072240eeef4a9 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2192,14 +2192,22 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { self.check_proc_macro_attrs(&item.attrs); 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); + this.with_self_rib(Def::SelfTy(None, Some(item_def_id)), |this| { + visit::walk_item(this, item); + }); + }); } ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) => @@ -2489,13 +2497,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.check_proc_macro_attrs(&impl_item.attrs); @@ -2511,8 +2520,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) @@ -2522,8 +2531,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); @@ -2532,8 +2541,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); @@ -2542,8 +2551,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 { From 79009ed728f73b92d5e53b4212844e2dbc51ac5f Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Tue, 14 Aug 2018 18:29:53 +0100 Subject: [PATCH 2/5] Updated diagnostics. --- src/librustc_resolve/diagnostics.rs | 8 ++++---- src/librustc_resolve/lib.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 6593e239bc302..794e57a1ab2c8 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -770,17 +770,17 @@ 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 -::foo; // error: use of `Self` outside of an impl or trait +::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 { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 072240eeef4a9..2ce2173e2e455 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2977,7 +2977,7 @@ 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"); + err.span_label(span, "`Self` is only available in traits, impls, and type definitions"); return (err, Vec::new()); } if is_self_value(path, ns) { From cbcabcaac8d06c5c7f68e794b4e3ceb41253b8c1 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Tue, 14 Aug 2018 18:45:44 +0100 Subject: [PATCH 3/5] Added feature gate. --- src/librustc_resolve/diagnostics.rs | 3 +- src/librustc_resolve/lib.rs | 15 ++++++-- src/libsyntax/feature_gate.rs | 36 +++++++++++-------- .../feature-gate-self-in-typedefs.rs | 18 ++++++++++ .../feature-gate-self-in-typedefs.stderr | 9 +++++ 5 files changed, 62 insertions(+), 19 deletions(-) create mode 100644 src/test/ui/feature-gates/feature-gate-self-in-typedefs.rs create mode 100644 src/test/ui/feature-gates/feature-gate-self-in-typedefs.stderr diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 794e57a1ab2c8..c1dc3041d7d17 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -775,7 +775,8 @@ The `Self` keyword was used outside an impl, trait, or type definition. Erroneous code example: ```compile_fail,E0411 -::foo; // error: use of `Self` outside of an impl, trait, or type definition +::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 diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2ce2173e2e455..faf129eb8365a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2204,9 +2204,13 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { ItemKind::Union(_, ref generics) => { self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| { let item_def_id = this.definitions.local_def_id(item.id); - this.with_self_rib(Def::SelfTy(None, Some(item_def_id)), |this| { + 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); - }); + } }); } @@ -2977,7 +2981,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, impls, and type definitions"); + 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) { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 56e69b9df9e04..0626442aa42f3 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -138,7 +138,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), @@ -168,6 +168,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), @@ -245,24 +246,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 = "..."). @@ -292,10 +294,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 { ... }` @@ -334,6 +336,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), @@ -391,7 +394,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 @@ -400,7 +403,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 @@ -475,7 +478,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) @@ -505,11 +508,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! ( diff --git a/src/test/ui/feature-gates/feature-gate-self-in-typedefs.rs b/src/test/ui/feature-gates/feature-gate-self-in-typedefs.rs new file mode 100644 index 0000000000000..4b476a0a645b1 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-self-in-typedefs.rs @@ -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 or the MIT license +// , 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() {} diff --git a/src/test/ui/feature-gates/feature-gate-self-in-typedefs.stderr b/src/test/ui/feature-gates/feature-gate-self-in-typedefs.stderr new file mode 100644 index 0000000000000..c3f9abd90a7f1 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-self-in-typedefs.stderr @@ -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`. From 7920a65c5ff8bde8a80b0c350de949c39b3a407d Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Wed, 15 Aug 2018 02:24:05 +0100 Subject: [PATCH 4/5] Added tests. --- src/test/run-pass/self-in-typedefs.rs | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/test/run-pass/self-in-typedefs.rs diff --git a/src/test/run-pass/self-in-typedefs.rs b/src/test/run-pass/self-in-typedefs.rs new file mode 100644 index 0000000000000..d262e8c60a18e --- /dev/null +++ b/src/test/run-pass/self-in-typedefs.rs @@ -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 or the MIT license +// , 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 +{ + Foo(&'a Self), + Bar(T), +} + +struct B<'a, T: 'a> +where + Self: Send, T: PartialEq +{ + foo: &'a Self, + bar: T, +} + +union C<'a, T: 'a> +where + Self: Send, T: PartialEq +{ + foo: &'a Self, + bar: T, +} + +fn main() {} From 4e7d3f5a5eb9db95194cbb672f081c2ad9647674 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Tue, 14 Aug 2018 21:26:33 +0100 Subject: [PATCH 5/5] Added page for feature to unstable book. --- .../src/language-features/self-in-typedefs.md | 24 +++++++++++++++++++ src/librustc_resolve/lib.rs | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 src/doc/unstable-book/src/language-features/self-in-typedefs.md diff --git a/src/doc/unstable-book/src/language-features/self-in-typedefs.md b/src/doc/unstable-book/src/language-features/self-in-typedefs.md new file mode 100644 index 0000000000000..2416e85c17d1f --- /dev/null +++ b/src/doc/unstable-book/src/language-features/self-in-typedefs.md @@ -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 +where + Self: PartialOrd // can write `Self` instead of `List` +{ + Nil, + Cons(T, Box) // likewise here +} +``` diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index faf129eb8365a..5becf5034d9a2 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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))]