Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tweak transparent enums and unions diagnostic spans #61748

Merged
merged 2 commits into from
Jun 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 68 additions & 33 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1789,32 +1789,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");
Centril marked this conversation as resolved.
Show resolved Hide resolved
}
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 @@ -1842,28 +1881,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!(
Centril marked this conversation as resolved.
Show resolved Hide resolved
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