Skip to content

Commit a5b0311

Browse files
committed
rustc_layout, rustc_abi: make sure the types are well-formed
1 parent 38bbc2c commit a5b0311

File tree

9 files changed

+87
-36
lines changed

9 files changed

+87
-36
lines changed

compiler/rustc_passes/src/abi_test.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustc_span::source_map::Spanned;
77
use rustc_span::symbol::sym;
88
use rustc_target::abi::call::FnAbi;
99

10+
use super::layout_test::ensure_wf;
1011
use crate::errors::{AbiInvalidAttribute, AbiNe, AbiOf, UnrecognizedField};
1112

1213
pub fn test_abi(tcx: TyCtxt<'_>) {
@@ -131,6 +132,10 @@ fn test_abi_eq<'tcx>(abi1: &'tcx FnAbi<'tcx, Ty<'tcx>>, abi2: &'tcx FnAbi<'tcx,
131132
fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: DefId, attr: &Attribute) {
132133
let param_env = tcx.param_env(item_def_id);
133134
let ty = tcx.type_of(item_def_id).instantiate_identity();
135+
let span = tcx.def_span(item_def_id);
136+
if !ensure_wf(tcx, param_env, ty, span) {
137+
return;
138+
}
134139
let meta_items = attr.meta_item_list().unwrap_or_default();
135140
for meta_item in meta_items {
136141
match meta_item.name_or_empty() {
@@ -148,11 +153,7 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: DefId, attr: &Attribute) {
148153
);
149154

150155
let fn_name = tcx.item_name(item_def_id);
151-
tcx.sess.emit_err(AbiOf {
152-
span: tcx.def_span(item_def_id),
153-
fn_name,
154-
fn_abi: format!("{:#?}", abi),
155-
});
156+
tcx.sess.emit_err(AbiOf { span, fn_name, fn_abi: format!("{:#?}", abi) });
156157
}
157158
sym::assert_eq => {
158159
let ty::Tuple(fields) = ty.kind() else {
@@ -196,7 +197,7 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: DefId, attr: &Attribute) {
196197

197198
if !test_abi_eq(abi1, abi2) {
198199
tcx.sess.emit_err(AbiNe {
199-
span: tcx.def_span(item_def_id),
200+
span,
200201
left: format!("{:#?}", abi1),
201202
right: format!("{:#?}", abi2),
202203
});

compiler/rustc_passes/src/layout_test.rs

+40-21
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ use rustc_ast::Attribute;
22
use rustc_hir::def::DefKind;
33
use rustc_hir::def_id::LocalDefId;
44
use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout};
5-
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
5+
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
66
use rustc_span::source_map::Spanned;
77
use rustc_span::symbol::sym;
88
use rustc_span::Span;
99
use rustc_target::abi::{HasDataLayout, TargetDataLayout};
10+
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
11+
use rustc_trait_selection::{infer::TyCtxtInferExt, traits};
1012

1113
use crate::errors::{
1214
LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutInvalidAttribute, LayoutOf,
@@ -40,9 +42,39 @@ pub fn test_layout(tcx: TyCtxt<'_>) {
4042
}
4143
}
4244

45+
pub fn ensure_wf<'tcx>(
46+
tcx: TyCtxt<'tcx>,
47+
param_env: ParamEnv<'tcx>,
48+
ty: Ty<'tcx>,
49+
span: Span,
50+
) -> bool {
51+
let pred = ty::ClauseKind::WellFormed(ty.into());
52+
let obligation = traits::Obligation::new(
53+
tcx,
54+
traits::ObligationCause::dummy_with_span(span),
55+
param_env,
56+
pred,
57+
);
58+
let infcx = tcx.infer_ctxt().build();
59+
let ocx = traits::ObligationCtxt::new(&infcx);
60+
ocx.register_obligation(obligation);
61+
let errors = ocx.select_all_or_error();
62+
if !errors.is_empty() {
63+
infcx.err_ctxt().report_fulfillment_errors(&errors);
64+
false
65+
} else {
66+
// looks WF!
67+
true
68+
}
69+
}
70+
4371
fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
4472
let param_env = tcx.param_env(item_def_id);
4573
let ty = tcx.type_of(item_def_id).instantiate_identity();
74+
let span = tcx.def_span(item_def_id.to_def_id());
75+
if !ensure_wf(tcx, param_env, ty, span) {
76+
return;
77+
}
4678
match tcx.layout_of(param_env.and(ty)) {
4779
Ok(ty_layout) => {
4880
// Check out the `#[rustc_layout(..)]` attribute to tell what to dump.
@@ -51,29 +83,24 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
5183
for meta_item in meta_items {
5284
match meta_item.name_or_empty() {
5385
sym::abi => {
54-
tcx.sess.emit_err(LayoutAbi {
55-
span: tcx.def_span(item_def_id.to_def_id()),
56-
abi: format!("{:?}", ty_layout.abi),
57-
});
86+
tcx.sess.emit_err(LayoutAbi { span, abi: format!("{:?}", ty_layout.abi) });
5887
}
5988

6089
sym::align => {
6190
tcx.sess.emit_err(LayoutAlign {
62-
span: tcx.def_span(item_def_id.to_def_id()),
91+
span,
6392
align: format!("{:?}", ty_layout.align),
6493
});
6594
}
6695

6796
sym::size => {
68-
tcx.sess.emit_err(LayoutSize {
69-
span: tcx.def_span(item_def_id.to_def_id()),
70-
size: format!("{:?}", ty_layout.size),
71-
});
97+
tcx.sess
98+
.emit_err(LayoutSize { span, size: format!("{:?}", ty_layout.size) });
7299
}
73100

74101
sym::homogeneous_aggregate => {
75102
tcx.sess.emit_err(LayoutHomogeneousAggregate {
76-
span: tcx.def_span(item_def_id.to_def_id()),
103+
span,
77104
homogeneous_aggregate: format!(
78105
"{:?}",
79106
ty_layout.homogeneous_aggregate(&UnwrapLayoutCx { tcx, param_env })
@@ -90,11 +117,7 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
90117
)
91118
);
92119
let ty_layout = format!("{:#?}", *ty_layout);
93-
tcx.sess.emit_err(LayoutOf {
94-
span: tcx.def_span(item_def_id.to_def_id()),
95-
normalized_ty,
96-
ty_layout,
97-
});
120+
tcx.sess.emit_err(LayoutOf { span, normalized_ty, ty_layout });
98121
}
99122

100123
name => {
@@ -105,11 +128,7 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
105128
}
106129

107130
Err(layout_error) => {
108-
tcx.sess.emit_fatal(Spanned {
109-
node: layout_error.into_diagnostic(),
110-
111-
span: tcx.def_span(item_def_id.to_def_id()),
112-
});
131+
tcx.sess.emit_fatal(Spanned { node: layout_error.into_diagnostic(), span });
113132
}
114133
}
115134
}

tests/ui/abi/compatibility.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![feature(rustc_attrs, transparent_unions)]
33
#![allow(unused, improper_ctypes_definitions)]
44
use std::marker::PhantomData;
5+
use std::mem::ManuallyDrop;
56
use std::num::NonZeroI32;
67
use std::ptr::NonNull;
78

@@ -37,9 +38,9 @@ enum ReprCEnum<T> {
3738
Variant2(T),
3839
}
3940
#[repr(C)]
40-
union ReprCUnion<T: Copy> {
41+
union ReprCUnion<T> {
4142
nothing: (),
42-
something: T,
43+
something: ManuallyDrop<T>,
4344
}
4445

4546
macro_rules! test_abi_compatible {
@@ -82,9 +83,9 @@ struct Wrapper2<T>((), Zst, T);
8283
#[repr(transparent)]
8384
struct Wrapper3<T>(T, [u8; 0], PhantomData<u64>);
8485
#[repr(transparent)]
85-
union WrapperUnion<T: Copy> {
86+
union WrapperUnion<T> {
8687
nothing: (),
87-
something: T,
88+
something: ManuallyDrop<T>,
8889
}
8990

9091
macro_rules! test_transparent {

tests/ui/abi/debug.rs

+3
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,6 @@ type TestAbiNeFloat = (fn(f32), fn(u32)); //~ ERROR: ABIs are not compatible
4848
// Sign matters on some targets (such as s390x), so let's make sure we never accept this.
4949
#[rustc_abi(assert_eq)]
5050
type TestAbiNeSign = (fn(i32), fn(u32)); //~ ERROR: ABIs are not compatible
51+
52+
#[rustc_abi(assert_eq)]
53+
type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); //~ ERROR: cannot be known at compilation time

tests/ui/abi/debug.stderr

+11-1
Original file line numberDiff line numberDiff line change
@@ -945,5 +945,15 @@ error: ABIs are not compatible
945945
LL | type TestAbiNeSign = (fn(i32), fn(u32));
946946
| ^^^^^^^^^^^^^^^^^^
947947

948-
error: aborting due to 10 previous errors
948+
error[E0277]: the size for values of type `str` cannot be known at compilation time
949+
--> $DIR/debug.rs:53:1
950+
|
951+
LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str)));
952+
| ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
953+
|
954+
= help: the trait `Sized` is not implemented for `str`
955+
= note: only the last element of a tuple may have a dynamically sized type
956+
957+
error: aborting due to 11 previous errors
949958

959+
For more information about this error, try `rustc --explain E0277`.

tests/ui/associated-types/issue-85103.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ use std::borrow::Cow;
44

55
#[rustc_layout(debug)]
66
type Edges<'a, E> = Cow<'a, [E]>;
7-
//~^ 6:1: 6:18: unable to determine layout for `<[E] as ToOwned>::Owned` because `<[E] as ToOwned>::Owned` cannot be normalized
7+
//~^ the trait bound `[E]: ToOwned` is not satisfied
88

99
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
error: unable to determine layout for `<[E] as ToOwned>::Owned` because `<[E] as ToOwned>::Owned` cannot be normalized
1+
error[E0277]: the trait bound `[E]: ToOwned` is not satisfied
22
--> $DIR/issue-85103.rs:6:1
33
|
44
LL | type Edges<'a, E> = Cow<'a, [E]>;
5-
| ^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^ the trait `ToOwned` is not implemented for `[E]`
6+
|
7+
note: required by a bound in `Cow`
8+
--> $SRC_DIR/alloc/src/borrow.rs:LL:COL
69

710
error: aborting due to previous error
811

12+
For more information about this error, try `rustc --explain E0277`.

tests/ui/layout/debug.rs

+3
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,6 @@ impl S {
7373
#[rustc_layout(debug)]
7474
const C: () = (); //~ ERROR: can only be applied to
7575
}
76+
77+
#[rustc_layout(debug)]
78+
type Impossible = (str, str); //~ ERROR: cannot be known at compilation time

tests/ui/layout/debug.stderr

+11-1
Original file line numberDiff line numberDiff line change
@@ -563,5 +563,15 @@ error: `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarat
563563
LL | const C: () = ();
564564
| ^^^^^^^^^^^
565565

566-
error: aborting due to 16 previous errors
566+
error[E0277]: the size for values of type `str` cannot be known at compilation time
567+
--> $DIR/debug.rs:78:1
568+
|
569+
LL | type Impossible = (str, str);
570+
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
571+
|
572+
= help: the trait `Sized` is not implemented for `str`
573+
= note: only the last element of a tuple may have a dynamically sized type
574+
575+
error: aborting due to 17 previous errors
567576

577+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)