mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-14 01:25:54 +00:00
Detail transitive containment in E0588 diagnostic
This commit is contained in:
parent
ef92009c1d
commit
3ab95ceb12
@ -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!(
|
||||
tcx.sess,
|
||||
sp,
|
||||
E0588,
|
||||
"packed type cannot transitively contain a `[repr(align)]` type"
|
||||
)
|
||||
.emit();
|
||||
} 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"
|
||||
);
|
||||
|
||||
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
|
||||
)
|
||||
} else {
|
||||
format!("...which contains a field of type `{}`", ident)
|
||||
},
|
||||
);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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.
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user