Detail transitive containment in E0588 diagnostic

This commit is contained in:
varkor 2020-01-07 00:00:16 +00:00
parent ef92009c1d
commit 3ab95ceb12
3 changed files with 174 additions and 41 deletions

View File

@ -118,7 +118,7 @@ use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LOCAL_CRATE};
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::{ExprKind, GenericArg, HirIdMap, ItemKind, Node, PatKind, QPath};
use rustc_hir::{ExprKind, GenericArg, HirIdMap, Item, ItemKind, Node, PatKind, QPath};
use rustc_index::vec::Idx;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::source_map::{original_sp, DUMMY_SP};
@ -2295,44 +2295,81 @@ fn check_packed(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) {
"type has conflicting packed and align representation hints"
)
.emit();
} else if check_packed_inner(tcx, def_id, &mut Vec::new()) {
struct_span_err!(
} else {
if let Some(def_spans) = check_packed_inner(tcx, def_id, &mut vec![]) {
let mut err = struct_span_err!(
tcx.sess,
sp,
E0588,
"packed type cannot transitively contain a `[repr(align)]` type"
"packed type cannot transitively contain a `#[repr(align)]` type"
);
let hir = tcx.hir();
if let Some(hir_id) = hir.as_local_hir_id(def_spans[0].0) {
if let Node::Item(Item { ident, .. }) = hir.get(hir_id) {
err.span_note(
tcx.def_span(def_spans[0].0),
&format!("`{}` has a `#[repr(align)]` attribute", ident),
);
}
}
if def_spans.len() > 2 {
let mut first = true;
for (adt_def, span) in def_spans.iter().skip(1).rev() {
if let Some(hir_id) = hir.as_local_hir_id(*adt_def) {
if let Node::Item(Item { ident, .. }) = hir.get(hir_id) {
err.span_note(
*span,
&if first {
format!(
"`{}` contains a field of type `{}`",
tcx.type_of(def_id),
ident
)
.emit();
} else {
format!("...which contains a field of type `{}`", ident)
},
);
first = false;
}
}
}
}
fn check_packed_inner(tcx: TyCtxt<'_>, def_id: DefId, stack: &mut Vec<DefId>) -> bool {
let t = tcx.type_of(def_id);
if stack.contains(&def_id) {
debug!("check_packed_inner: {:?} is recursive", t);
return false;
err.emit();
}
if let ty::Adt(def, substs) = t.kind {
}
}
}
fn check_packed_inner(
tcx: TyCtxt<'_>,
def_id: DefId,
stack: &mut Vec<DefId>,
) -> Option<Vec<(DefId, Span)>> {
if let ty::Adt(def, substs) = tcx.type_of(def_id).kind {
if def.is_struct() || def.is_union() {
if tcx.adt_def(def.did).repr.align.is_some() {
return true;
if def.repr.align.is_some() {
return Some(vec![(def.did, DUMMY_SP)]);
}
// push struct def_id before checking fields
stack.push(def_id);
for field in &def.non_enum_variant().fields {
let f = field.ty(tcx, substs);
if let ty::Adt(def, _) = f.kind {
if check_packed_inner(tcx, def.did, stack) {
return true;
if let ty::Adt(def, _) = field.ty(tcx, substs).kind {
if !stack.contains(&def.did) {
if let Some(mut defs) = check_packed_inner(tcx, def.did, stack) {
defs.push((def.did, field.ident.span));
return Some(defs);
}
}
}
}
// only need to pop if not early out
stack.pop();
}
}
false
None
}
/// Emit an error when encountering more or less than one variant in a transparent enum.

View File

@ -16,34 +16,34 @@ union UB {
}
#[repr(packed)]
struct SC(SA); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
struct SC(SA); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
#[repr(packed)]
struct SD(SB); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
struct SD(SB); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
#[repr(packed)]
struct SE(UA); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
struct SE(UA); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
#[repr(packed)]
struct SF(UB); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
struct SF(UB); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
#[repr(packed)]
union UC { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
union UC { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
a: UA
}
#[repr(packed)]
union UD { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
union UD { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
n: UB
}
#[repr(packed)]
union UE { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
union UE { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
a: SA
}
#[repr(packed)]
union UF { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
union UF { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
n: SB
}

View File

@ -1,58 +1,154 @@
error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> $DIR/repr-packed-contains-align.rs:19:1
|
LL | struct SC(SA);
| ^^^^^^^^^^^^^^
|
note: `SA` has a `#[repr(align)]` attribute
--> $DIR/repr-packed-contains-align.rs:5:1
|
LL | struct SA(i32);
| ^^^^^^^^^^^^^^^
error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> $DIR/repr-packed-contains-align.rs:22:1
|
LL | struct SD(SB);
| ^^^^^^^^^^^^^^
|
note: `SA` has a `#[repr(align)]` attribute
--> $DIR/repr-packed-contains-align.rs:5:1
|
LL | struct SA(i32);
| ^^^^^^^^^^^^^^^
note: `SD` contains a field of type `SB`
--> $DIR/repr-packed-contains-align.rs:22:11
|
LL | struct SD(SB);
| ^^
note: ...which contains a field of type `SA`
--> $DIR/repr-packed-contains-align.rs:7:11
|
LL | struct SB(SA);
| ^^
error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> $DIR/repr-packed-contains-align.rs:25:1
|
LL | struct SE(UA);
| ^^^^^^^^^^^^^^
|
note: `UA` has a `#[repr(align)]` attribute
--> $DIR/repr-packed-contains-align.rs:10:1
|
LL | / union UA {
LL | | i: i32
LL | | }
| |_^
error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> $DIR/repr-packed-contains-align.rs:28:1
|
LL | struct SF(UB);
| ^^^^^^^^^^^^^^
|
note: `UA` has a `#[repr(align)]` attribute
--> $DIR/repr-packed-contains-align.rs:10:1
|
LL | / union UA {
LL | | i: i32
LL | | }
| |_^
note: `SF` contains a field of type `UB`
--> $DIR/repr-packed-contains-align.rs:28:11
|
LL | struct SF(UB);
| ^^
note: ...which contains a field of type `UA`
--> $DIR/repr-packed-contains-align.rs:15:5
|
LL | a: UA
| ^
error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> $DIR/repr-packed-contains-align.rs:31:1
|
LL | / union UC {
LL | | a: UA
LL | | }
| |_^
|
note: `UA` has a `#[repr(align)]` attribute
--> $DIR/repr-packed-contains-align.rs:10:1
|
LL | / union UA {
LL | | i: i32
LL | | }
| |_^
error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> $DIR/repr-packed-contains-align.rs:36:1
|
LL | / union UD {
LL | | n: UB
LL | | }
| |_^
|
note: `UA` has a `#[repr(align)]` attribute
--> $DIR/repr-packed-contains-align.rs:10:1
|
LL | / union UA {
LL | | i: i32
LL | | }
| |_^
note: `UD` contains a field of type `UB`
--> $DIR/repr-packed-contains-align.rs:37:5
|
LL | n: UB
| ^
note: ...which contains a field of type `UA`
--> $DIR/repr-packed-contains-align.rs:15:5
|
LL | a: UA
| ^
error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> $DIR/repr-packed-contains-align.rs:41:1
|
LL | / union UE {
LL | | a: SA
LL | | }
| |_^
|
note: `SA` has a `#[repr(align)]` attribute
--> $DIR/repr-packed-contains-align.rs:5:1
|
LL | struct SA(i32);
| ^^^^^^^^^^^^^^^
error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> $DIR/repr-packed-contains-align.rs:46:1
|
LL | / union UF {
LL | | n: SB
LL | | }
| |_^
|
note: `SA` has a `#[repr(align)]` attribute
--> $DIR/repr-packed-contains-align.rs:5:1
|
LL | struct SA(i32);
| ^^^^^^^^^^^^^^^
note: `UF` contains a field of type `SB`
--> $DIR/repr-packed-contains-align.rs:47:5
|
LL | n: SB
| ^
note: ...which contains a field of type `SA`
--> $DIR/repr-packed-contains-align.rs:7:11
|
LL | struct SB(SA);
| ^^
error: aborting due to 8 previous errors