From a4891699125fa12d46217890e4eb68b35e9ff6d5 Mon Sep 17 00:00:00 2001 From: F001 Date: Tue, 28 Aug 2018 12:51:43 +0800 Subject: [PATCH 1/2] implement feature tuple_struct_self_ctor --- .../tuple-struct-self-ctor.md | 33 ++++++ src/librustc_resolve/build_reduced_graph.rs | 2 + src/librustc_resolve/lib.rs | 76 ++++++++++--- src/libsyntax/feature_gate.rs | 12 +++ src/test/run-pass/tuple-struct-self-ctor.rs | 102 ++++++++++++++++++ .../feature-gate-tuple-struct-self-ctor.rs | 19 ++++ ...feature-gate-tuple-struct-self-ctor.stderr | 20 ++++ src/test/ui/resolve/tuple-struct-alias.rs | 9 -- src/test/ui/resolve/tuple-struct-alias.stderr | 22 +--- 9 files changed, 254 insertions(+), 41 deletions(-) create mode 100644 src/doc/unstable-book/src/language-features/tuple-struct-self-ctor.md create mode 100644 src/test/run-pass/tuple-struct-self-ctor.rs create mode 100644 src/test/ui/feature-gates/feature-gate-tuple-struct-self-ctor.rs create mode 100644 src/test/ui/feature-gates/feature-gate-tuple-struct-self-ctor.stderr 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 new file mode 100644 index 0000000000000..7ea52ebe2431c --- /dev/null +++ b/src/doc/unstable-book/src/language-features/tuple-struct-self-ctor.md @@ -0,0 +1,33 @@ +# `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 + } + } +} +``` diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index d1a05964c8f64..c7aea641e35d4 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -585,6 +585,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { 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); } } @@ -703,6 +704,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { 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(..) => { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c725d56d0cfdc..f2d46c0510c75 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1463,6 +1463,9 @@ 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, + /// Only used for better errors on `fn(): fn()` current_type_ascription: Vec, @@ -1764,6 +1767,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { 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(), @@ -2204,6 +2208,19 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { None } + fn resolve_adt(&mut self, item: &Item, generics: &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); + } + }); + } + fn resolve_item(&mut self, item: &Item) { let name = item.ident.name; debug!("(resolving item) resolving {}", name); @@ -2216,19 +2233,25 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { |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.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); - } - }); + self.resolve_adt(item, generics); } ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) => @@ -2503,6 +2526,32 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { self.ribs[TypeNS].pop(); } + fn with_tuple_struct_self_ctor_rib(&mut self, self_ty: &Ty, 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); + } + } + fn resolve_implementation(&mut self, generics: &Generics, opt_trait_reference: &Option, @@ -2554,8 +2603,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { ValueNS, impl_item.span, |n, s| MethodNotMemberOfTrait(n, s)); - - visit::walk_impl_item(this, impl_item); + this.with_tuple_struct_self_ctor_rib(self_type, |this| { + visit::walk_impl_item(this, impl_item); + }); } ImplItemKind::Type(ref ty) => { // If this is a trait impl, ensure the type diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index d98e457439927..4d24abcf90eb3 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -512,6 +512,9 @@ declare_features! ( // 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), ); declare_features! ( @@ -1736,6 +1739,15 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { 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 new file mode 100644 index 0000000000000..7392003bb2300 --- /dev/null +++ b/src/test/run-pass/tuple-struct-self-ctor.rs @@ -0,0 +1,102 @@ +// 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(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); // With type parameter + +impl ST2 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) -> Option { + 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-tuple-struct-self-ctor.rs b/src/test/ui/feature-gates/feature-gate-tuple-struct-self-ctor.rs new file mode 100644 index 0000000000000..aa907e813ed5a --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-tuple-struct-self-ctor.rs @@ -0,0 +1,19 @@ +// 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. + +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 new file mode 100644 index 0000000000000..e92924e960278 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-tuple-struct-self-ctor.stderr @@ -0,0 +1,20 @@ +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`. diff --git a/src/test/ui/resolve/tuple-struct-alias.rs b/src/test/ui/resolve/tuple-struct-alias.rs index 0dbca07b771d7..1f3588dd3ca4e 100644 --- a/src/test/ui/resolve/tuple-struct-alias.rs +++ b/src/test/ui/resolve/tuple-struct-alias.rs @@ -11,15 +11,6 @@ struct S(u8, u16); type A = S; -impl S { - fn f() { - let s = Self(0, 1); //~ ERROR expected function - match s { - Self(..) => {} //~ ERROR expected tuple struct/variant - } - } -} - fn main() { let s = A(0, 1); //~ ERROR expected function match s { diff --git a/src/test/ui/resolve/tuple-struct-alias.stderr b/src/test/ui/resolve/tuple-struct-alias.stderr index cdac6277bcfa3..ad2ae4acb8b0e 100644 --- a/src/test/ui/resolve/tuple-struct-alias.stderr +++ b/src/test/ui/resolve/tuple-struct-alias.stderr @@ -1,21 +1,5 @@ -error[E0423]: expected function, found self type `Self` - --> $DIR/tuple-struct-alias.rs:16:17 - | -LL | let s = Self(0, 1); //~ ERROR expected function - | ^^^^ not a function - | - = note: can't use `Self` as a constructor, you must use the implemented struct - -error[E0532]: expected tuple struct/variant, found self type `Self` - --> $DIR/tuple-struct-alias.rs:18:13 - | -LL | Self(..) => {} //~ ERROR expected tuple struct/variant - | ^^^^ not a tuple struct/variant - | - = note: can't use `Self` as a constructor, you must use the implemented struct - error[E0423]: expected function, found type alias `A` - --> $DIR/tuple-struct-alias.rs:24:13 + --> $DIR/tuple-struct-alias.rs:15:13 | LL | let s = A(0, 1); //~ ERROR expected function | ^ did you mean `S`? @@ -23,14 +7,14 @@ LL | let s = A(0, 1); //~ ERROR expected function = note: can't use a type alias as a constructor error[E0532]: expected tuple struct/variant, found type alias `A` - --> $DIR/tuple-struct-alias.rs:26:9 + --> $DIR/tuple-struct-alias.rs:17:9 | LL | A(..) => {} //~ ERROR expected tuple struct/variant | ^ did you mean `S`? | = note: can't use a type alias as a constructor -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors Some errors occurred: E0423, E0532. For more information about an error, try `rustc --explain E0423`. From 2157958b27b7f1cd471533d71c8e09843aec57ad Mon Sep 17 00:00:00 2001 From: F001 Date: Thu, 6 Sep 2018 10:46:55 +0800 Subject: [PATCH 2/2] introduce SelfCtor --- ...truct-self-ctor.md => self-struct-ctor.md} | 6 +- src/librustc/hir/def.rs | 5 +- src/librustc/hir/lowering.rs | 50 +++-- src/librustc/ich/impls_hir.rs | 1 + src/librustc/middle/mem_categorization.rs | 4 +- src/librustc/middle/stability.rs | 2 +- src/librustc/ty/mod.rs | 3 +- src/librustc_mir/hair/cx/expr.rs | 25 ++- src/librustc_mir/hair/pattern/mod.rs | 2 +- src/librustc_passes/rvalue_promotion.rs | 5 +- src/librustc_resolve/build_reduced_graph.rs | 2 - src/librustc_resolve/lib.rs | 171 ++++++++---------- src/librustc_save_analysis/lib.rs | 1 + src/librustc_typeck/check/_match.rs | 30 ++- src/librustc_typeck/check/mod.rs | 38 +++- src/librustdoc/clean/inline.rs | 3 +- .../passes/collect_intra_doc_links.rs | 4 +- src/librustdoc/visit_ast.rs | 2 +- src/libsyntax/feature_gate.rs | 13 +- .../feature-gate-self-struct-ctor.rs | 22 +++ .../feature-gate-self-struct-ctor.stderr | 19 ++ .../feature-gate-tuple-struct-self-ctor.rs | 19 -- ...feature-gate-tuple-struct-self-ctor.stderr | 20 -- .../ui/keyword/keyword-self-as-identifier.rs | 1 + .../keyword/keyword-self-as-identifier.stderr | 13 +- .../rfcs/rfc-2302-self-struct-ctor.rs} | 49 +++-- src/test/ui/self/self_type_keyword-2.rs | 3 + src/test/ui/self/self_type_keyword-2.stderr | 32 +++- 28 files changed, 326 insertions(+), 219 deletions(-) rename src/doc/unstable-book/src/language-features/{tuple-struct-self-ctor.md => self-struct-ctor.md} (79%) create mode 100644 src/test/ui/feature-gates/feature-gate-self-struct-ctor.rs create mode 100644 src/test/ui/feature-gates/feature-gate-self-struct-ctor.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-tuple-struct-self-ctor.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-tuple-struct-self-ctor.stderr rename src/test/{run-pass/tuple-struct-self-ctor.rs => ui/run-pass/rfcs/rfc-2302-self-struct-ctor.rs} (70%) diff --git a/src/doc/unstable-book/src/language-features/tuple-struct-self-ctor.md b/src/doc/unstable-book/src/language-features/self-struct-ctor.md similarity index 79% rename from src/doc/unstable-book/src/language-features/tuple-struct-self-ctor.md rename to src/doc/unstable-book/src/language-features/self-struct-ctor.md index 7ea52ebe2431c..b4742c48a32ff 100644 --- a/src/doc/unstable-book/src/language-features/tuple-struct-self-ctor.md +++ b/src/doc/unstable-book/src/language-features/self-struct-ctor.md @@ -1,17 +1,17 @@ -# `tuple_struct_self_ctor` +# `self_struct_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` +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(tuple_struct_self_ctor)] +#![feature(self_struct_ctor)] struct ST(i32, i32); diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index b10f4785f1637..4286b0628f5ff 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -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 @@ impl Def { 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 @@ impl Def { 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", diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 34b3eb0a8c8bf..45628e2b6f3b8 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -67,6 +67,7 @@ use syntax::ast; 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { 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) -> Vec { diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 3f1899bc54fb4..bc2eb5f442b47 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -1021,6 +1021,7 @@ impl_stable_hash_for!(enum hir::def::Def { 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), diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index b63cde0f205f7..172511474710d 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -708,7 +708,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { (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()) diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index f237c5b397bd5..73a55265f009a 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -783,7 +783,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { 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) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index a48aabc3cd7c7..d9e3bdaf266a9 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2134,7 +2134,8 @@ impl<'a, 'gcx, 'tcx> AdtDef { 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) } } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 055f238e5db4e..510e7eb9c63f7 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -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( diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index ee50322fbb355..57519d6ad7d70 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -667,7 +667,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) | - Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => { + Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => { PatternKind::Leaf { subpatterns: subpatterns } } diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 74b010f57b01d..828800465209e 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -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) } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index c7aea641e35d4..d1a05964c8f64 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -585,7 +585,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> { 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 @@ impl<'a, 'cl> Resolver<'a, 'cl> { 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(..) => { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index f2d46c0510c75..384d3ed744a9a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -558,17 +558,21 @@ impl<'a> PathSource<'a> { 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, - /// Only used for better errors on `fn(): fn()` current_type_ascription: Vec, @@ -1767,7 +1768,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { 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 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { |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 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { self.ribs[TypeNS].pop(); } - fn with_tuple_struct_self_ctor_rib(&mut self, self_ty: &Ty, f: F) + fn with_self_struct_ctor_rib(&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 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { 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!"), - } - }); - } + }); + } + }); }); }); }); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 8d6a75ecc5925..c9bae297031ff 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -813,6 +813,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { HirDef::Macro(..) | HirDef::ToolMod | HirDef::NonMacroAttr(..) | + HirDef::SelfCtor(..) | HirDef::Err => None, } } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 2a8ee4bd8df0e..7733ea37c056c 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -756,12 +756,13 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); } 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 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); // 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 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); } _ => 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() { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9ab269702db1c..6a8860a3d9d06 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3898,7 +3898,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }, ); - - // 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.write_user_substs_from_substs(hir_id, substs); - ty_substituted + (ty_substituted, new_def) } fn check_rustc_args_require_const(&self, diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 75d7488d26a75..507461f2ea175 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -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)) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index cced30d1a0c20..a60347e008f88 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -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(..) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 451e24d6c0dc9..0aaf2d526f934 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -371,7 +371,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> { // 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, _ => {} } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 4d24abcf90eb3..7266d807d3ba8 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -513,8 +513,8 @@ declare_features! ( // 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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { 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/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 index 0000000000000..98eab39491320 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-self-struct-ctor.rs @@ -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 index 0000000000000..6061a0db76ec5 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-self-struct-ctor.stderr @@ -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 index aa907e813ed5a..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-tuple-struct-self-ctor.rs +++ /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 or the MIT license -// , 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 index e92924e960278..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-tuple-struct-self-ctor.stderr +++ /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`. diff --git a/src/test/ui/keyword/keyword-self-as-identifier.rs b/src/test/ui/keyword/keyword-self-as-identifier.rs index b50fc68bed6be..ad5b8fb64342d 100644 --- a/src/test/ui/keyword/keyword-self-as-identifier.rs +++ b/src/test/ui/keyword/keyword-self-as-identifier.rs @@ -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) } diff --git a/src/test/ui/keyword/keyword-self-as-identifier.stderr b/src/test/ui/keyword/keyword-self-as-identifier.stderr index c47f4aeabefd8..296269819f836 100644 --- a/src/test/ui/keyword/keyword-self-as-identifier.stderr +++ b/src/test/ui/keyword/keyword-self-as-identifier.stderr @@ -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/run-pass/tuple-struct-self-ctor.rs b/src/test/ui/run-pass/rfcs/rfc-2302-self-struct-ctor.rs similarity index 70% rename from src/test/run-pass/tuple-struct-self-ctor.rs rename to src/test/ui/run-pass/rfcs/rfc-2302-self-struct-ctor.rs index 7392003bb2300..156e240e44282 100644 --- a/src/test/run-pass/tuple-struct-self-ctor.rs +++ b/src/test/ui/run-pass/rfcs/rfc-2302-self-struct-ctor.rs @@ -1,14 +1,6 @@ -// 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(tuple_struct_self_ctor)] +// run-pass + +#![feature(self_struct_ctor)] #![allow(dead_code)] @@ -83,6 +75,34 @@ impl ST5 { } } +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 = Some(0).map(Self); + } +} + +struct ST7(T1, T2); + +impl ST7 { + + 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(); @@ -99,4 +119,11 @@ fn main() { let v5 = ST5::ctor(); v5.pattern(); + + let v6 = ST6::ctor(); + v6.type_alias(); + + let v7 = ST7::::ctor(); + let r = v7.pattern(); + println!("{} {}", r.0, r.1) } diff --git a/src/test/ui/self/self_type_keyword-2.rs b/src/test/ui/self/self_type_keyword-2.rs index 8331ae0b307d9..bbaf060ca87e3 100644 --- a/src/test/ui/self/self_type_keyword-2.rs +++ b/src/test/ui/self/self_type_keyword-2.rs @@ -13,11 +13,14 @@ use self::Self as Foo; //~ ERROR unresolved import `self::Self` 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) } } diff --git a/src/test/ui/self/self_type_keyword-2.stderr b/src/test/ui/self/self_type_keyword-2.stderr index 972e5bdddc673..82529974d0e37 100644 --- a/src/test/ui/self/self_type_keyword-2.stderr +++ b/src/test/ui/self/self_type_keyword-2.stderr @@ -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`.