Skip to content

Commit b1a193d

Browse files
author
Alexander Regueiro
committed
Fixed issue #56199.
1 parent 79305cf commit b1a193d

File tree

6 files changed

+130
-38
lines changed

6 files changed

+130
-38
lines changed

src/librustc/hir/map/definitions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ pub struct DefPath {
234234
/// The path leading from the crate root to the item.
235235
pub data: Vec<DisambiguatedDefPathData>,
236236

237-
/// The crate root this path is relative to.
237+
/// The krate root this path is relative to.
238238
pub krate: CrateNum,
239239
}
240240

src/librustc/ty/mod.rs

+52-32
Original file line numberDiff line numberDiff line change
@@ -1753,17 +1753,19 @@ bitflags! {
17531753
pub struct AdtFlags: u32 {
17541754
const NO_ADT_FLAGS = 0;
17551755
const IS_ENUM = 1 << 0;
1756-
const IS_PHANTOM_DATA = 1 << 1;
1757-
const IS_FUNDAMENTAL = 1 << 2;
1758-
const IS_UNION = 1 << 3;
1759-
const IS_BOX = 1 << 4;
1756+
const IS_UNION = 1 << 1;
1757+
const IS_STRUCT = 1 << 2;
1758+
const IS_TUPLE_STRUCT = 1 << 3;
1759+
const IS_PHANTOM_DATA = 1 << 4;
1760+
const IS_FUNDAMENTAL = 1 << 5;
1761+
const IS_BOX = 1 << 6;
17601762
/// Indicates whether the type is an `Arc`.
1761-
const IS_ARC = 1 << 5;
1763+
const IS_ARC = 1 << 7;
17621764
/// Indicates whether the type is an `Rc`.
1763-
const IS_RC = 1 << 6;
1765+
const IS_RC = 1 << 8;
17641766
/// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
17651767
/// (i.e., this flag is never set unless this ADT is an enum).
1766-
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 7;
1768+
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 9;
17671769
}
17681770
}
17691771

@@ -2077,31 +2079,43 @@ impl<'a, 'gcx, 'tcx> AdtDef {
20772079
repr: ReprOptions) -> Self {
20782080
debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
20792081
let mut flags = AdtFlags::NO_ADT_FLAGS;
2082+
2083+
if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
2084+
debug!("found non-exhaustive variant list for {:?}", did);
2085+
flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
2086+
}
2087+
flags |= match kind {
2088+
AdtKind::Enum => AdtFlags::IS_ENUM,
2089+
AdtKind::Union => AdtFlags::IS_UNION,
2090+
AdtKind::Struct => AdtFlags::IS_STRUCT,
2091+
};
2092+
2093+
if let AdtKind::Struct = kind {
2094+
let variant_def = &variants[VariantIdx::new(0)];
2095+
let def_key = tcx.def_key(variant_def.did);
2096+
match def_key.disambiguated_data.data {
2097+
DefPathData::StructCtor => flags |= AdtFlags::IS_TUPLE_STRUCT,
2098+
_ => (),
2099+
}
2100+
}
2101+
20802102
let attrs = tcx.get_attrs(did);
20812103
if attr::contains_name(&attrs, "fundamental") {
2082-
flags = flags | AdtFlags::IS_FUNDAMENTAL;
2104+
flags |= AdtFlags::IS_FUNDAMENTAL;
20832105
}
20842106
if Some(did) == tcx.lang_items().phantom_data() {
2085-
flags = flags | AdtFlags::IS_PHANTOM_DATA;
2107+
flags |= AdtFlags::IS_PHANTOM_DATA;
20862108
}
20872109
if Some(did) == tcx.lang_items().owned_box() {
2088-
flags = flags | AdtFlags::IS_BOX;
2110+
flags |= AdtFlags::IS_BOX;
20892111
}
20902112
if Some(did) == tcx.lang_items().arc() {
2091-
flags = flags | AdtFlags::IS_ARC;
2113+
flags |= AdtFlags::IS_ARC;
20922114
}
20932115
if Some(did) == tcx.lang_items().rc() {
2094-
flags = flags | AdtFlags::IS_RC;
2095-
}
2096-
if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
2097-
debug!("found non-exhaustive variant list for {:?}", did);
2098-
flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
2099-
}
2100-
match kind {
2101-
AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM,
2102-
AdtKind::Union => flags = flags | AdtFlags::IS_UNION,
2103-
AdtKind::Struct => {}
2116+
flags |= AdtFlags::IS_RC;
21042117
}
2118+
21052119
AdtDef {
21062120
did,
21072121
variants,
@@ -2112,25 +2126,31 @@ impl<'a, 'gcx, 'tcx> AdtDef {
21122126

21132127
#[inline]
21142128
pub fn is_struct(&self) -> bool {
2115-
!self.is_union() && !self.is_enum()
2129+
self.flags.contains(AdtFlags::IS_STRUCT)
2130+
}
2131+
2132+
/// If this function returns `true`, it implies that `is_struct` must return `true`.
2133+
#[inline]
2134+
pub fn is_tuple_struct(&self) -> bool {
2135+
self.flags.contains(AdtFlags::IS_TUPLE_STRUCT)
21162136
}
21172137

21182138
#[inline]
21192139
pub fn is_union(&self) -> bool {
2120-
self.flags.intersects(AdtFlags::IS_UNION)
2140+
self.flags.contains(AdtFlags::IS_UNION)
21212141
}
21222142

21232143
#[inline]
21242144
pub fn is_enum(&self) -> bool {
2125-
self.flags.intersects(AdtFlags::IS_ENUM)
2145+
self.flags.contains(AdtFlags::IS_ENUM)
21262146
}
21272147

21282148
#[inline]
21292149
pub fn is_variant_list_non_exhaustive(&self) -> bool {
2130-
self.flags.intersects(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
2150+
self.flags.contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
21312151
}
21322152

2133-
/// Returns the kind of the ADT - Struct or Enum.
2153+
/// Returns the kind of the ADT.
21342154
#[inline]
21352155
pub fn adt_kind(&self) -> AdtKind {
21362156
if self.is_enum() {
@@ -2159,33 +2179,33 @@ impl<'a, 'gcx, 'tcx> AdtDef {
21592179
}
21602180
}
21612181

2162-
/// Returns whether this type is #[fundamental] for the purposes
2182+
/// Returns whether this type is `#[fundamental]` for the purposes
21632183
/// of coherence checking.
21642184
#[inline]
21652185
pub fn is_fundamental(&self) -> bool {
2166-
self.flags.intersects(AdtFlags::IS_FUNDAMENTAL)
2186+
self.flags.contains(AdtFlags::IS_FUNDAMENTAL)
21672187
}
21682188

21692189
/// Returns `true` if this is PhantomData<T>.
21702190
#[inline]
21712191
pub fn is_phantom_data(&self) -> bool {
2172-
self.flags.intersects(AdtFlags::IS_PHANTOM_DATA)
2192+
self.flags.contains(AdtFlags::IS_PHANTOM_DATA)
21732193
}
21742194

21752195
/// Returns `true` if this is `Arc<T>`.
21762196
pub fn is_arc(&self) -> bool {
2177-
self.flags.intersects(AdtFlags::IS_ARC)
2197+
self.flags.contains(AdtFlags::IS_ARC)
21782198
}
21792199

21802200
/// Returns `true` if this is `Rc<T>`.
21812201
pub fn is_rc(&self) -> bool {
2182-
self.flags.intersects(AdtFlags::IS_RC)
2202+
self.flags.contains(AdtFlags::IS_RC)
21832203
}
21842204

21852205
/// Returns `true` if this is Box<T>.
21862206
#[inline]
21872207
pub fn is_box(&self) -> bool {
2188-
self.flags.intersects(AdtFlags::IS_BOX)
2208+
self.flags.contains(AdtFlags::IS_BOX)
21892209
}
21902210

21912211
/// Returns whether this type has a destructor.

src/librustc_typeck/check/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
280280
Def::Local(id) | Def::Upvar(id, ..) => {
281281
Some(self.tcx.hir().span(id))
282282
}
283-
_ => self.tcx.hir().span_if_local(def.def_id())
283+
_ => def.opt_def_id().and_then(|did| self.tcx.hir().span_if_local(did)),
284284
};
285285
if let Some(span) = def_span {
286286
let label = match (unit_variant, inner_callee_path) {

src/librustc_typeck/check/mod.rs

+23-4
Original file line numberDiff line numberDiff line change
@@ -3222,8 +3222,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
32223222
return_expr_ty);
32233223
}
32243224

3225-
// A generic function for checking the 'then' and 'else' clauses in an 'if'
3226-
// or 'if-else' expression.
3225+
// A generic function for checking the "then" and "else" clauses in an "if"
3226+
// or "if-else" expression.
32273227
fn check_then_else(&self,
32283228
cond_expr: &'gcx hir::Expr,
32293229
then_expr: &'gcx hir::Expr,
@@ -5218,14 +5218,33 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
52185218
let (def_id, ty) = match def {
52195219
Def::SelfCtor(impl_def_id) => {
52205220
let ty = self.impl_self_ty(span, impl_def_id).ty;
5221+
let adt_def = ty.ty_adt_def();
52215222

5222-
match ty.ty_adt_def() {
5223-
Some(adt_def) if adt_def.is_struct() => {
5223+
match adt_def {
5224+
Some(adt_def) if adt_def.is_tuple_struct() => {
52245225
let variant = adt_def.non_enum_variant();
52255226
new_def = Def::StructCtor(variant.did, variant.ctor_kind);
52265227
(variant.did, tcx.type_of(variant.did))
52275228
}
52285229
_ => {
5230+
let mut err = tcx.sess.struct_span_err(span,
5231+
"the `Self` constructor can only be used with tuple structs");
5232+
if let Some(adt_def) = adt_def {
5233+
match adt_def.adt_kind() {
5234+
AdtKind::Enum => {
5235+
err.note("did you mean to use one of the enum's variants?");
5236+
},
5237+
AdtKind::Union => {},
5238+
AdtKind::Struct => {
5239+
err.span_label(
5240+
span,
5241+
format!("did you mean `Self {{ /* fields */ }}`?"),
5242+
);
5243+
}
5244+
}
5245+
}
5246+
err.emit();
5247+
52295248
(impl_def_id, tcx.types.err)
52305249
}
52315250
}

src/test/ui/issues/issue-56199.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
enum Foo {}
3+
struct Bar {}
4+
5+
impl Foo {
6+
fn foo() {
7+
let _ = Self;
8+
//~^ ERROR the `Self` constructor can only be used with tuple structs
9+
let _ = Self();
10+
//~^ ERROR the `Self` constructor can only be used with tuple structs
11+
}
12+
}
13+
14+
impl Bar {
15+
fn bar() {
16+
let _ = Self;
17+
//~^ ERROR the `Self` constructor can only be used with tuple structs
18+
let _ = Self();
19+
//~^ ERROR the `Self` constructor can only be used with tuple structs
20+
}
21+
}
22+
23+
fn main() {}

src/test/ui/issues/issue-56199.stderr

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error: the `Self` constructor can only be used with tuple structs
2+
--> $DIR/issue-56199.rs:7:17
3+
|
4+
LL | let _ = Self;
5+
| ^^^^
6+
|
7+
= note: did you mean to use one of the enum's variants?
8+
9+
error: the `Self` constructor can only be used with tuple structs
10+
--> $DIR/issue-56199.rs:9:17
11+
|
12+
LL | let _ = Self();
13+
| ^^^^
14+
|
15+
= note: did you mean to use one of the enum's variants?
16+
17+
error: the `Self` constructor can only be used with tuple structs
18+
--> $DIR/issue-56199.rs:16:17
19+
|
20+
LL | let _ = Self;
21+
| ^^^^ did you mean `Self { /* fields */ }`?
22+
23+
error: the `Self` constructor can only be used with tuple structs
24+
--> $DIR/issue-56199.rs:18:17
25+
|
26+
LL | let _ = Self();
27+
| ^^^^ did you mean `Self { /* fields */ }`?
28+
29+
error: aborting due to 4 previous errors
30+

0 commit comments

Comments
 (0)