]> git.lizzy.rs Git - rust.git/commitdiff
introduce SelfCtor
authorF001 <changchun.fan@qq.com>
Thu, 6 Sep 2018 02:46:55 +0000 (10:46 +0800)
committerF001 <changchun.fan@qq.com>
Thu, 13 Sep 2018 04:27:29 +0000 (12:27 +0800)
30 files changed:
src/doc/unstable-book/src/language-features/self-struct-ctor.md [new file with mode: 0644]
src/doc/unstable-book/src/language-features/tuple-struct-self-ctor.md [deleted file]
src/librustc/hir/def.rs
src/librustc/hir/lowering.rs
src/librustc/ich/impls_hir.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/stability.rs
src/librustc/ty/mod.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_passes/rvalue_promotion.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_save_analysis/lib.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/mod.rs
src/librustdoc/clean/inline.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/visit_ast.rs
src/libsyntax/feature_gate.rs
src/test/run-pass/tuple-struct-self-ctor.rs [deleted file]
src/test/ui/feature-gates/feature-gate-self-struct-ctor.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-self-struct-ctor.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-tuple-struct-self-ctor.rs [deleted file]
src/test/ui/feature-gates/feature-gate-tuple-struct-self-ctor.stderr [deleted file]
src/test/ui/keyword/keyword-self-as-identifier.rs
src/test/ui/keyword/keyword-self-as-identifier.stderr
src/test/ui/run-pass/rfcs/rfc-2302-self-struct-ctor.rs [new file with mode: 0644]
src/test/ui/self/self_type_keyword-2.rs
src/test/ui/self/self_type_keyword-2.stderr

diff --git a/src/doc/unstable-book/src/language-features/self-struct-ctor.md b/src/doc/unstable-book/src/language-features/self-struct-ctor.md
new file mode 100644 (file)
index 0000000..b4742c4
--- /dev/null
@@ -0,0 +1,33 @@
+# `self_struct_ctor`
+
+The tracking issue for this feature is: [#51994]
+[#51994]: https://github.com/rust-lang/rust/issues/51994
+
+------------------------
+
+The `self_struct_ctor` feature gate lets you use the special `Self`
+identifier as a constructor and a pattern.
+
+A simple example is:
+
+```rust
+#![feature(self_struct_ctor)]
+
+struct ST(i32, i32);
+
+impl ST {
+    fn new() -> Self {
+        ST(0, 1)
+    }
+
+    fn ctor() -> Self {
+        Self(1,2)           // constructed by `Self`, it is the same as `ST(1, 2)`
+    }
+
+    fn pattern(self) {
+        match self {
+            Self(x, y) => println!("{} {}", x, y), // used as a pattern
+        }
+    }
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/tuple-struct-self-ctor.md b/src/doc/unstable-book/src/language-features/tuple-struct-self-ctor.md
deleted file mode 100644 (file)
index 7ea52eb..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-# `tuple_struct_self_ctor`
-
-The tracking issue for this feature is: [#51994]
-[#51994]: https://github.com/rust-lang/rust/issues/51994
-
-------------------------
-
-The `tuple_struct_self_ctor` feature gate lets you use the special `Self`
-identifier as a constructor and a pattern.
-
-A simple example is:
-
-```rust
-#![feature(tuple_struct_self_ctor)]
-
-struct ST(i32, i32);
-
-impl ST {
-    fn new() -> Self {
-        ST(0, 1)
-    }
-
-    fn ctor() -> Self {
-        Self(1,2)           // constructed by `Self`, it is the same as `ST(1, 2)`
-    }
-
-    fn pattern(self) {
-        match self {
-            Self(x, y) => println!("{} {}", x, y), // used as a pattern
-        }
-    }
-}
-```
index b10f4785f16377d3e08cef3fdd7d12928e845048..4286b0628f5fff76f7054e69d74650287483850e 100644 (file)
@@ -69,6 +69,7 @@ pub enum Def {
     Static(DefId, bool /* is_mutbl */),
     StructCtor(DefId, CtorKind), // DefId refers to NodeId of the struct's constructor
     VariantCtor(DefId, CtorKind), // DefId refers to the enum variant
+    SelfCtor(DefId /* impl */),  // DefId refers to the impl
     Method(DefId),
     AssociatedConst(DefId),
 
@@ -272,7 +273,8 @@ pub fn def_id(&self) -> DefId {
             Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
             Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
             Def::AssociatedConst(id) | Def::Macro(id, ..) |
-            Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) => {
+            Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) |
+            Def::SelfCtor(id) => {
                 id
             }
 
@@ -309,6 +311,7 @@ pub fn kind_name(&self) -> &'static str {
             Def::StructCtor(.., CtorKind::Fn) => "tuple struct",
             Def::StructCtor(.., CtorKind::Const) => "unit struct",
             Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
+            Def::SelfCtor(..) => "self constructor",
             Def::Union(..) => "union",
             Def::Trait(..) => "trait",
             Def::ForeignTy(..) => "foreign type",
index 34b3eb0a8c8bf64d1fd595377f2f028d89dcaf3f..45628e2b6f3b80f2e336b19cf8bea0dd405e044a 100644 (file)
@@ -67,6 +67,7 @@
 use syntax::ast::*;
 use syntax::errors;
 use syntax::ext::hygiene::{Mark, SyntaxContext};
+use syntax::feature_gate::{emit_feature_err, GateIssue};
 use syntax::print::pprust;
 use syntax::ptr::P;
 use syntax::source_map::{self, respan, CompilerDesugaringKind, Spanned};
@@ -3429,19 +3430,24 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                     ParamMode::Optional,
                     ImplTraitContext::Disallowed,
                 );
+                self.check_self_struct_ctor_feature(&qpath);
                 hir::PatKind::TupleStruct(
                     qpath,
                     pats.iter().map(|x| self.lower_pat(x)).collect(),
                     ddpos,
                 )
             }
-            PatKind::Path(ref qself, ref path) => hir::PatKind::Path(self.lower_qpath(
-                p.id,
-                qself,
-                path,
-                ParamMode::Optional,
-                ImplTraitContext::Disallowed,
-            )),
+            PatKind::Path(ref qself, ref path) => {
+                let qpath = self.lower_qpath(
+                    p.id,
+                    qself,
+                    path,
+                    ParamMode::Optional,
+                    ImplTraitContext::Disallowed,
+                );
+                self.check_self_struct_ctor_feature(&qpath);
+                hir::PatKind::Path(qpath)
+            }
             PatKind::Struct(ref path, ref fields, etc) => {
                 let qpath = self.lower_qpath(
                     p.id,
@@ -3828,13 +3834,17 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                     attrs: e.attrs.clone(),
                 };
             }
-            ExprKind::Path(ref qself, ref path) => hir::ExprKind::Path(self.lower_qpath(
-                e.id,
-                qself,
-                path,
-                ParamMode::Optional,
-                ImplTraitContext::Disallowed,
-            )),
+            ExprKind::Path(ref qself, ref path) => {
+                let qpath = self.lower_qpath(
+                    e.id,
+                    qself,
+                    path,
+                    ParamMode::Optional,
+                    ImplTraitContext::Disallowed,
+                );
+                self.check_self_struct_ctor_feature(&qpath);
+                hir::ExprKind::Path(qpath)
+            }
             ExprKind::Break(opt_label, ref opt_expr) => {
                 let destination = if self.is_in_loop_condition && opt_label.is_none() {
                     hir::Destination {
@@ -4815,6 +4825,18 @@ fn wrap_in_try_constructor(
                                             ThinVec::new()));
         P(self.expr_call(e.span, from_err, hir_vec![e]))
     }
+
+    fn check_self_struct_ctor_feature(&self, qp: &hir::QPath) {
+        if let hir::QPath::Resolved(_, ref p) = qp {
+            if p.segments.len() == 1 &&
+               p.segments[0].ident.name == keywords::SelfType.name() &&
+               !self.sess.features_untracked().self_struct_ctor {
+                emit_feature_err(&self.sess.parse_sess, "self_struct_ctor",
+                                 p.span, GateIssue::Language,
+                                 "`Self` struct constructors are unstable");
+            }
+        }
+    }
 }
 
 fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body>) -> Vec<hir::BodyId> {
index 3f1899bc54fb4c2e1e34b1c548cb51fcc3726e6b..bc2eb5f442b47df373d9173d2cea1f627a8a9f9e 100644 (file)
@@ -1021,6 +1021,7 @@ fn to_stable_hash_key(&self,
     Const(def_id),
     Static(def_id, is_mutbl),
     StructCtor(def_id, ctor_kind),
+    SelfCtor(impl_def_id),
     VariantCtor(def_id, ctor_kind),
     Method(def_id),
     AssociatedConst(def_id),
index b63cde0f205f78031363d851a4e6d718291f8620..172511474710d6e47c6cf27b4eb6751c04fed669 100644 (file)
@@ -708,7 +708,7 @@ pub fn cat_def(&self,
 
         match def {
           Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) |
-          Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) => {
+          Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => {
                 Ok(self.cat_rvalue_node(hir_id, span, expr_ty))
           }
 
@@ -1288,7 +1288,7 @@ fn cat_pattern_<F>(&self, mut cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McR
                     (self.cat_downcast_if_needed(pat, cmt, def_id),
                      self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len())
                 }
-                Def::StructCtor(_, CtorKind::Fn) => {
+                Def::StructCtor(_, CtorKind::Fn) | Def::SelfCtor(..) => {
                     match self.pat_ty_unadjusted(&pat)?.sty {
                         ty::Adt(adt_def, _) => {
                             (cmt, adt_def.non_enum_variant().fields.len())
index f237c5b397bd5263722c7ab089f0760ac12a605f..73a55265f009ac017844f2de1aa755f83ca36104 100644 (file)
@@ -783,7 +783,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
     fn visit_path(&mut self, path: &'tcx hir::Path, id: hir::HirId) {
         let id = self.tcx.hir.hir_to_node_id(id);
         match path.def {
-            Def::Local(..) | Def::Upvar(..) |
+            Def::Local(..) | Def::Upvar(..) | Def::SelfCtor(..) |
             Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => {}
             _ => self.tcx.check_stability(path.def.def_id(), Some(id), path.span)
         }
index a48aabc3cd7c7379c1f4a1a2de070fc89212e9e3..d9e3bdaf266a9a76a8d19210b18f8a78a321edbe 100644 (file)
@@ -2134,7 +2134,8 @@ pub fn variant_of_def(&self, def: Def) -> &VariantDef {
         match def {
             Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid),
             Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
-            Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => self.non_enum_variant(),
+            Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) |
+            Def::SelfCtor(..) => self.non_enum_variant(),
             _ => bug!("unexpected def {:?} in variant_of_def", def)
         }
     }
index 055f238e5db4ea12f2c03d6a079d7ff2fe70b5ea..510e7eb9c63f79e483b6d5b8a898786066560c65 100644 (file)
@@ -273,7 +273,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                             Def::VariantCtor(variant_id, CtorKind::Fn) => {
                                 Some((adt_def, adt_def.variant_index_with_id(variant_id)))
                             }
-                            Def::StructCtor(_, CtorKind::Fn) => Some((adt_def, 0)),
+                            Def::StructCtor(_, CtorKind::Fn) |
+                            Def::SelfCtor(..) => Some((adt_def, 0)),
                             _ => None,
                         }
                     })
@@ -759,6 +760,25 @@ fn user_annotated_ty_for_def(
                 sty => bug!("unexpected sty: {:?}", sty),
             },
 
+        // `Self` is used in expression as a tuple struct constructor or an unit struct constructor
+        Def::SelfCtor(_) => {
+            let sty = &cx.tables().node_id_to_type(hir_id).sty;
+            match sty {
+                ty::FnDef(ref def_id, _) => {
+                    Some(cx.tables().user_substs(hir_id)?.unchecked_map(|user_substs| {
+                        // Here, we just pair a `DefId` with the
+                        // `user_substs`, so no new types etc are introduced.
+                        cx.tcx().mk_fn_def(*def_id, user_substs)
+                    }))
+                }
+                ty::Adt(ref adt_def, _) => {
+                    user_annotated_ty_for_adt(cx, hir_id, adt_def)
+                }
+                _ => {
+                    bug!("unexpected sty: {:?}", sty)
+                }
+            }
+        }
         _ =>
             bug!("user_annotated_ty_for_def: unexpected def {:?} at {:?}", def, hir_id)
     }
@@ -857,7 +877,8 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         Def::Fn(_) |
         Def::Method(_) |
         Def::StructCtor(_, CtorKind::Fn) |
-        Def::VariantCtor(_, CtorKind::Fn) => {
+        Def::VariantCtor(_, CtorKind::Fn) |
+        Def::SelfCtor(..) => {
             let user_ty = user_annotated_ty_for_def(cx, expr.hir_id, &def);
             ExprKind::Literal {
                 literal: ty::Const::zero_sized(
index ee50322fbb355b2700760d7b04c09f7caf47bb30..57519d6ad7d70908524d3a404be7aa5662a28202 100644 (file)
@@ -667,7 +667,7 @@ fn lower_variant_or_leaf(
             }
 
             Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
-            Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => {
+            Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => {
                 PatternKind::Leaf { subpatterns: subpatterns }
             }
 
index 74b010f57b01d7c1279b7375ef0ddb1c30210cd4..828800465209e857447a768f767c03459cd2f4ad 100644 (file)
@@ -376,7 +376,7 @@ fn check_expr_kind<'a, 'tcx>(
             let def = v.tables.qpath_def(qpath, e.hir_id);
             match def {
                 Def::VariantCtor(..) | Def::StructCtor(..) |
-                Def::Fn(..) | Def::Method(..) => Promotable,
+                Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => Promotable,
 
                 // References to a static that are themselves within a static
                 // are inherently promotable with the exception
@@ -441,7 +441,8 @@ fn check_expr_kind<'a, 'tcx>(
             };
             let def_result = match def {
                 Def::StructCtor(_, CtorKind::Fn) |
-                Def::VariantCtor(_, CtorKind::Fn) => Promotable,
+                Def::VariantCtor(_, CtorKind::Fn) |
+                Def::SelfCtor(..) => Promotable,
                 Def::Fn(did) => {
                     v.handle_const_fn_call(did, node_ty, e.span)
                 }
index c7aea641e35d42e0eb0b9dcd92fc80c828d269cb..d1a05964c8f6497c0993fc342a40ee201c7e1817 100644 (file)
@@ -585,7 +585,6 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                                                    CtorKind::from_ast(struct_def));
                     self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion));
                     self.struct_constructors.insert(def.def_id(), (ctor_def, ctor_vis));
-                    self.tuple_structs.insert(def.def_id(), ctor_def);
                 }
             }
 
@@ -704,7 +703,6 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, chi
                         self.cstore.def_key(def_id).parent
                             .map(|index| DefId { krate: def_id.krate, index: index }) {
                     self.struct_constructors.insert(struct_def_id, (def, vis));
-                    self.tuple_structs.insert(struct_def_id, def);
                 }
             }
             Def::Trait(..) => {
index f2d46c0510c756801481e79d612145ac44d5c80a..384d3ed744a9a14ccd785bbd7ba5e9129c9d1292 100644 (file)
@@ -558,17 +558,21 @@ fn is_expected(self, def: Def) -> bool {
                 Def::StructCtor(_, CtorKind::Const) | Def::StructCtor(_, CtorKind::Fn) |
                 Def::VariantCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Fn) |
                 Def::Const(..) | Def::Static(..) | Def::Local(..) | Def::Upvar(..) |
-                Def::Fn(..) | Def::Method(..) | Def::AssociatedConst(..) => true,
+                Def::Fn(..) | Def::Method(..) | Def::AssociatedConst(..) |
+                Def::SelfCtor(..) => true,
                 _ => false,
             },
             PathSource::Pat => match def {
                 Def::StructCtor(_, CtorKind::Const) |
                 Def::VariantCtor(_, CtorKind::Const) |
-                Def::Const(..) | Def::AssociatedConst(..) => true,
+                Def::Const(..) | Def::AssociatedConst(..) |
+                Def::SelfCtor(..) => true,
                 _ => false,
             },
             PathSource::TupleStruct => match def {
-                Def::StructCtor(_, CtorKind::Fn) | Def::VariantCtor(_, CtorKind::Fn) => true,
+                Def::StructCtor(_, CtorKind::Fn) |
+                Def::VariantCtor(_, CtorKind::Fn) |
+                Def::SelfCtor(..) => true,
                 _ => false,
             },
             PathSource::Struct => match def {
@@ -1463,9 +1467,6 @@ pub struct Resolver<'a, 'b: 'a> {
     /// it's not used during normal resolution, only for better error reporting.
     struct_constructors: DefIdMap<(Def, ty::Visibility)>,
 
-    /// Map from tuple struct's DefId to VariantData's Def
-    tuple_structs: DefIdMap<Def>,
-
     /// Only used for better errors on `fn(): fn()`
     current_type_ascription: Vec<Span>,
 
@@ -1767,7 +1768,6 @@ pub fn new(session: &'a Session,
             warned_proc_macros: FxHashSet(),
             potentially_unused_imports: Vec::new(),
             struct_constructors: DefIdMap(),
-            tuple_structs: DefIdMap(),
             found_unresolved_macro: false,
             unused_macros: FxHashSet(),
             current_type_ascription: Vec::new(),
@@ -2233,23 +2233,8 @@ fn resolve_item(&mut self, item: &Item) {
                                              |this| visit::walk_item(this, item));
             }
 
-            ItemKind::Struct(ref variant, ref generics) => {
-                if variant.is_tuple() || variant.is_unit() {
-                    if let Some(def_id) = self.definitions.opt_local_def_id(item.id) {
-                        if let Some(variant_id) = self.definitions.opt_local_def_id(variant.id()) {
-                            let variant_def = if variant.is_tuple() {
-                                Def::StructCtor(variant_id, CtorKind::Fn)
-                            } else {
-                                Def::StructCtor(variant_id, CtorKind::Const)
-                            };
-                            self.tuple_structs.insert(def_id, variant_def);
-                        }
-                    }
-                }
-                self.resolve_adt(item, generics);
-            }
-
             ItemKind::Enum(_, ref generics) |
+            ItemKind::Struct(_, ref generics) |
             ItemKind::Union(_, ref generics) => {
                 self.resolve_adt(item, generics);
             }
@@ -2526,30 +2511,15 @@ fn with_self_rib<F>(&mut self, self_def: Def, f: F)
         self.ribs[TypeNS].pop();
     }
 
-    fn with_tuple_struct_self_ctor_rib<F>(&mut self, self_ty: &Ty, f: F)
+    fn with_self_struct_ctor_rib<F>(&mut self, impl_id: DefId, f: F)
         where F: FnOnce(&mut Resolver)
     {
-        let variant_def = if self.session.features_untracked().tuple_struct_self_ctor {
-            let base_def = self.def_map.get(&self_ty.id).map(|r| r.base_def());
-            if let Some(Def::Struct(ref def_id)) = base_def {
-                self.tuple_structs.get(def_id).cloned()
-            } else {
-                None
-            }
-        } else {
-            None
-        };
-
-        // when feature gate is enabled and `Self` is a tuple struct
-        if let Some(variant_def) = variant_def {
-            let mut self_type_rib = Rib::new(NormalRibKind);
-            self_type_rib.bindings.insert(keywords::SelfType.ident(), variant_def);
-            self.ribs[ValueNS].push(self_type_rib);
-            f(self);
-            self.ribs[ValueNS].pop();
-        } else {
-            f(self);
-        }
+        let self_def = Def::SelfCtor(impl_id);
+        let mut self_type_rib = Rib::new(NormalRibKind);
+        self_type_rib.bindings.insert(keywords::SelfType.ident(), self_def);
+        self.ribs[ValueNS].push(self_type_rib);
+        f(self);
+        self.ribs[ValueNS].pop();
     }
 
     fn resolve_implementation(&mut self,
@@ -2576,64 +2546,65 @@ fn resolve_implementation(&mut self,
                         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);
-
-                                // We also need a new scope for the impl item type parameters.
-                                let type_parameters = HasTypeParameters(&impl_item.generics,
-                                                                        TraitOrImplItemRibKind);
-                                this.with_type_parameter_rib(type_parameters, |this| {
-                                    use self::ResolutionError::*;
-                                    match impl_item.node {
-                                        ImplItemKind::Const(..) => {
-                                            // If this is a trait impl, ensure the const
-                                            // exists in trait
-                                            this.check_trait_item(impl_item.ident,
-                                                                  ValueNS,
-                                                                  impl_item.span,
-                                                |n, s| ConstNotMemberOfTrait(n, s));
-                                            this.with_constant_rib(|this|
-                                                visit::walk_impl_item(this, impl_item)
-                                            );
-                                        }
-                                        ImplItemKind::Method(..) => {
-                                            // If this is a trait impl, ensure the method
-                                            // exists in trait
-                                            this.check_trait_item(impl_item.ident,
-                                                                  ValueNS,
-                                                                  impl_item.span,
-                                                |n, s| MethodNotMemberOfTrait(n, s));
-                                            this.with_tuple_struct_self_ctor_rib(self_type, |this| {
+                            this.with_self_struct_ctor_rib(item_def_id, |this| {
+                                for impl_item in impl_items {
+                                    this.resolve_visibility(&impl_item.vis);
+
+                                    // We also need a new scope for the impl item type parameters.
+                                    let type_parameters = HasTypeParameters(&impl_item.generics,
+                                                                            TraitOrImplItemRibKind);
+                                    this.with_type_parameter_rib(type_parameters, |this| {
+                                        use self::ResolutionError::*;
+                                        match impl_item.node {
+                                            ImplItemKind::Const(..) => {
+                                                // If this is a trait impl, ensure the const
+                                                // exists in trait
+                                                this.check_trait_item(impl_item.ident,
+                                                                      ValueNS,
+                                                                      impl_item.span,
+                                                    |n, s| ConstNotMemberOfTrait(n, s));
+                                                this.with_constant_rib(|this|
+                                                    visit::walk_impl_item(this, impl_item)
+                                                );
+                                            }
+                                            ImplItemKind::Method(..) => {
+                                                // If this is a trait impl, ensure the method
+                                                // exists in trait
+                                                this.check_trait_item(impl_item.ident,
+                                                                      ValueNS,
+                                                                      impl_item.span,
+                                                    |n, s| MethodNotMemberOfTrait(n, s));
+
                                                 visit::walk_impl_item(this, impl_item);
-                                            });
-                                        }
-                                        ImplItemKind::Type(ref ty) => {
-                                            // If this is a trait impl, ensure the type
-                                            // exists in trait
-                                            this.check_trait_item(impl_item.ident,
-                                                                  TypeNS,
-                                                                  impl_item.span,
-                                                |n, s| TypeNotMemberOfTrait(n, s));
-
-                                            this.visit_ty(ty);
-                                        }
-                                        ImplItemKind::Existential(ref bounds) => {
-                                            // If this is a trait impl, ensure the type
-                                            // exists in trait
-                                            this.check_trait_item(impl_item.ident,
-                                                                  TypeNS,
-                                                                  impl_item.span,
-                                                |n, s| TypeNotMemberOfTrait(n, s));
-
-                                            for bound in bounds {
-                                                this.visit_param_bound(bound);
                                             }
+                                            ImplItemKind::Type(ref ty) => {
+                                                // If this is a trait impl, ensure the type
+                                                // exists in trait
+                                                this.check_trait_item(impl_item.ident,
+                                                                      TypeNS,
+                                                                      impl_item.span,
+                                                    |n, s| TypeNotMemberOfTrait(n, s));
+
+                                                this.visit_ty(ty);
+                                            }
+                                            ImplItemKind::Existential(ref bounds) => {
+                                                // If this is a trait impl, ensure the type
+                                                // exists in trait
+                                                this.check_trait_item(impl_item.ident,
+                                                                      TypeNS,
+                                                                      impl_item.span,
+                                                    |n, s| TypeNotMemberOfTrait(n, s));
+
+                                                for bound in bounds {
+                                                    this.visit_param_bound(bound);
+                                                }
+                                            }
+                                            ImplItemKind::Macro(_) =>
+                                                panic!("unexpanded macro in resolve!"),
                                         }
-                                        ImplItemKind::Macro(_) =>
-                                            panic!("unexpanded macro in resolve!"),
-                                    }
-                                });
-                            }
+                                    });
+                                }
+                            });
                         });
                     });
                 });
index 8d6a75ecc59257eb83b66c5d4090327824ee7b41..c9bae297031fffe6a976551e62acb5b17d74e46a 100644 (file)
@@ -813,6 +813,7 @@ fn fn_type(path: &ast::Path) -> bool {
             HirDef::Macro(..) |
             HirDef::ToolMod |
             HirDef::NonMacroAttr(..) |
+            HirDef::SelfCtor(..) |
             HirDef::Err => None,
         }
     }
index 2a8ee4bd8df0eeeb9feb5e19bbecb337641271c0..7733ea37c056cc6a8480cc97a1ad03ed4d32c712 100644 (file)
@@ -756,12 +756,13 @@ fn check_pat_path(&self,
             }
             Def::VariantCtor(_, CtorKind::Const) |
             Def::StructCtor(_, CtorKind::Const) |
+            Def::SelfCtor(..) |
             Def::Const(..) | Def::AssociatedConst(..) => {} // OK
             _ => bug!("unexpected pattern definition: {:?}", def)
         }
 
         // Type check the path.
-        let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
+        let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id).0;
         self.demand_suptype(pat.span, expected, pat_ty);
         pat_ty
     }
@@ -791,6 +792,24 @@ fn check_pat_tuple_struct(&self,
 
         // Resolve the path and check the definition for errors.
         let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
+        if def == Def::Err {
+            self.set_tainted_by_errors();
+            on_error();
+            return self.tcx.types.err;
+        }
+
+        // Type check the path.
+        let (pat_ty, def) = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
+        if !pat_ty.is_fn() {
+            report_unexpected_def(def);
+            return self.tcx.types.err;
+        }
+        // Replace constructor type with constructed type for tuple struct patterns.
+        let pat_ty = pat_ty.fn_sig(tcx).output();
+        let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type");
+
+        self.demand_eqtype(pat.span, expected, pat_ty);
+
         let variant = match def {
             Def::Err => {
                 self.set_tainted_by_errors();
@@ -807,15 +826,6 @@ fn check_pat_tuple_struct(&self,
             }
             _ => bug!("unexpected pattern definition: {:?}", def)
         };
-
-        // Type check the path.
-        let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
-        // Replace constructor type with constructed type for tuple struct patterns.
-        let pat_ty = pat_ty.fn_sig(tcx).output();
-        let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type");
-
-        self.demand_eqtype(pat.span, expected, pat_ty);
-
         // Type check subpatterns.
         if subpats.len() == variant.fields.len() ||
                 subpats.len() < variant.fields.len() && ddpos.is_some() {
index 9ab269702db1c8d99c8fd4a04d2719fbecb82fae..6a8860a3d9d06985e05b0cc08bf0eaeda1fdf18b 100644 (file)
@@ -3898,7 +3898,7 @@ fn check_expr_kind(&self,
             hir::ExprKind::Path(ref qpath) => {
                 let (def, opt_ty, segs) = self.resolve_ty_and_def_ufcs(qpath, expr.id, expr.span);
                 let ty = if def != Def::Err {
-                    self.instantiate_value_path(segs, opt_ty, def, expr.span, id)
+                    self.instantiate_value_path(segs, opt_ty, def, expr.span, id).0
                 } else {
                     self.set_tainted_by_errors();
                     tcx.types.err
@@ -4923,7 +4923,8 @@ fn def_ids_for_path_segments(&self,
         match def {
             // Case 1. Reference to a struct/variant constructor.
             Def::StructCtor(def_id, ..) |
-            Def::VariantCtor(def_id, ..) => {
+            Def::VariantCtor(def_id, ..) |
+            Def::SelfCtor(.., def_id) => {
                 // Everything but the final segment should have no
                 // parameters at all.
                 let generics = self.tcx.generics_of(def_id);
@@ -4969,7 +4970,7 @@ pub fn instantiate_value_path(&self,
                                   def: Def,
                                   span: Span,
                                   node_id: ast::NodeId)
-                                  -> Ty<'tcx> {
+                                  -> (Ty<'tcx>, Def) {
         debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})",
                segments,
                def,
@@ -5019,7 +5020,7 @@ pub fn instantiate_value_path(&self,
                 let ty = self.local_ty(span, nid);
                 let ty = self.normalize_associated_types_in(span, &ty);
                 self.write_ty(self.tcx.hir.node_to_hir_id(node_id), ty);
-                return ty;
+                return (ty, def);
             }
             _ => {}
         }
@@ -5056,7 +5057,28 @@ pub fn instantiate_value_path(&self,
             self.tcx.generics_of(*def_id).has_self
         }).unwrap_or(false);
 
-        let def_id = def.def_id();
+        let mut new_def = def;
+        let (def_id, ty) = if let Def::SelfCtor(impl_def_id) = def {
+            let ty = self.impl_self_ty(span, impl_def_id).ty;
+
+            match ty.ty_adt_def() {
+                Some(adt_def) if adt_def.is_struct() => {
+                    let variant = adt_def.non_enum_variant();
+                    new_def = Def::StructCtor(variant.did, variant.ctor_kind);
+                    (variant.did, self.tcx.type_of(variant.did))
+                }
+                _ => {
+                    (impl_def_id, self.tcx.types.err)
+                }
+            }
+        } else {
+            let def_id = def.def_id();
+
+            // The things we are substituting into the type should not contain
+            // escaping late-bound regions, and nor should the base type scheme.
+            let ty = self.tcx.type_of(def_id);
+            (def_id, ty)
+        };
 
         let substs = AstConv::create_substs_for_generic_args(
             self.tcx,
@@ -5121,10 +5143,6 @@ pub fn instantiate_value_path(&self,
                 }
             },
         );
-
-        // The things we are substituting into the type should not contain
-        // escaping late-bound regions, and nor should the base type scheme.
-        let ty = self.tcx.type_of(def_id);
         assert!(!substs.has_escaping_regions());
         assert!(!ty.has_escaping_regions());
 
@@ -5168,7 +5186,7 @@ pub fn instantiate_value_path(&self,
 
         self.write_user_substs_from_substs(hir_id, substs);
 
-        ty_substituted
+        (ty_substituted, new_def)
     }
 
     fn check_rustc_args_require_const(&self,
index 75d7488d26a75ac67b9ae9c7474293511f1f15bb..507461f2ea175f9a24e1bd4d4537411e524a310d 100644 (file)
@@ -93,7 +93,8 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa
         // Assume that enum variants and struct types are re-exported next to
         // their constructors.
         Def::VariantCtor(..) |
-        Def::StructCtor(..) => return Some(Vec::new()),
+        Def::StructCtor(..) |
+        Def::SelfCtor(..) => return Some(Vec::new()),
         Def::Mod(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Module);
             clean::ModuleItem(build_module(cx, did, visited))
index cced30d1a0c205fc0fe19d6e73f6fb68d07f6a10..a60347e008f88d268650b0c31a12b9ee6e8c0936 100644 (file)
@@ -525,7 +525,9 @@ fn ambiguity_error(cx: &DocContext, attrs: &Attributes,
 fn value_ns_kind(def: Def, path_str: &str) -> Option<(&'static str, String)> {
     match def {
         // structs, variants, and mods exist in both namespaces. skip them
-        Def::StructCtor(..) | Def::Mod(..) | Def::Variant(..) | Def::VariantCtor(..) => None,
+        Def::StructCtor(..) | Def::Mod(..) | Def::Variant(..) |
+        Def::VariantCtor(..) | Def::SelfCtor(..)
+            => None,
         Def::Fn(..)
             => Some(("function", format!("{}()", path_str))),
         Def::Method(..)
index 451e24d6c0dc938ecf90a79c4bdb6462a388ba23..0aaf2d526f934a1fcc186a29267fdad3443b526a 100644 (file)
@@ -371,7 +371,7 @@ pub fn visit_item(&mut self, item: &hir::Item,
                 // struct and variant constructors always show up alongside their definitions, we've
                 // already processed them so just discard these.
                 match path.def {
-                    Def::StructCtor(..) | Def::VariantCtor(..) => return,
+                    Def::StructCtor(..) | Def::VariantCtor(..) | Def::SelfCtor(..) => return,
                     _ => {}
                 }
 
index 4d24abcf90eb33b3c3bb72d4ad9da8f1fee5be79..7266d807d3ba8644fa60ea4b4c5810f417b4f92d 100644 (file)
@@ -513,8 +513,8 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // Non-builtin attributes in inner attribute position
     (active, custom_inner_attributes, "1.30.0", Some(38356), None),
 
-    // tuple struct self constructor (RFC 2302)
-    (active, tuple_struct_self_ctor, "1.31.0", Some(51994), None),
+    // Self struct constructor  (RFC 2302)
+    (active, self_struct_ctor, "1.31.0", Some(51994), None),
 );
 
 declare_features! (
@@ -1739,15 +1739,6 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
             ast::ExprKind::Async(..) => {
                 gate_feature_post!(&self, async_await, e.span, "async blocks are unstable");
             }
-            ast::ExprKind::Call(ref callee, _) => {
-                if let ast::ExprKind::Path(_, ref p) = callee.node {
-                    if p.segments.len() == 1 &&
-                       p.segments[0].ident.name == keywords::SelfType.name() {
-                        gate_feature_post!(&self, tuple_struct_self_ctor, e.span,
-                            "tuple struct Self constructors are unstable");
-                    }
-                }
-            }
             _ => {}
         }
         visit::walk_expr(self, e);
diff --git a/src/test/run-pass/tuple-struct-self-ctor.rs b/src/test/run-pass/tuple-struct-self-ctor.rs
deleted file mode 100644 (file)
index 7392003..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-// 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(tuple_struct_self_ctor)]
-
-#![allow(dead_code)]
-
-use std::fmt::Display;
-
-struct ST1(i32, i32);
-
-impl ST1 {
-    fn new() -> Self {
-        ST1(0, 1)
-    }
-
-    fn ctor() -> Self {
-        Self(1,2)         // Self as a constructor
-    }
-
-    fn pattern(self) {
-        match self {
-            Self(x, y) => println!("{} {}", x, y), // Self as a pattern
-        }
-    }
-}
-
-struct ST2<T>(T); // With type parameter
-
-impl<T> ST2<T> where T: Display {
-
-    fn ctor(v: T) -> Self {
-        Self(v)
-    }
-
-    fn pattern(&self) {
-        match self {
-            Self(ref v) => println!("{}", v),
-        }
-    }
-}
-
-struct ST3<'a>(&'a i32); // With lifetime parameter
-
-impl<'a> ST3<'a> {
-
-    fn ctor(v: &'a i32) -> Self {
-        Self(v)
-    }
-
-    fn pattern(self) {
-        let Self(ref v) = self;
-        println!("{}", v);
-    }
-}
-
-struct ST4(usize);
-
-impl ST4 {
-    fn map(opt: Option<usize>) -> Option<Self> {
-        opt.map(Self)     // use `Self` as a function passed somewhere
-    }
-}
-
-struct ST5;               // unit struct
-
-impl ST5 {
-    fn ctor() -> Self {
-        Self               // `Self` as a unit struct value
-    }
-
-    fn pattern(self) -> Self {
-        match self {
-            Self => Self,   // `Self` as a unit struct value for matching
-        }
-    }
-}
-
-fn main() {
-    let v1 = ST1::ctor();
-    v1.pattern();
-
-    let v2 = ST2::ctor(10);
-    v2.pattern();
-
-    let local = 42;
-    let v3 = ST3::ctor(&local);
-    v3.pattern();
-
-    let v4 = Some(1usize);
-    let _ = ST4::map(v4);
-
-    let v5 = ST5::ctor();
-    v5.pattern();
-}
diff --git a/src/test/ui/feature-gates/feature-gate-self-struct-ctor.rs b/src/test/ui/feature-gates/feature-gate-self-struct-ctor.rs
new file mode 100644 (file)
index 0000000..98eab39
--- /dev/null
@@ -0,0 +1,22 @@
+struct ST1(i32, i32);
+
+impl ST1 {
+    fn ctor() -> Self {
+        Self(1,2)
+        //~^ ERROR: `Self` struct constructors are unstable (see issue #51994) [E0658]
+    }
+}
+
+struct ST2;
+
+impl ST2 {
+    fn ctor() -> Self {
+        Self
+        //~^ ERROR: `Self` struct constructors are unstable (see issue #51994) [E0658]
+    }
+}
+
+fn main() {
+    let _ = ST1::ctor();
+    let _ = ST2::ctor();
+}
diff --git a/src/test/ui/feature-gates/feature-gate-self-struct-ctor.stderr b/src/test/ui/feature-gates/feature-gate-self-struct-ctor.stderr
new file mode 100644 (file)
index 0000000..6061a0d
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0658]: `Self` struct constructors are unstable (see issue #51994)
+  --> $DIR/feature-gate-self-struct-ctor.rs:5:9
+   |
+LL |         Self(1,2)
+   |         ^^^^
+   |
+   = help: add #![feature(self_struct_ctor)] to the crate attributes to enable
+
+error[E0658]: `Self` struct constructors are unstable (see issue #51994)
+  --> $DIR/feature-gate-self-struct-ctor.rs:14:9
+   |
+LL |         Self
+   |         ^^^^
+   |
+   = help: add #![feature(self_struct_ctor)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-tuple-struct-self-ctor.rs b/src/test/ui/feature-gates/feature-gate-tuple-struct-self-ctor.rs
deleted file mode 100644 (file)
index aa907e8..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// 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.
-
-struct ST(i32, i32);
-
-impl ST {
-    fn ctor() -> Self {
-        Self(1,2)
-        //~^ ERROR: expected function, found self type `Self` [E0423]
-        //~^^ ERROR: tuple struct Self constructors are unstable (see issue #51994) [E0658]
-    }
-}
diff --git a/src/test/ui/feature-gates/feature-gate-tuple-struct-self-ctor.stderr b/src/test/ui/feature-gates/feature-gate-tuple-struct-self-ctor.stderr
deleted file mode 100644 (file)
index e92924e..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0423]: expected function, found self type `Self`
-  --> $DIR/feature-gate-tuple-struct-self-ctor.rs:15:9
-   |
-LL |         Self(1,2)
-   |         ^^^^ not a function
-   |
-   = note: can't use `Self` as a constructor, you must use the implemented struct
-
-error[E0658]: tuple struct Self constructors are unstable (see issue #51994)
-  --> $DIR/feature-gate-tuple-struct-self-ctor.rs:15:9
-   |
-LL |         Self(1,2)
-   |         ^^^^^^^^^
-   |
-   = help: add #![feature(tuple_struct_self_ctor)] to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-Some errors occurred: E0423, E0658.
-For more information about an error, try `rustc --explain E0423`.
index b50fc68bed6be587c24f1d525165931dfd543fb6..ad5b8fb64342d0aa469250f99c62101a2f24531f 100644 (file)
@@ -10,4 +10,5 @@
 
 fn main() {
     let Self = 22; //~ ERROR cannot find unit struct/variant or constant `Self` in this scope
+        //~^ ERROR `Self` struct constructors are unstable (see issue #51994)
 }
index c47f4aeabefd81f2cdcf53cceaef157cc3fdbefe..296269819f8364507501645c8b26ca448ea72c42 100644 (file)
@@ -4,6 +4,15 @@ error[E0531]: cannot find unit struct/variant or constant `Self` in this scope
 LL |     let Self = 22; //~ ERROR cannot find unit struct/variant or constant `Self` in this scope
    |         ^^^^ not found in this scope
 
-error: aborting due to previous error
+error[E0658]: `Self` struct constructors are unstable (see issue #51994)
+  --> $DIR/keyword-self-as-identifier.rs:12:9
+   |
+LL |     let Self = 22; //~ ERROR cannot find unit struct/variant or constant `Self` in this scope
+   |         ^^^^
+   |
+   = help: add #![feature(self_struct_ctor)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0531`.
+Some errors occurred: E0531, E0658.
+For more information about an error, try `rustc --explain E0531`.
diff --git a/src/test/ui/run-pass/rfcs/rfc-2302-self-struct-ctor.rs b/src/test/ui/run-pass/rfcs/rfc-2302-self-struct-ctor.rs
new file mode 100644 (file)
index 0000000..156e240
--- /dev/null
@@ -0,0 +1,129 @@
+// run-pass
+
+#![feature(self_struct_ctor)]
+
+#![allow(dead_code)]
+
+use std::fmt::Display;
+
+struct ST1(i32, i32);
+
+impl ST1 {
+    fn new() -> Self {
+        ST1(0, 1)
+    }
+
+    fn ctor() -> Self {
+        Self(1,2)         // Self as a constructor
+    }
+
+    fn pattern(self) {
+        match self {
+            Self(x, y) => println!("{} {}", x, y), // Self as a pattern
+        }
+    }
+}
+
+struct ST2<T>(T); // With type parameter
+
+impl<T> ST2<T> where T: Display {
+
+    fn ctor(v: T) -> Self {
+        Self(v)
+    }
+
+    fn pattern(&self) {
+        match self {
+            Self(ref v) => println!("{}", v),
+        }
+    }
+}
+
+struct ST3<'a>(&'a i32); // With lifetime parameter
+
+impl<'a> ST3<'a> {
+
+    fn ctor(v: &'a i32) -> Self {
+        Self(v)
+    }
+
+    fn pattern(self) {
+        let Self(ref v) = self;
+        println!("{}", v);
+    }
+}
+
+struct ST4(usize);
+
+impl ST4 {
+    fn map(opt: Option<usize>) -> Option<Self> {
+        opt.map(Self)     // use `Self` as a function passed somewhere
+    }
+}
+
+struct ST5;               // unit struct
+
+impl ST5 {
+    fn ctor() -> Self {
+        Self               // `Self` as a unit struct value
+    }
+
+    fn pattern(self) -> Self {
+        match self {
+            Self => Self,   // `Self` as a unit struct value for matching
+        }
+    }
+}
+
+struct ST6(i32);
+type T = ST6;
+impl T {
+    fn ctor() -> Self {
+        ST6(1)
+    }
+
+    fn type_alias(self) {
+        let Self(_x) = match self { Self(x) => Self(x) };
+        let _opt: Option<Self> = Some(0).map(Self);
+    }
+}
+
+struct ST7<T1, T2>(T1, T2);
+
+impl ST7<i32, usize> {
+
+    fn ctor() -> Self {
+        Self(1, 2)
+    }
+
+    fn pattern(self) -> Self {
+        match self {
+            Self(x, y) => Self(x, y),
+        }
+    }
+}
+
+fn main() {
+    let v1 = ST1::ctor();
+    v1.pattern();
+
+    let v2 = ST2::ctor(10);
+    v2.pattern();
+
+    let local = 42;
+    let v3 = ST3::ctor(&local);
+    v3.pattern();
+
+    let v4 = Some(1usize);
+    let _ = ST4::map(v4);
+
+    let v5 = ST5::ctor();
+    v5.pattern();
+
+    let v6 = ST6::ctor();
+    v6.type_alias();
+
+    let v7 = ST7::<i32, usize>::ctor();
+    let r = v7.pattern();
+    println!("{} {}", r.0, r.1)
+}
index 8331ae0b307d95ebd222685fdf2147be7be246c8..bbaf060ca87e3b226afb54ba50076c9458f6c3a2 100644 (file)
 pub fn main() {
     let Self = 5;
     //~^ ERROR cannot find unit struct/variant or constant `Self` in this scope
+    //~^^ ERROR `Self` struct constructors are unstable (see issue #51994)
 
     match 15 {
         Self => (),
         //~^ ERROR cannot find unit struct/variant or constant `Self` in this scope
+        //~^^ ERROR `Self` struct constructors are unstable (see issue #51994)
         Foo { x: Self } => (),
         //~^ ERROR cannot find unit struct/variant or constant `Self` in this scope
+        //~^^ ERROR `Self` struct constructors are unstable (see issue #51994)
     }
 }
index 972e5bdddc6733493e530b2b1015c11bbac8336b..82529974d0e37a4f74b01b4bd5c78c514e480a0b 100644 (file)
@@ -11,18 +11,42 @@ LL |     let Self = 5;
    |         ^^^^ not found in this scope
 
 error[E0531]: cannot find unit struct/variant or constant `Self` in this scope
-  --> $DIR/self_type_keyword-2.rs:18:9
+  --> $DIR/self_type_keyword-2.rs:19:9
    |
 LL |         Self => (),
    |         ^^^^ not found in this scope
 
 error[E0531]: cannot find unit struct/variant or constant `Self` in this scope
-  --> $DIR/self_type_keyword-2.rs:20:18
+  --> $DIR/self_type_keyword-2.rs:22:18
    |
 LL |         Foo { x: Self } => (),
    |                  ^^^^ not found in this scope
 
-error: aborting due to 4 previous errors
+error[E0658]: `Self` struct constructors are unstable (see issue #51994)
+  --> $DIR/self_type_keyword-2.rs:14:9
+   |
+LL |     let Self = 5;
+   |         ^^^^
+   |
+   = help: add #![feature(self_struct_ctor)] to the crate attributes to enable
+
+error[E0658]: `Self` struct constructors are unstable (see issue #51994)
+  --> $DIR/self_type_keyword-2.rs:19:9
+   |
+LL |         Self => (),
+   |         ^^^^
+   |
+   = help: add #![feature(self_struct_ctor)] to the crate attributes to enable
+
+error[E0658]: `Self` struct constructors are unstable (see issue #51994)
+  --> $DIR/self_type_keyword-2.rs:22:18
+   |
+LL |         Foo { x: Self } => (),
+   |                  ^^^^
+   |
+   = help: add #![feature(self_struct_ctor)] to the crate attributes to enable
+
+error: aborting due to 7 previous errors
 
-Some errors occurred: E0432, E0531.
+Some errors occurred: E0432, E0531, E0658.
 For more information about an error, try `rustc --explain E0432`.