Skip to content

Commit 2157958

Browse files
committed
introduce SelfCtor
1 parent a489169 commit 2157958

28 files changed

+326
-219
lines changed

src/doc/unstable-book/src/language-features/tuple-struct-self-ctor.md src/doc/unstable-book/src/language-features/self-struct-ctor.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
# `tuple_struct_self_ctor`
1+
# `self_struct_ctor`
22

33
The tracking issue for this feature is: [#51994]
44
[#51994]: https://github.com/rust-lang/rust/issues/51994
55

66
------------------------
77

8-
The `tuple_struct_self_ctor` feature gate lets you use the special `Self`
8+
The `self_struct_ctor` feature gate lets you use the special `Self`
99
identifier as a constructor and a pattern.
1010

1111
A simple example is:
1212

1313
```rust
14-
#![feature(tuple_struct_self_ctor)]
14+
#![feature(self_struct_ctor)]
1515

1616
struct ST(i32, i32);
1717

src/librustc/hir/def.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ pub enum Def {
6969
Static(DefId, bool /* is_mutbl */),
7070
StructCtor(DefId, CtorKind), // DefId refers to NodeId of the struct's constructor
7171
VariantCtor(DefId, CtorKind), // DefId refers to the enum variant
72+
SelfCtor(DefId /* impl */), // DefId refers to the impl
7273
Method(DefId),
7374
AssociatedConst(DefId),
7475

@@ -272,7 +273,8 @@ impl Def {
272273
Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
273274
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
274275
Def::AssociatedConst(id) | Def::Macro(id, ..) |
275-
Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) => {
276+
Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) |
277+
Def::SelfCtor(id) => {
276278
id
277279
}
278280

@@ -309,6 +311,7 @@ impl Def {
309311
Def::StructCtor(.., CtorKind::Fn) => "tuple struct",
310312
Def::StructCtor(.., CtorKind::Const) => "unit struct",
311313
Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
314+
Def::SelfCtor(..) => "self constructor",
312315
Def::Union(..) => "union",
313316
Def::Trait(..) => "trait",
314317
Def::ForeignTy(..) => "foreign type",

src/librustc/hir/lowering.rs

+36-14
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ use syntax::ast;
6767
use syntax::ast::*;
6868
use syntax::errors;
6969
use syntax::ext::hygiene::{Mark, SyntaxContext};
70+
use syntax::feature_gate::{emit_feature_err, GateIssue};
7071
use syntax::print::pprust;
7172
use syntax::ptr::P;
7273
use syntax::source_map::{self, respan, CompilerDesugaringKind, Spanned};
@@ -3429,19 +3430,24 @@ impl<'a> LoweringContext<'a> {
34293430
ParamMode::Optional,
34303431
ImplTraitContext::Disallowed,
34313432
);
3433+
self.check_self_struct_ctor_feature(&qpath);
34323434
hir::PatKind::TupleStruct(
34333435
qpath,
34343436
pats.iter().map(|x| self.lower_pat(x)).collect(),
34353437
ddpos,
34363438
)
34373439
}
3438-
PatKind::Path(ref qself, ref path) => hir::PatKind::Path(self.lower_qpath(
3439-
p.id,
3440-
qself,
3441-
path,
3442-
ParamMode::Optional,
3443-
ImplTraitContext::Disallowed,
3444-
)),
3440+
PatKind::Path(ref qself, ref path) => {
3441+
let qpath = self.lower_qpath(
3442+
p.id,
3443+
qself,
3444+
path,
3445+
ParamMode::Optional,
3446+
ImplTraitContext::Disallowed,
3447+
);
3448+
self.check_self_struct_ctor_feature(&qpath);
3449+
hir::PatKind::Path(qpath)
3450+
}
34453451
PatKind::Struct(ref path, ref fields, etc) => {
34463452
let qpath = self.lower_qpath(
34473453
p.id,
@@ -3828,13 +3834,17 @@ impl<'a> LoweringContext<'a> {
38283834
attrs: e.attrs.clone(),
38293835
};
38303836
}
3831-
ExprKind::Path(ref qself, ref path) => hir::ExprKind::Path(self.lower_qpath(
3832-
e.id,
3833-
qself,
3834-
path,
3835-
ParamMode::Optional,
3836-
ImplTraitContext::Disallowed,
3837-
)),
3837+
ExprKind::Path(ref qself, ref path) => {
3838+
let qpath = self.lower_qpath(
3839+
e.id,
3840+
qself,
3841+
path,
3842+
ParamMode::Optional,
3843+
ImplTraitContext::Disallowed,
3844+
);
3845+
self.check_self_struct_ctor_feature(&qpath);
3846+
hir::ExprKind::Path(qpath)
3847+
}
38383848
ExprKind::Break(opt_label, ref opt_expr) => {
38393849
let destination = if self.is_in_loop_condition && opt_label.is_none() {
38403850
hir::Destination {
@@ -4815,6 +4825,18 @@ impl<'a> LoweringContext<'a> {
48154825
ThinVec::new()));
48164826
P(self.expr_call(e.span, from_err, hir_vec![e]))
48174827
}
4828+
4829+
fn check_self_struct_ctor_feature(&self, qp: &hir::QPath) {
4830+
if let hir::QPath::Resolved(_, ref p) = qp {
4831+
if p.segments.len() == 1 &&
4832+
p.segments[0].ident.name == keywords::SelfType.name() &&
4833+
!self.sess.features_untracked().self_struct_ctor {
4834+
emit_feature_err(&self.sess.parse_sess, "self_struct_ctor",
4835+
p.span, GateIssue::Language,
4836+
"`Self` struct constructors are unstable");
4837+
}
4838+
}
4839+
}
48184840
}
48194841

48204842
fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body>) -> Vec<hir::BodyId> {

src/librustc/ich/impls_hir.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,7 @@ impl_stable_hash_for!(enum hir::def::Def {
10211021
Const(def_id),
10221022
Static(def_id, is_mutbl),
10231023
StructCtor(def_id, ctor_kind),
1024+
SelfCtor(impl_def_id),
10241025
VariantCtor(def_id, ctor_kind),
10251026
Method(def_id),
10261027
AssociatedConst(def_id),

src/librustc/middle/mem_categorization.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
708708

709709
match def {
710710
Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) |
711-
Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) => {
711+
Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => {
712712
Ok(self.cat_rvalue_node(hir_id, span, expr_ty))
713713
}
714714

@@ -1288,7 +1288,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
12881288
(self.cat_downcast_if_needed(pat, cmt, def_id),
12891289
self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len())
12901290
}
1291-
Def::StructCtor(_, CtorKind::Fn) => {
1291+
Def::StructCtor(_, CtorKind::Fn) | Def::SelfCtor(..) => {
12921292
match self.pat_ty_unadjusted(&pat)?.sty {
12931293
ty::Adt(adt_def, _) => {
12941294
(cmt, adt_def.non_enum_variant().fields.len())

src/librustc/middle/stability.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
783783
fn visit_path(&mut self, path: &'tcx hir::Path, id: hir::HirId) {
784784
let id = self.tcx.hir.hir_to_node_id(id);
785785
match path.def {
786-
Def::Local(..) | Def::Upvar(..) |
786+
Def::Local(..) | Def::Upvar(..) | Def::SelfCtor(..) |
787787
Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => {}
788788
_ => self.tcx.check_stability(path.def.def_id(), Some(id), path.span)
789789
}

src/librustc/ty/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2134,7 +2134,8 @@ impl<'a, 'gcx, 'tcx> AdtDef {
21342134
match def {
21352135
Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid),
21362136
Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
2137-
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => self.non_enum_variant(),
2137+
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) |
2138+
Def::SelfCtor(..) => self.non_enum_variant(),
21382139
_ => bug!("unexpected def {:?} in variant_of_def", def)
21392140
}
21402141
}

src/librustc_mir/hair/cx/expr.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
273273
Def::VariantCtor(variant_id, CtorKind::Fn) => {
274274
Some((adt_def, adt_def.variant_index_with_id(variant_id)))
275275
}
276-
Def::StructCtor(_, CtorKind::Fn) => Some((adt_def, 0)),
276+
Def::StructCtor(_, CtorKind::Fn) |
277+
Def::SelfCtor(..) => Some((adt_def, 0)),
277278
_ => None,
278279
}
279280
})
@@ -759,6 +760,25 @@ fn user_annotated_ty_for_def(
759760
sty => bug!("unexpected sty: {:?}", sty),
760761
},
761762

763+
// `Self` is used in expression as a tuple struct constructor or an unit struct constructor
764+
Def::SelfCtor(_) => {
765+
let sty = &cx.tables().node_id_to_type(hir_id).sty;
766+
match sty {
767+
ty::FnDef(ref def_id, _) => {
768+
Some(cx.tables().user_substs(hir_id)?.unchecked_map(|user_substs| {
769+
// Here, we just pair a `DefId` with the
770+
// `user_substs`, so no new types etc are introduced.
771+
cx.tcx().mk_fn_def(*def_id, user_substs)
772+
}))
773+
}
774+
ty::Adt(ref adt_def, _) => {
775+
user_annotated_ty_for_adt(cx, hir_id, adt_def)
776+
}
777+
_ => {
778+
bug!("unexpected sty: {:?}", sty)
779+
}
780+
}
781+
}
762782
_ =>
763783
bug!("user_annotated_ty_for_def: unexpected def {:?} at {:?}", def, hir_id)
764784
}
@@ -857,7 +877,8 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
857877
Def::Fn(_) |
858878
Def::Method(_) |
859879
Def::StructCtor(_, CtorKind::Fn) |
860-
Def::VariantCtor(_, CtorKind::Fn) => {
880+
Def::VariantCtor(_, CtorKind::Fn) |
881+
Def::SelfCtor(..) => {
861882
let user_ty = user_annotated_ty_for_def(cx, expr.hir_id, &def);
862883
ExprKind::Literal {
863884
literal: ty::Const::zero_sized(

src/librustc_mir/hair/pattern/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
667667
}
668668

669669
Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
670-
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => {
670+
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => {
671671
PatternKind::Leaf { subpatterns: subpatterns }
672672
}
673673

src/librustc_passes/rvalue_promotion.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ fn check_expr_kind<'a, 'tcx>(
376376
let def = v.tables.qpath_def(qpath, e.hir_id);
377377
match def {
378378
Def::VariantCtor(..) | Def::StructCtor(..) |
379-
Def::Fn(..) | Def::Method(..) => Promotable,
379+
Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => Promotable,
380380

381381
// References to a static that are themselves within a static
382382
// are inherently promotable with the exception
@@ -441,7 +441,8 @@ fn check_expr_kind<'a, 'tcx>(
441441
};
442442
let def_result = match def {
443443
Def::StructCtor(_, CtorKind::Fn) |
444-
Def::VariantCtor(_, CtorKind::Fn) => Promotable,
444+
Def::VariantCtor(_, CtorKind::Fn) |
445+
Def::SelfCtor(..) => Promotable,
445446
Def::Fn(did) => {
446447
v.handle_const_fn_call(did, node_ty, e.span)
447448
}

src/librustc_resolve/build_reduced_graph.rs

-2
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
585585
CtorKind::from_ast(struct_def));
586586
self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion));
587587
self.struct_constructors.insert(def.def_id(), (ctor_def, ctor_vis));
588-
self.tuple_structs.insert(def.def_id(), ctor_def);
589588
}
590589
}
591590

@@ -704,7 +703,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
704703
self.cstore.def_key(def_id).parent
705704
.map(|index| DefId { krate: def_id.krate, index: index }) {
706705
self.struct_constructors.insert(struct_def_id, (def, vis));
707-
self.tuple_structs.insert(struct_def_id, def);
708706
}
709707
}
710708
Def::Trait(..) => {

0 commit comments

Comments
 (0)