Skip to content

Commit

Permalink
Rollup merge of rust-lang#61748 - estebank:transparent-span, r=Centril
Browse files Browse the repository at this point in the history
Tweak transparent enums and unions diagnostic spans
  • Loading branch information
Centril authored Jun 18, 2019
2 parents 65da792 + f06b761 commit 06d2a89
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 102 deletions.
101 changes: 68 additions & 33 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1788,32 +1788,71 @@ fn check_packed_inner<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, stack: &mut Vec<De
false
}

/// Emit an error when encountering more or less than one variant in a transparent enum.
fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, did: DefId) {
let variant_spans: Vec<_> = adt.variants.iter().map(|variant| {
tcx.hir().span_if_local(variant.def_id).unwrap()
}).collect();
let msg = format!(
"needs exactly one variant, but has {}",
adt.variants.len(),
);
let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg);
err.span_label(sp, &msg);
if let &[ref start.., ref end] = &variant_spans[..] {
for variant_span in start {
err.span_label(*variant_span, "");
}
err.span_label(*end, &format!("too many variants in `{}`", tcx.def_path_str(did)));
}
err.emit();
}

/// Emit an error when encountering more or less than one non-zero-sized field in a transparent
/// enum.
fn bad_non_zero_sized_fields<'tcx>(
tcx: TyCtxt<'tcx>,
adt: &'tcx ty::AdtDef,
field_count: usize,
field_spans: impl Iterator<Item = Span>,
sp: Span,
) {
let msg = format!("needs exactly one non-zero-sized field, but has {}", field_count);
let mut err = struct_span_err!(
tcx.sess,
sp,
E0690,
"{}transparent {} {}",
if adt.is_enum() { "the variant of a " } else { "" },
adt.descr(),
msg,
);
err.span_label(sp, &msg);
for sp in field_spans {
err.span_label(sp, "this field is non-zero-sized");
}
err.emit();
}

fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) {
let adt = tcx.adt_def(def_id);
if !adt.repr.transparent() {
return;
}
let sp = tcx.sess.source_map().def_span(sp);

if adt.is_enum() {
if !tcx.features().transparent_enums {
emit_feature_err(&tcx.sess.parse_sess,
sym::transparent_enums,
sp,
GateIssue::Language,
"transparent enums are unstable");
emit_feature_err(
&tcx.sess.parse_sess,
sym::transparent_enums,
sp,
GateIssue::Language,
"transparent enums are unstable",
);
}
if adt.variants.len() != 1 {
let variant_spans: Vec<_> = adt.variants.iter().map(|variant| {
tcx.hir().span_if_local(variant.def_id).unwrap()
}).collect();
let mut err = struct_span_err!(tcx.sess, sp, E0731,
"transparent enum needs exactly one variant, but has {}",
adt.variants.len());
if !variant_spans.is_empty() {
err.span_note(variant_spans, &format!("the following variants exist on `{}`",
tcx.def_path_str(def_id)));
}
err.emit();
bad_variant_count(tcx, adt, sp, def_id);
if adt.variants.is_empty() {
// Don't bother checking the fields. No variants (and thus no fields) exist.
return;
Expand Down Expand Up @@ -1841,28 +1880,24 @@ fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) {
(span, zst, align1)
});

let non_zst_fields = field_infos.clone().filter(|(_span, zst, _align1)| !*zst);
let non_zst_fields = field_infos.clone().filter_map(|(span, zst, _align1)| if !zst {
Some(span)
} else {
None
});
let non_zst_count = non_zst_fields.clone().count();
if non_zst_count != 1 {
let field_spans: Vec<_> = non_zst_fields.map(|(span, _zst, _align1)| span).collect();

let mut err = struct_span_err!(tcx.sess, sp, E0690,
"{}transparent {} needs exactly one non-zero-sized field, but has {}",
if adt.is_enum() { "the variant of a " } else { "" },
adt.descr(),
non_zst_count);
if !field_spans.is_empty() {
err.span_note(field_spans,
&format!("the following non-zero-sized fields exist on `{}`:",
tcx.def_path_str(def_id)));
}
err.emit();
bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, sp);
}
for (span, zst, align1) in field_infos {
if zst && !align1 {
span_err!(tcx.sess, span, E0691,
"zero-sized field in transparent {} has alignment larger than 1",
adt.descr());
struct_span_err!(
tcx.sess,
span,
E0691,
"zero-sized field in transparent {} has alignment larger than 1",
adt.descr(),
).span_label(span, "has alignment larger than 1").emit();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
error[E0658]: transparent enums are unstable
--> $DIR/feature-gate-transparent_enums.rs:2:1
|
LL | / enum OkButUnstableEnum {
LL | | Foo((), String, ()),
LL | | }
| |_^
LL | enum OkButUnstableEnum {
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/60405
= help: add #![feature(transparent_enums)] to the crate attributes to enable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
error[E0658]: transparent unions are unstable
--> $DIR/feature-gate-transparent_unions.rs:2:1
|
LL | / union OkButUnstableUnion {
LL | | field: u8,
LL | | zst: (),
LL | | }
| |_^
LL | union OkButUnstableUnion {
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/60405
= help: add #![feature(transparent_unions)] to the crate attributes to enable
Expand Down
94 changes: 34 additions & 60 deletions src/test/ui/repr/repr-transparent.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,57 @@ error[E0690]: transparent struct needs exactly one non-zero-sized field, but has
--> $DIR/repr-transparent.rs:11:1
|
LL | struct NoFields;
| ^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0

error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
--> $DIR/repr-transparent.rs:14:1
|
LL | struct ContainsOnlyZst(());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0

error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
--> $DIR/repr-transparent.rs:17:1
|
LL | struct ContainsOnlyZstArray([bool; 0]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0

error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
--> $DIR/repr-transparent.rs:20:1
|
LL | struct ContainsMultipleZst(PhantomData<*const i32>, NoFields);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0

error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 2
--> $DIR/repr-transparent.rs:24:1
|
LL | struct MultipleNonZst(u8, u8);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the following non-zero-sized fields exist on `MultipleNonZst`:
--> $DIR/repr-transparent.rs:24:23
|
LL | struct MultipleNonZst(u8, u8);
| ^^ ^^
| ^^^^^^^^^^^^^^^^^^^^^^--^^--^^
| | | |
| | | this field is non-zero-sized
| | this field is non-zero-sized
| needs exactly one non-zero-sized field, but has 2

error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 2
--> $DIR/repr-transparent.rs:30:1
|
LL | pub struct StructWithProjection(f32, <f32 as Mirror>::It);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the following non-zero-sized fields exist on `StructWithProjection`:
--> $DIR/repr-transparent.rs:30:33
|
LL | pub struct StructWithProjection(f32, <f32 as Mirror>::It);
| ^^^ ^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^-------------------^^
| | | |
| | | this field is non-zero-sized
| | this field is non-zero-sized
| needs exactly one non-zero-sized field, but has 2

error[E0691]: zero-sized field in transparent struct has alignment larger than 1
--> $DIR/repr-transparent.rs:34:32
|
LL | struct NontrivialAlignZst(u32, [u16; 0]);
| ^^^^^^^^
| ^^^^^^^^ has alignment larger than 1

error[E0691]: zero-sized field in transparent struct has alignment larger than 1
--> $DIR/repr-transparent.rs:40:24
|
LL | struct GenericAlign<T>(ZstAlign32<T>, u32);
| ^^^^^^^^^^^^^
| ^^^^^^^^^^^^^ has alignment larger than 1

error[E0084]: unsupported representation for zero-variant enum
--> $DIR/repr-transparent.rs:42:1
Expand All @@ -70,71 +66,49 @@ error[E0731]: transparent enum needs exactly one variant, but has 0
--> $DIR/repr-transparent.rs:43:1
|
LL | enum Void {}
| ^^^^^^^^^^^^
| ^^^^^^^^^ needs exactly one variant, but has 0

error[E0690]: the variant of a transparent enum needs exactly one non-zero-sized field, but has 0
--> $DIR/repr-transparent.rs:47:1
|
LL | / enum FieldlessEnum {
LL | | Foo,
LL | | }
| |_^
LL | enum FieldlessEnum {
| ^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0

error[E0690]: the variant of a transparent enum needs exactly one non-zero-sized field, but has 2
--> $DIR/repr-transparent.rs:52:1
|
LL | / enum TooManyFieldsEnum {
LL | | Foo(u32, String),
LL | | }
| |_^
|
note: the following non-zero-sized fields exist on `TooManyFieldsEnum`:
--> $DIR/repr-transparent.rs:53:9
|
LL | enum TooManyFieldsEnum {
| ^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 2
LL | Foo(u32, String),
| ^^^ ^^^^^^
| --- ------ this field is non-zero-sized
| |
| this field is non-zero-sized

error[E0731]: transparent enum needs exactly one variant, but has 2
--> $DIR/repr-transparent.rs:58:1
|
LL | / enum TooManyVariants {
LL | | Foo(String),
LL | | Bar,
LL | | }
| |_^
|
note: the following variants exist on `TooManyVariants`
--> $DIR/repr-transparent.rs:59:5
|
LL | enum TooManyVariants {
| ^^^^^^^^^^^^^^^^^^^^ needs exactly one variant, but has 2
LL | Foo(String),
| ^^^^^^^^^^^
| -----------
LL | Bar,
| ^^^
| --- too many variants in `TooManyVariants`

error[E0690]: transparent union needs exactly one non-zero-sized field, but has 0
--> $DIR/repr-transparent.rs:64:1
|
LL | / union UnitUnion {
LL | | u: (),
LL | | }
| |_^
LL | union UnitUnion {
| ^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0

error[E0690]: transparent union needs exactly one non-zero-sized field, but has 2
--> $DIR/repr-transparent.rs:69:1
|
LL | / union TooManyFields {
LL | | u: u32,
LL | | s: i32
LL | | }
| |_^
|
note: the following non-zero-sized fields exist on `TooManyFields`:
--> $DIR/repr-transparent.rs:70:5
|
LL | union TooManyFields {
| ^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 2
LL | u: u32,
| ^^^^^^
| ------ this field is non-zero-sized
LL | s: i32
| ^^^^^^
| ------ this field is non-zero-sized

error: aborting due to 15 previous errors

Expand Down

0 comments on commit 06d2a89

Please sign in to comment.