--- /dev/null
+# `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
+ }
+ }
+}
+```
+++ /dev/null
-# `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
- }
- }
-}
-```
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),
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
}
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",
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};
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,
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 {
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> {
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),
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))
}
(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())
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)
}
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)
}
}
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,
}
})
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)
}
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(
}
Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
- Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => {
+ Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => {
PatternKind::Leaf { subpatterns: subpatterns }
}
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
};
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)
}
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);
}
}
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(..) => {
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 {
/// 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>,
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(),
|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);
}
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,
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!"),
- }
- });
- }
+ });
+ }
+ });
});
});
});
HirDef::Macro(..) |
HirDef::ToolMod |
HirDef::NonMacroAttr(..) |
+ HirDef::SelfCtor(..) |
HirDef::Err => None,
}
}
}
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
}
// 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();
}
_ => 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() {
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
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);
def: Def,
span: Span,
node_id: ast::NodeId)
- -> Ty<'tcx> {
+ -> (Ty<'tcx>, Def) {
debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})",
segments,
def,
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);
}
_ => {}
}
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,
}
},
);
-
- // 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());
self.write_user_substs_from_substs(hir_id, substs);
- ty_substituted
+ (ty_substituted, new_def)
}
fn check_rustc_args_require_const(&self,
// 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))
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(..)
// 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,
_ => {}
}
// 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! (
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);
+++ /dev/null
-// 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();
-}
--- /dev/null
+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();
+}
--- /dev/null
+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`.
+++ /dev/null
-// 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]
- }
-}
+++ /dev/null
-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`.
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)
}
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`.
--- /dev/null
+// 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)
+}
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)
}
}
| ^^^^ 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`.