@@ -6,7 +6,7 @@ use super::*;
6
6
use rustc_attr as attr;
7
7
use rustc_errors:: { Applicability , ErrorGuaranteed , MultiSpan } ;
8
8
use rustc_hir as hir;
9
- use rustc_hir:: def:: { DefKind , Res } ;
9
+ use rustc_hir:: def:: { CtorKind , DefKind , Res } ;
10
10
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
11
11
use rustc_hir:: intravisit:: Visitor ;
12
12
use rustc_hir:: { ItemKind , Node , PathSegment } ;
@@ -75,15 +75,15 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) {
75
75
check_simd ( tcx, span, def_id) ;
76
76
}
77
77
78
- check_transparent ( tcx, span , def) ;
78
+ check_transparent ( tcx, def) ;
79
79
check_packed ( tcx, span, def) ;
80
80
}
81
81
82
82
fn check_union ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) {
83
83
let def = tcx. adt_def ( def_id) ;
84
84
let span = tcx. def_span ( def_id) ;
85
85
def. destructor ( tcx) ; // force the destructor to be evaluated
86
- check_transparent ( tcx, span , def) ;
86
+ check_transparent ( tcx, def) ;
87
87
check_union_fields ( tcx, span, def_id) ;
88
88
check_packed ( tcx, span, def) ;
89
89
}
@@ -506,11 +506,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
506
506
tcx. ensure ( ) . typeck ( id. owner_id . def_id ) ;
507
507
}
508
508
DefKind :: Enum => {
509
- let item = tcx. hir ( ) . item ( id) ;
510
- let hir:: ItemKind :: Enum ( ref enum_definition, _) = item. kind else {
511
- return ;
512
- } ;
513
- check_enum ( tcx, & enum_definition. variants , item. owner_id . def_id ) ;
509
+ check_enum ( tcx, id. owner_id . def_id ) ;
514
510
}
515
511
DefKind :: Fn => { } // entirely within check_item_body
516
512
DefKind :: Impl => {
@@ -1026,7 +1022,7 @@ pub(super) fn check_packed_inner(
1026
1022
None
1027
1023
}
1028
1024
1029
- pub ( super ) fn check_transparent < ' tcx > ( tcx : TyCtxt < ' tcx > , sp : Span , adt : ty:: AdtDef < ' tcx > ) {
1025
+ pub ( super ) fn check_transparent < ' tcx > ( tcx : TyCtxt < ' tcx > , adt : ty:: AdtDef < ' tcx > ) {
1030
1026
if !adt. repr ( ) . transparent ( ) {
1031
1027
return ;
1032
1028
}
@@ -1035,14 +1031,14 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
1035
1031
feature_err (
1036
1032
& tcx. sess . parse_sess ,
1037
1033
sym:: transparent_unions,
1038
- sp ,
1034
+ tcx . def_span ( adt . did ( ) ) ,
1039
1035
"transparent unions are unstable" ,
1040
1036
)
1041
1037
. emit ( ) ;
1042
1038
}
1043
1039
1044
1040
if adt. variants ( ) . len ( ) != 1 {
1045
- bad_variant_count ( tcx, adt, sp , adt. did ( ) ) ;
1041
+ bad_variant_count ( tcx, adt, tcx . def_span ( adt . did ( ) ) , adt. did ( ) ) ;
1046
1042
if adt. variants ( ) . is_empty ( ) {
1047
1043
// Don't bother checking the fields. No variants (and thus no fields) exist.
1048
1044
return ;
@@ -1103,7 +1099,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
1103
1099
. filter_map ( |( span, zst, _align1, _non_exhaustive) | if !zst { Some ( span) } else { None } ) ;
1104
1100
let non_zst_count = non_zst_fields. clone ( ) . count ( ) ;
1105
1101
if non_zst_count >= 2 {
1106
- bad_non_zero_sized_fields ( tcx, adt, non_zst_count, non_zst_fields, sp ) ;
1102
+ bad_non_zero_sized_fields ( tcx, adt, non_zst_count, non_zst_fields, tcx . def_span ( adt . did ( ) ) ) ;
1107
1103
}
1108
1104
let incompatible_zst_fields =
1109
1105
field_infos. clone ( ) . filter ( |( _, _, _, opt) | opt. is_some ( ) ) . count ( ) ;
@@ -1143,20 +1139,19 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
1143
1139
}
1144
1140
1145
1141
#[ allow( trivial_numeric_casts) ]
1146
- fn check_enum < ' tcx > ( tcx : TyCtxt < ' tcx > , vs : & ' tcx [ hir :: Variant < ' tcx > ] , def_id : LocalDefId ) {
1142
+ fn check_enum < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : LocalDefId ) {
1147
1143
let def = tcx. adt_def ( def_id) ;
1148
- let sp = tcx. def_span ( def_id) ;
1149
1144
def. destructor ( tcx) ; // force the destructor to be evaluated
1150
1145
1151
- if vs . is_empty ( ) {
1146
+ if def . variants ( ) . is_empty ( ) {
1152
1147
if let Some ( attr) = tcx. get_attrs ( def_id. to_def_id ( ) , sym:: repr) . next ( ) {
1153
1148
struct_span_err ! (
1154
1149
tcx. sess,
1155
1150
attr. span,
1156
1151
E0084 ,
1157
1152
"unsupported representation for zero-variant enum"
1158
1153
)
1159
- . span_label ( sp , "zero-variant enum" )
1154
+ . span_label ( tcx . def_span ( def_id ) , "zero-variant enum" )
1160
1155
. emit ( ) ;
1161
1156
}
1162
1157
}
@@ -1167,88 +1162,96 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L
1167
1162
feature_err (
1168
1163
& tcx. sess . parse_sess ,
1169
1164
sym:: repr128,
1170
- sp ,
1165
+ tcx . def_span ( def_id ) ,
1171
1166
"repr with 128-bit type is unstable" ,
1172
1167
)
1173
1168
. emit ( ) ;
1174
1169
}
1175
1170
}
1176
1171
1177
- for v in vs {
1178
- if let Some ( ref e ) = v. disr_expr {
1179
- tcx. ensure ( ) . typeck ( tcx . hir ( ) . local_def_id ( e . hir_id ) ) ;
1172
+ for v in def . variants ( ) {
1173
+ if let ty :: VariantDiscr :: Explicit ( discr_def_id ) = v. discr {
1174
+ tcx. ensure ( ) . typeck ( discr_def_id . expect_local ( ) ) ;
1180
1175
}
1181
1176
}
1182
1177
1183
- if tcx. adt_def ( def_id) . repr ( ) . int . is_none ( ) {
1184
- let is_unit = |var : & hir:: Variant < ' _ > | matches ! ( var. data, hir:: VariantData :: Unit ( ..) ) ;
1178
+ if def. repr ( ) . int . is_none ( ) {
1179
+ let is_unit = |var : & ty:: VariantDef | matches ! ( var. ctor_kind, CtorKind :: Const ) ;
1180
+ let has_disr = |var : & ty:: VariantDef | matches ! ( var. discr, ty:: VariantDiscr :: Explicit ( _) ) ;
1185
1181
1186
- let has_disr = |var : & hir:: Variant < ' _ > | var. disr_expr . is_some ( ) ;
1187
- let has_non_units = vs. iter ( ) . any ( |var| !is_unit ( var) ) ;
1188
- let disr_units = vs. iter ( ) . any ( |var| is_unit ( & var) && has_disr ( & var) ) ;
1189
- let disr_non_unit = vs. iter ( ) . any ( |var| !is_unit ( & var) && has_disr ( & var) ) ;
1182
+ let has_non_units = def. variants ( ) . iter ( ) . any ( |var| !is_unit ( var) ) ;
1183
+ let disr_units = def. variants ( ) . iter ( ) . any ( |var| is_unit ( & var) && has_disr ( & var) ) ;
1184
+ let disr_non_unit = def. variants ( ) . iter ( ) . any ( |var| !is_unit ( & var) && has_disr ( & var) ) ;
1190
1185
1191
1186
if disr_non_unit || ( disr_units && has_non_units) {
1192
- let mut err =
1193
- struct_span_err ! ( tcx. sess, sp, E0732 , "`#[repr(inttype)]` must be specified" ) ;
1187
+ let mut err = struct_span_err ! (
1188
+ tcx. sess,
1189
+ tcx. def_span( def_id) ,
1190
+ E0732 ,
1191
+ "`#[repr(inttype)]` must be specified"
1192
+ ) ;
1194
1193
err. emit ( ) ;
1195
1194
}
1196
1195
}
1197
1196
1198
- detect_discriminant_duplicate ( tcx, def. discriminants ( tcx) . collect ( ) , vs, sp) ;
1199
-
1200
- check_transparent ( tcx, sp, def) ;
1197
+ detect_discriminant_duplicate ( tcx, def) ;
1198
+ check_transparent ( tcx, def) ;
1201
1199
}
1202
1200
1203
1201
/// Part of enum check. Given the discriminants of an enum, errors if two or more discriminants are equal
1204
- fn detect_discriminant_duplicate < ' tcx > (
1205
- tcx : TyCtxt < ' tcx > ,
1206
- mut discrs : Vec < ( VariantIdx , Discr < ' tcx > ) > ,
1207
- vs : & ' tcx [ hir:: Variant < ' tcx > ] ,
1208
- self_span : Span ,
1209
- ) {
1202
+ fn detect_discriminant_duplicate < ' tcx > ( tcx : TyCtxt < ' tcx > , adt : ty:: AdtDef < ' tcx > ) {
1210
1203
// Helper closure to reduce duplicate code. This gets called everytime we detect a duplicate.
1211
1204
// Here `idx` refers to the order of which the discriminant appears, and its index in `vs`
1212
- let report = |dis : Discr < ' tcx > , idx : usize , err : & mut Diagnostic | {
1213
- let var = & vs [ idx] ; // HIR for the duplicate discriminant
1214
- let ( span, display_discr) = match var. disr_expr {
1215
- Some ( ref expr ) => {
1205
+ let report = |dis : Discr < ' tcx > , idx, err : & mut Diagnostic | {
1206
+ let var = adt . variant ( idx) ; // HIR for the duplicate discriminant
1207
+ let ( span, display_discr) = match var. discr {
1208
+ ty :: VariantDiscr :: Explicit ( discr_def_id ) => {
1216
1209
// In the case the discriminant is both a duplicate and overflowed, let the user know
1217
- if let hir:: ExprKind :: Lit ( lit) = & tcx. hir ( ) . body ( expr. body ) . value . kind
1210
+ if let hir:: Node :: AnonConst ( expr) = tcx. hir ( ) . get_by_def_id ( discr_def_id. expect_local ( ) )
1211
+ && let hir:: ExprKind :: Lit ( lit) = & tcx. hir ( ) . body ( expr. body ) . value . kind
1218
1212
&& let rustc_ast:: LitKind :: Int ( lit_value, _int_kind) = & lit. node
1219
1213
&& * lit_value != dis. val
1220
1214
{
1221
- ( tcx. hir ( ) . span ( expr. hir_id ) , format ! ( "`{dis}` (overflowed from `{lit_value}`)" ) )
1222
- // Otherwise, format the value as-is
1215
+ ( tcx. def_span ( discr_def_id) , format ! ( "`{dis}` (overflowed from `{lit_value}`)" ) )
1223
1216
} else {
1224
- ( tcx. hir ( ) . span ( expr. hir_id ) , format ! ( "`{dis}`" ) )
1217
+ // Otherwise, format the value as-is
1218
+ ( tcx. def_span ( discr_def_id) , format ! ( "`{dis}`" ) )
1225
1219
}
1226
1220
}
1227
- None => {
1221
+ // This should not happen.
1222
+ ty:: VariantDiscr :: Relative ( 0 ) => ( tcx. def_span ( var. def_id ) , format ! ( "`{dis}`" ) ) ,
1223
+ ty:: VariantDiscr :: Relative ( distance_to_explicit) => {
1228
1224
// At this point we know this discriminant is a duplicate, and was not explicitly
1229
1225
// assigned by the user. Here we iterate backwards to fetch the HIR for the last
1230
1226
// explicitly assigned discriminant, and letting the user know that this was the
1231
1227
// increment startpoint, and how many steps from there leading to the duplicate
1232
- if let Some ( ( n , hir :: Variant { span , ident , .. } ) ) =
1233
- vs [ .. idx] . iter ( ) . rev ( ) . enumerate ( ) . find ( |v| v . 1 . disr_expr . is_some ( ) )
1228
+ if let Some ( explicit_idx ) =
1229
+ idx. as_u32 ( ) . checked_sub ( distance_to_explicit ) . map ( VariantIdx :: from_u32 )
1234
1230
{
1235
- let ve_ident = var. ident ;
1236
- let n = n + 1 ;
1237
- let sp = if n > 1 { "variants" } else { "variant" } ;
1231
+ let explicit_variant = adt. variant ( explicit_idx) ;
1232
+ let ve_ident = var. name ;
1233
+ let ex_ident = explicit_variant. name ;
1234
+ let sp = if distance_to_explicit > 1 { "variants" } else { "variant" } ;
1238
1235
1239
1236
err. span_label (
1240
- * span,
1241
- format ! ( "discriminant for `{ve_ident}` incremented from this startpoint (`{ident}` + {n} {sp} later => `{ve_ident}` = {dis})" ) ,
1237
+ tcx. def_span ( explicit_variant. def_id ) ,
1238
+ format ! (
1239
+ "discriminant for `{ve_ident}` incremented from this startpoint \
1240
+ (`{ex_ident}` + {distance_to_explicit} {sp} later \
1241
+ => `{ve_ident}` = {dis})"
1242
+ ) ,
1242
1243
) ;
1243
1244
}
1244
1245
1245
- ( vs [ idx ] . span , format ! ( "`{dis}`" ) )
1246
+ ( tcx . def_span ( var . def_id ) , format ! ( "`{dis}`" ) )
1246
1247
}
1247
1248
} ;
1248
1249
1249
1250
err. span_label ( span, format ! ( "{display_discr} assigned here" ) ) ;
1250
1251
} ;
1251
1252
1253
+ let mut discrs = adt. discriminants ( tcx) . collect :: < Vec < _ > > ( ) ;
1254
+
1252
1255
// Here we loop through the discriminants, comparing each discriminant to another.
1253
1256
// When a duplicate is detected, we instantiate an error and point to both
1254
1257
// initial and duplicate value. The duplicate discriminant is then discarded by swapping
@@ -1257,29 +1260,29 @@ fn detect_discriminant_duplicate<'tcx>(
1257
1260
// style as we are mutating `discrs` on the fly).
1258
1261
let mut i = 0 ;
1259
1262
while i < discrs. len ( ) {
1260
- let hir_var_i_idx = discrs[ i] . 0 . index ( ) ;
1263
+ let var_i_idx = discrs[ i] . 0 ;
1261
1264
let mut error: Option < DiagnosticBuilder < ' _ , _ > > = None ;
1262
1265
1263
1266
let mut o = i + 1 ;
1264
1267
while o < discrs. len ( ) {
1265
- let hir_var_o_idx = discrs[ o] . 0 . index ( ) ;
1268
+ let var_o_idx = discrs[ o] . 0 ;
1266
1269
1267
1270
if discrs[ i] . 1 . val == discrs[ o] . 1 . val {
1268
1271
let err = error. get_or_insert_with ( || {
1269
1272
let mut ret = struct_span_err ! (
1270
1273
tcx. sess,
1271
- self_span ,
1274
+ tcx . def_span ( adt . did ( ) ) ,
1272
1275
E0081 ,
1273
1276
"discriminant value `{}` assigned more than once" ,
1274
1277
discrs[ i] . 1 ,
1275
1278
) ;
1276
1279
1277
- report ( discrs[ i] . 1 , hir_var_i_idx , & mut ret) ;
1280
+ report ( discrs[ i] . 1 , var_i_idx , & mut ret) ;
1278
1281
1279
1282
ret
1280
1283
} ) ;
1281
1284
1282
- report ( discrs[ o] . 1 , hir_var_o_idx , err) ;
1285
+ report ( discrs[ o] . 1 , var_o_idx , err) ;
1283
1286
1284
1287
// Safe to unwrap here, as we wouldn't reach this point if `discrs` was empty
1285
1288
discrs[ o] = * discrs. last ( ) . unwrap ( ) ;
0 commit comments