Skip to content

Commit 5446a52

Browse files
committed
Add a because to errors derived from fields
1 parent 9b6f8e5 commit 5446a52

File tree

2 files changed

+33
-34
lines changed

2 files changed

+33
-34
lines changed

compiler/rustc_lint/src/builtin.rs

+21-22
Original file line numberDiff line numberDiff line change
@@ -2410,7 +2410,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
24102410
/// Information about why a type cannot be initialized this way.
24112411
struct InitError {
24122412
message: String,
2413-
/// Spans from struct fields and similar can be obtained from just the type.
2413+
/// Spans from struct fields and similar that can be obtained from just the type.
24142414
span: Option<Span>,
24152415
/// Used to report a trace through adts.
24162416
nested: Option<Box<InitError>>,
@@ -2497,7 +2497,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
24972497
descr: &str,
24982498
init: InitKind,
24992499
) -> Option<InitError> {
2500-
let field_err = variant.fields.iter().find_map(|field| {
2500+
let mut field_err = variant.fields.iter().find_map(|field| {
25012501
ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map(|mut err| {
25022502
if !field.did.is_local() {
25032503
err
@@ -2515,28 +2515,27 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
25152515

25162516
// Check if this ADT has a constrained layout (like `NonNull` and friends).
25172517
if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) {
2518-
match &layout.abi {
2519-
Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) => {
2520-
let range = scalar.valid_range(cx);
2521-
if !range.contains(0) {
2522-
return Some(
2523-
InitError::from(format!("`{}` must be non-null", ty))
2524-
.nested(field_err),
2525-
);
2526-
} else if init == InitKind::Uninit && !scalar.is_always_valid(cx) {
2527-
// Prefer reporting on the fields over the entire struct for uninit,
2528-
// as the information bubbles out and it may be unclear why the type can't
2529-
// be null from just its outside signature.
2530-
return Some(
2531-
InitError::from(format!(
2532-
"`{}` must be initialized inside its custom valid range",
2533-
ty,
2534-
))
2535-
.nested(field_err),
2536-
);
2518+
if let Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) = &layout.abi {
2519+
let range = scalar.valid_range(cx);
2520+
let msg = if !range.contains(0) {
2521+
"must be non-null"
2522+
} else if init == InitKind::Uninit && !scalar.is_always_valid(cx) {
2523+
// Prefer reporting on the fields over the entire struct for uninit,
2524+
// as the information bubbles out and it may be unclear why the type can't
2525+
// be null from just its outside signature.
2526+
2527+
"must be initialized inside its custom valid range"
2528+
} else {
2529+
return field_err;
2530+
};
2531+
if let Some(field_err) = &mut field_err {
2532+
// Most of the time, if the field error is the same as the struct error,
2533+
// the struct error only happens because of the field error.
2534+
if field_err.message.contains(msg) {
2535+
field_err.message = format!("because {}", field_err.message);
25372536
}
25382537
}
2539-
_ => {}
2538+
return Some(InitError::from(format!("`{ty}` {msg}")).nested(field_err));
25402539
}
25412540
}
25422541
field_err

src/test/ui/lint/invalid_value.stderr

+12-12
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ LL | let _val: Wrap<&'static T> = mem::zeroed();
3535
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
3636
|
3737
= note: `Wrap<&T>` must be non-null
38-
note: references must be non-null (in this struct field)
38+
note: because references must be non-null (in this struct field)
3939
--> $DIR/invalid_value.rs:17:18
4040
|
4141
LL | struct Wrap<T> { wrapped: T }
@@ -51,7 +51,7 @@ LL | let _val: Wrap<&'static T> = mem::uninitialized();
5151
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
5252
|
5353
= note: `Wrap<&T>` must be non-null
54-
note: references must be non-null (in this struct field)
54+
note: because references must be non-null (in this struct field)
5555
--> $DIR/invalid_value.rs:17:18
5656
|
5757
LL | struct Wrap<T> { wrapped: T }
@@ -163,7 +163,7 @@ LL | let _val: Ref = mem::zeroed();
163163
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
164164
|
165165
= note: `Ref` must be non-null
166-
note: references must be non-null (in this struct field)
166+
note: because references must be non-null (in this struct field)
167167
--> $DIR/invalid_value.rs:14:12
168168
|
169169
LL | struct Ref(&'static i32);
@@ -179,7 +179,7 @@ LL | let _val: Ref = mem::uninitialized();
179179
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
180180
|
181181
= note: `Ref` must be non-null
182-
note: references must be non-null (in this struct field)
182+
note: because references must be non-null (in this struct field)
183183
--> $DIR/invalid_value.rs:14:12
184184
|
185185
LL | struct Ref(&'static i32);
@@ -217,7 +217,7 @@ LL | let _val: Wrap<fn()> = mem::zeroed();
217217
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
218218
|
219219
= note: `Wrap<fn()>` must be non-null
220-
note: function pointers must be non-null (in this struct field)
220+
note: because function pointers must be non-null (in this struct field)
221221
--> $DIR/invalid_value.rs:17:18
222222
|
223223
LL | struct Wrap<T> { wrapped: T }
@@ -233,7 +233,7 @@ LL | let _val: Wrap<fn()> = mem::uninitialized();
233233
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
234234
|
235235
= note: `Wrap<fn()>` must be non-null
236-
note: function pointers must be non-null (in this struct field)
236+
note: because function pointers must be non-null (in this struct field)
237237
--> $DIR/invalid_value.rs:17:18
238238
|
239239
LL | struct Wrap<T> { wrapped: T }
@@ -249,7 +249,7 @@ LL | let _val: WrapEnum<fn()> = mem::zeroed();
249249
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
250250
|
251251
= note: `WrapEnum<fn()>` must be non-null
252-
note: function pointers must be non-null (in this field of the only potentially inhabited enum variant)
252+
note: because function pointers must be non-null (in this field of the only potentially inhabited enum variant)
253253
--> $DIR/invalid_value.rs:18:28
254254
|
255255
LL | enum WrapEnum<T> { Wrapped(T) }
@@ -265,7 +265,7 @@ LL | let _val: WrapEnum<fn()> = mem::uninitialized();
265265
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
266266
|
267267
= note: `WrapEnum<fn()>` must be non-null
268-
note: function pointers must be non-null (in this field of the only potentially inhabited enum variant)
268+
note: because function pointers must be non-null (in this field of the only potentially inhabited enum variant)
269269
--> $DIR/invalid_value.rs:18:28
270270
|
271271
LL | enum WrapEnum<T> { Wrapped(T) }
@@ -285,7 +285,7 @@ note: `RefPair` must be non-null (in this struct field)
285285
|
286286
LL | struct Wrap<T> { wrapped: T }
287287
| ^^^^^^^^^^
288-
note: references must be non-null (in this struct field)
288+
note: because references must be non-null (in this struct field)
289289
--> $DIR/invalid_value.rs:15:16
290290
|
291291
LL | struct RefPair((&'static i32, i32));
@@ -305,7 +305,7 @@ note: `RefPair` must be non-null (in this struct field)
305305
|
306306
LL | struct Wrap<T> { wrapped: T }
307307
| ^^^^^^^^^^
308-
note: references must be non-null (in this struct field)
308+
note: because references must be non-null (in this struct field)
309309
--> $DIR/invalid_value.rs:15:16
310310
|
311311
LL | struct RefPair((&'static i32, i32));
@@ -441,7 +441,7 @@ LL | let _val: OneFruitNonZero = mem::zeroed();
441441
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
442442
|
443443
= note: `OneFruitNonZero` must be non-null
444-
note: `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
444+
note: because `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
445445
--> $DIR/invalid_value.rs:39:12
446446
|
447447
LL | Banana(NonZeroU32),
@@ -457,7 +457,7 @@ LL | let _val: OneFruitNonZero = mem::uninitialized();
457457
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
458458
|
459459
= note: `OneFruitNonZero` must be non-null
460-
note: `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
460+
note: because `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
461461
--> $DIR/invalid_value.rs:39:12
462462
|
463463
LL | Banana(NonZeroU32),

0 commit comments

Comments
 (0)