Skip to content

Commit ca4e394

Browse files
committed
Auto merge of #99203 - GuillaumeGomez:rollup-b2re0dv, r=GuillaumeGomez
Rollup of 10 pull requests Successful merges: - #98789 (rustdoc-json-types: Clean up derives.) - #98848 (Build the Clippy book as part of x.py doc) - #99020 (check non_exhaustive attr and private fields for transparent types) - #99132 (Add some autolabels for A-bootstrap and T-infra) - #99148 (Clarify that [iu]size bounds were only defined for the target arch) - #99152 (Use CSS variables to handle theming (part 2)) - #99168 (Add regression test for #74713) - #99176 (:arrow_up: rust-analyzer) - #99183 (Mention rust-analyzer maintainers when `proc_macro` bridge is changed) - #99185 (llvm-wrapper: adapt for LLVM API change) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents a639f89 + f290811 commit ca4e394

File tree

27 files changed

+565
-257
lines changed

27 files changed

+565
-257
lines changed

compiler/rustc_lint_defs/src/builtin.rs

+55
Original file line numberDiff line numberDiff line change
@@ -3132,6 +3132,60 @@ declare_lint! {
31323132
"detects unexpected names and values in `#[cfg]` conditions",
31333133
}
31343134

3135+
declare_lint! {
3136+
/// The `repr_transparent_external_private_fields` lint
3137+
/// detects types marked `#[repr(transparent)]` that (transitively)
3138+
/// contain an external ZST type marked `#[non_exhaustive]` or containing
3139+
/// private fields
3140+
///
3141+
/// ### Example
3142+
///
3143+
/// ```rust,ignore (needs external crate)
3144+
/// #![deny(repr_transparent_external_private_fields)]
3145+
/// use foo::NonExhaustiveZst;
3146+
///
3147+
/// #[repr(transparent)]
3148+
/// struct Bar(u32, ([u32; 0], NonExhaustiveZst));
3149+
/// ```
3150+
///
3151+
/// This will produce:
3152+
///
3153+
/// ```text
3154+
/// error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
3155+
/// --> src/main.rs:5:28
3156+
/// |
3157+
/// 5 | struct Bar(u32, ([u32; 0], NonExhaustiveZst));
3158+
/// | ^^^^^^^^^^^^^^^^
3159+
/// |
3160+
/// note: the lint level is defined here
3161+
/// --> src/main.rs:1:9
3162+
/// |
3163+
/// 1 | #![deny(repr_transparent_external_private_fields)]
3164+
/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3165+
/// = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
3166+
/// = note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
3167+
/// = note: this struct contains `NonExhaustiveZst`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.
3168+
/// ```
3169+
///
3170+
/// ### Explanation
3171+
///
3172+
/// Previous, Rust accepted fields that contain external private zero-sized types,
3173+
/// even though it should not be a breaking change to add a non-zero-sized field to
3174+
/// that private type.
3175+
///
3176+
/// This is a [future-incompatible] lint to transition this
3177+
/// to a hard error in the future. See [issue #78586] for more details.
3178+
///
3179+
/// [issue #78586]: https://github.com/rust-lang/rust/issues/78586
3180+
/// [future-incompatible]: ../index.md#future-incompatible-lints
3181+
pub REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
3182+
Warn,
3183+
"tranparent type contains an external ZST that is marked #[non_exhaustive] or contains private fields",
3184+
@future_incompatible = FutureIncompatibleInfo {
3185+
reference: "issue #78586 <https://github.com/rust-lang/rust/issues/78586>",
3186+
};
3187+
}
3188+
31353189
declare_lint_pass! {
31363190
/// Does nothing as a lint pass, but registers some `Lint`s
31373191
/// that are used by other parts of the compiler.
@@ -3237,6 +3291,7 @@ declare_lint_pass! {
32373291
DEPRECATED_WHERE_CLAUSE_LOCATION,
32383292
TEST_UNSTABLE_LINT,
32393293
FFI_UNWIND_CALLS,
3294+
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
32403295
]
32413296
}
32423297

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,14 @@ LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
411411

412412
extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
413413
size_t ConstraintsLen) {
414+
#if LLVM_VERSION_LT(15, 0)
414415
return InlineAsm::Verify(unwrap<FunctionType>(Ty),
415416
StringRef(Constraints, ConstraintsLen));
417+
#else
418+
// llvm::Error converts to true if it is an error.
419+
return !llvm::errorToBool(InlineAsm::verify(
420+
unwrap<FunctionType>(Ty), StringRef(Constraints, ConstraintsLen)));
421+
#endif
416422
}
417423

418424
extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,

compiler/rustc_typeck/src/check/check.rs

+66-5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use rustc_infer::infer::outlives::env::OutlivesEnvironment;
1717
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1818
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
1919
use rustc_infer::traits::Obligation;
20+
use rustc_lint::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
2021
use rustc_middle::hir::nested_filter;
2122
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
2223
use rustc_middle::ty::subst::GenericArgKind;
@@ -1318,7 +1319,8 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
13181319
}
13191320
}
13201321

1321-
// For each field, figure out if it's known to be a ZST and align(1)
1322+
// For each field, figure out if it's known to be a ZST and align(1), with "known"
1323+
// respecting #[non_exhaustive] attributes.
13221324
let field_infos = adt.all_fields().map(|field| {
13231325
let ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, field.did));
13241326
let param_env = tcx.param_env(field.did);
@@ -1327,16 +1329,56 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
13271329
let span = tcx.hir().span_if_local(field.did).unwrap();
13281330
let zst = layout.map_or(false, |layout| layout.is_zst());
13291331
let align1 = layout.map_or(false, |layout| layout.align.abi.bytes() == 1);
1330-
(span, zst, align1)
1332+
if !zst {
1333+
return (span, zst, align1, None);
1334+
}
1335+
1336+
fn check_non_exhaustive<'tcx>(
1337+
tcx: TyCtxt<'tcx>,
1338+
t: Ty<'tcx>,
1339+
) -> ControlFlow<(&'static str, DefId, SubstsRef<'tcx>, bool)> {
1340+
match t.kind() {
1341+
ty::Tuple(list) => list.iter().try_for_each(|t| check_non_exhaustive(tcx, t)),
1342+
ty::Array(ty, _) => check_non_exhaustive(tcx, *ty),
1343+
ty::Adt(def, subst) => {
1344+
if !def.did().is_local() {
1345+
let non_exhaustive = def.is_variant_list_non_exhaustive()
1346+
|| def
1347+
.variants()
1348+
.iter()
1349+
.any(ty::VariantDef::is_field_list_non_exhaustive);
1350+
let has_priv = def.all_fields().any(|f| !f.vis.is_public());
1351+
if non_exhaustive || has_priv {
1352+
return ControlFlow::Break((
1353+
def.descr(),
1354+
def.did(),
1355+
subst,
1356+
non_exhaustive,
1357+
));
1358+
}
1359+
}
1360+
def.all_fields()
1361+
.map(|field| field.ty(tcx, subst))
1362+
.try_for_each(|t| check_non_exhaustive(tcx, t))
1363+
}
1364+
_ => ControlFlow::Continue(()),
1365+
}
1366+
}
1367+
1368+
(span, zst, align1, check_non_exhaustive(tcx, ty).break_value())
13311369
});
13321370

1333-
let non_zst_fields =
1334-
field_infos.clone().filter_map(|(span, zst, _align1)| if !zst { Some(span) } else { None });
1371+
let non_zst_fields = field_infos
1372+
.clone()
1373+
.filter_map(|(span, zst, _align1, _non_exhaustive)| if !zst { Some(span) } else { None });
13351374
let non_zst_count = non_zst_fields.clone().count();
13361375
if non_zst_count >= 2 {
13371376
bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, sp);
13381377
}
1339-
for (span, zst, align1) in field_infos {
1378+
let incompatible_zst_fields =
1379+
field_infos.clone().filter(|(_, _, _, opt)| opt.is_some()).count();
1380+
let incompat = incompatible_zst_fields + non_zst_count >= 2 && non_zst_count < 2;
1381+
for (span, zst, align1, non_exhaustive) in field_infos {
13401382
if zst && !align1 {
13411383
struct_span_err!(
13421384
tcx.sess,
@@ -1348,6 +1390,25 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
13481390
.span_label(span, "has alignment larger than 1")
13491391
.emit();
13501392
}
1393+
if incompat && let Some((descr, def_id, substs, non_exhaustive)) = non_exhaustive {
1394+
tcx.struct_span_lint_hir(
1395+
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
1396+
tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()),
1397+
span,
1398+
|lint| {
1399+
let note = if non_exhaustive {
1400+
"is marked with `#[non_exhaustive]`"
1401+
} else {
1402+
"contains private fields"
1403+
};
1404+
let field_ty = tcx.def_path_str_with_substs(def_id, substs);
1405+
lint.build("zero-sized fields in repr(transparent) cannot contain external non-exhaustive types")
1406+
.note(format!("this {descr} contains `{field_ty}`, which {note}, \
1407+
and makes it not a breaking change to become non-zero-sized in the future."))
1408+
.emit();
1409+
},
1410+
)
1411+
}
13511412
}
13521413
}
13531414

library/core/src/num/int_macros.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ macro_rules! int_impl {
22
($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr, $BITS_MINUS_ONE:expr, $Min:expr, $Max:expr,
33
$rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr,
44
$reversed:expr, $le_bytes:expr, $be_bytes:expr,
5-
$to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => {
6-
/// The smallest value that can be represented by this integer type,
7-
#[doc = concat!("&minus;2<sup>", $BITS_MINUS_ONE, "</sup>.")]
5+
$to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr,
6+
$bound_condition:expr) => {
7+
/// The smallest value that can be represented by this integer type
8+
#[doc = concat!("(&minus;2<sup>", $BITS_MINUS_ONE, "</sup>", $bound_condition, ")")]
89
///
910
/// # Examples
1011
///
@@ -16,8 +17,8 @@ macro_rules! int_impl {
1617
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
1718
pub const MIN: Self = !0 ^ ((!0 as $UnsignedT) >> 1) as Self;
1819

19-
/// The largest value that can be represented by this integer type,
20-
#[doc = concat!("2<sup>", $BITS_MINUS_ONE, "</sup> &minus; 1.")]
20+
/// The largest value that can be represented by this integer type
21+
#[doc = concat!("(2<sup>", $BITS_MINUS_ONE, "</sup> &minus; 1", $bound_condition, ")")]
2122
///
2223
/// # Examples
2324
///

library/core/src/num/mod.rs

+22-16
Original file line numberDiff line numberDiff line change
@@ -196,25 +196,25 @@ macro_rules! widening_impl {
196196

197197
impl i8 {
198198
int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48",
199-
"[0x12]", "[0x12]", "", "" }
199+
"[0x12]", "[0x12]", "", "", "" }
200200
}
201201

202202
impl i16 {
203203
int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412",
204-
"0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
204+
"0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "", "" }
205205
}
206206

207207
impl i32 {
208208
int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
209209
"0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
210-
"[0x12, 0x34, 0x56, 0x78]", "", "" }
210+
"[0x12, 0x34, 0x56, 0x78]", "", "", "" }
211211
}
212212

213213
impl i64 {
214214
int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12,
215215
"0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
216216
"0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
217-
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" }
217+
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "", "" }
218218
}
219219

220220
impl i128 {
@@ -225,22 +225,24 @@ impl i128 {
225225
"[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
226226
0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
227227
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \
228-
0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", "", "" }
228+
0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", "", "", "" }
229229
}
230230

231231
#[cfg(target_pointer_width = "16")]
232232
impl isize {
233233
int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234",
234234
"0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]",
235-
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
235+
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!(),
236+
" on 16-bit targets" }
236237
}
237238

238239
#[cfg(target_pointer_width = "32")]
239240
impl isize {
240241
int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
241242
"0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
242243
"[0x12, 0x34, 0x56, 0x78]",
243-
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
244+
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!(),
245+
" on 32-bit targets" }
244246
}
245247

246248
#[cfg(target_pointer_width = "64")]
@@ -249,15 +251,16 @@ impl isize {
249251
12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
250252
"0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
251253
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
252-
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
254+
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!(),
255+
" on 64-bit targets" }
253256
}
254257

255258
/// If 6th bit set ascii is upper case.
256259
const ASCII_CASE_MASK: u8 = 0b0010_0000;
257260

258261
impl u8 {
259262
uint_impl! { u8, u8, i8, NonZeroU8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
260-
"[0x12]", "", "" }
263+
"[0x12]", "", "", "" }
261264
widening_impl! { u8, u16, 8, unsigned }
262265

263266
/// Checks if the value is within the ASCII range.
@@ -810,7 +813,7 @@ impl u8 {
810813

811814
impl u16 {
812815
uint_impl! { u16, u16, i16, NonZeroU16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
813-
"[0x34, 0x12]", "[0x12, 0x34]", "", "" }
816+
"[0x34, 0x12]", "[0x12, 0x34]", "", "", "" }
814817
widening_impl! { u16, u32, 16, unsigned }
815818

816819
/// Checks if the value is a Unicode surrogate code point, which are disallowed values for [`char`].
@@ -841,7 +844,7 @@ impl u16 {
841844

842845
impl u32 {
843846
uint_impl! { u32, u32, i32, NonZeroU32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
844-
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
847+
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "", "" }
845848
widening_impl! { u32, u64, 32, unsigned }
846849
}
847850

@@ -850,7 +853,7 @@ impl u64 {
850853
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
851854
"[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
852855
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
853-
"", ""}
856+
"", "", ""}
854857
widening_impl! { u64, u128, 64, unsigned }
855858
}
856859

@@ -862,21 +865,23 @@ impl u128 {
862865
0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
863866
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \
864867
0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]",
865-
"", ""}
868+
"", "", ""}
866869
}
867870

868871
#[cfg(target_pointer_width = "16")]
869872
impl usize {
870873
uint_impl! { usize, u16, isize, NonZeroUsize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
871874
"[0x34, 0x12]", "[0x12, 0x34]",
872-
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
875+
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!(),
876+
" on 16-bit targets" }
873877
widening_impl! { usize, u32, 16, unsigned }
874878
}
875879
#[cfg(target_pointer_width = "32")]
876880
impl usize {
877881
uint_impl! { usize, u32, isize, NonZeroUsize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
878882
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]",
879-
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
883+
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!(),
884+
" on 32-bit targets" }
880885
widening_impl! { usize, u64, 32, unsigned }
881886
}
882887

@@ -886,7 +891,8 @@ impl usize {
886891
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
887892
"[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
888893
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
889-
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
894+
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!(),
895+
" on 64-bit targets" }
890896
widening_impl! { usize, u128, 64, unsigned }
891897
}
892898

library/core/src/num/uint_macros.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ macro_rules! uint_impl {
33
$BITS:expr, $MaxV:expr,
44
$rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr,
55
$reversed:expr, $le_bytes:expr, $be_bytes:expr,
6-
$to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => {
6+
$to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr,
7+
$bound_condition:expr) => {
78
/// The smallest value that can be represented by this integer type.
89
///
910
/// # Examples
@@ -16,8 +17,8 @@ macro_rules! uint_impl {
1617
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
1718
pub const MIN: Self = 0;
1819

19-
/// The largest value that can be represented by this integer type,
20-
#[doc = concat!("2<sup>", $BITS, "</sup> &minus; 1.")]
20+
/// The largest value that can be represented by this integer type
21+
#[doc = concat!("(2<sup>", $BITS, "</sup> &minus; 1", $bound_condition, ")")]
2122
///
2223
/// # Examples
2324
///

src/bootstrap/builder.rs

+1
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,7 @@ impl<'a> Builder<'a> {
697697
doc::RustcBook,
698698
doc::CargoBook,
699699
doc::Clippy,
700+
doc::ClippyBook,
700701
doc::Miri,
701702
doc::EmbeddedBook,
702703
doc::EditionGuide,

src/bootstrap/doc.rs

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ macro_rules! book {
7474
// and checking against it?).
7575
book!(
7676
CargoBook, "src/tools/cargo/src/doc", "cargo", submodule = "src/tools/cargo";
77+
ClippyBook, "src/tools/clippy/book", "clippy";
7778
EditionGuide, "src/doc/edition-guide", "edition-guide", submodule;
7879
EmbeddedBook, "src/doc/embedded-book", "embedded-book", submodule;
7980
Nomicon, "src/doc/nomicon", "nomicon", submodule;

0 commit comments

Comments
 (0)