1
Fork 0

Add a because to errors derived from fields

This commit is contained in:
Oli Scherer 2022-11-07 10:48:40 +00:00
parent 9b6f8e500c
commit 5446a52b4b
2 changed files with 33 additions and 34 deletions

View file

@ -2410,7 +2410,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
/// Information about why a type cannot be initialized this way. /// Information about why a type cannot be initialized this way.
struct InitError { struct InitError {
message: String, message: String,
/// Spans from struct fields and similar can be obtained from just the type. /// Spans from struct fields and similar that can be obtained from just the type.
span: Option<Span>, span: Option<Span>,
/// Used to report a trace through adts. /// Used to report a trace through adts.
nested: Option<Box<InitError>>, nested: Option<Box<InitError>>,
@ -2497,7 +2497,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
descr: &str, descr: &str,
init: InitKind, init: InitKind,
) -> Option<InitError> { ) -> Option<InitError> {
let field_err = variant.fields.iter().find_map(|field| { let mut field_err = variant.fields.iter().find_map(|field| {
ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map(|mut err| { ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map(|mut err| {
if !field.did.is_local() { if !field.did.is_local() {
err err
@ -2515,28 +2515,27 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
// Check if this ADT has a constrained layout (like `NonNull` and friends). // Check if this ADT has a constrained layout (like `NonNull` and friends).
if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) { if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) {
match &layout.abi { if let Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) = &layout.abi {
Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) => { let range = scalar.valid_range(cx);
let range = scalar.valid_range(cx); let msg = if !range.contains(0) {
if !range.contains(0) { "must be non-null"
return Some( } else if init == InitKind::Uninit && !scalar.is_always_valid(cx) {
InitError::from(format!("`{}` must be non-null", ty)) // Prefer reporting on the fields over the entire struct for uninit,
.nested(field_err), // as the information bubbles out and it may be unclear why the type can't
); // be null from just its outside signature.
} else if init == InitKind::Uninit && !scalar.is_always_valid(cx) {
// Prefer reporting on the fields over the entire struct for uninit, "must be initialized inside its custom valid range"
// as the information bubbles out and it may be unclear why the type can't } else {
// be null from just its outside signature. return field_err;
return Some( };
InitError::from(format!( if let Some(field_err) = &mut field_err {
"`{}` must be initialized inside its custom valid range", // Most of the time, if the field error is the same as the struct error,
ty, // the struct error only happens because of the field error.
)) if field_err.message.contains(msg) {
.nested(field_err), field_err.message = format!("because {}", field_err.message);
);
} }
} }
_ => {} return Some(InitError::from(format!("`{ty}` {msg}")).nested(field_err));
} }
} }
field_err field_err

View file

@ -35,7 +35,7 @@ LL | let _val: Wrap<&'static T> = mem::zeroed();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
| |
= note: `Wrap<&T>` must be non-null = note: `Wrap<&T>` must be non-null
note: references must be non-null (in this struct field) note: because references must be non-null (in this struct field)
--> $DIR/invalid_value.rs:17:18 --> $DIR/invalid_value.rs:17:18
| |
LL | struct Wrap<T> { wrapped: T } LL | struct Wrap<T> { wrapped: T }
@ -51,7 +51,7 @@ LL | let _val: Wrap<&'static T> = mem::uninitialized();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
| |
= note: `Wrap<&T>` must be non-null = note: `Wrap<&T>` must be non-null
note: references must be non-null (in this struct field) note: because references must be non-null (in this struct field)
--> $DIR/invalid_value.rs:17:18 --> $DIR/invalid_value.rs:17:18
| |
LL | struct Wrap<T> { wrapped: T } LL | struct Wrap<T> { wrapped: T }
@ -163,7 +163,7 @@ LL | let _val: Ref = mem::zeroed();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
| |
= note: `Ref` must be non-null = note: `Ref` must be non-null
note: references must be non-null (in this struct field) note: because references must be non-null (in this struct field)
--> $DIR/invalid_value.rs:14:12 --> $DIR/invalid_value.rs:14:12
| |
LL | struct Ref(&'static i32); LL | struct Ref(&'static i32);
@ -179,7 +179,7 @@ LL | let _val: Ref = mem::uninitialized();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
| |
= note: `Ref` must be non-null = note: `Ref` must be non-null
note: references must be non-null (in this struct field) note: because references must be non-null (in this struct field)
--> $DIR/invalid_value.rs:14:12 --> $DIR/invalid_value.rs:14:12
| |
LL | struct Ref(&'static i32); LL | struct Ref(&'static i32);
@ -217,7 +217,7 @@ LL | let _val: Wrap<fn()> = mem::zeroed();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
| |
= note: `Wrap<fn()>` must be non-null = note: `Wrap<fn()>` must be non-null
note: function pointers must be non-null (in this struct field) note: because function pointers must be non-null (in this struct field)
--> $DIR/invalid_value.rs:17:18 --> $DIR/invalid_value.rs:17:18
| |
LL | struct Wrap<T> { wrapped: T } LL | struct Wrap<T> { wrapped: T }
@ -233,7 +233,7 @@ LL | let _val: Wrap<fn()> = mem::uninitialized();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
| |
= note: `Wrap<fn()>` must be non-null = note: `Wrap<fn()>` must be non-null
note: function pointers must be non-null (in this struct field) note: because function pointers must be non-null (in this struct field)
--> $DIR/invalid_value.rs:17:18 --> $DIR/invalid_value.rs:17:18
| |
LL | struct Wrap<T> { wrapped: T } LL | struct Wrap<T> { wrapped: T }
@ -249,7 +249,7 @@ LL | let _val: WrapEnum<fn()> = mem::zeroed();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
| |
= note: `WrapEnum<fn()>` must be non-null = note: `WrapEnum<fn()>` must be non-null
note: function pointers must be non-null (in this field of the only potentially inhabited enum variant) note: because function pointers must be non-null (in this field of the only potentially inhabited enum variant)
--> $DIR/invalid_value.rs:18:28 --> $DIR/invalid_value.rs:18:28
| |
LL | enum WrapEnum<T> { Wrapped(T) } LL | enum WrapEnum<T> { Wrapped(T) }
@ -265,7 +265,7 @@ LL | let _val: WrapEnum<fn()> = mem::uninitialized();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
| |
= note: `WrapEnum<fn()>` must be non-null = note: `WrapEnum<fn()>` must be non-null
note: function pointers must be non-null (in this field of the only potentially inhabited enum variant) note: because function pointers must be non-null (in this field of the only potentially inhabited enum variant)
--> $DIR/invalid_value.rs:18:28 --> $DIR/invalid_value.rs:18:28
| |
LL | enum WrapEnum<T> { Wrapped(T) } LL | enum WrapEnum<T> { Wrapped(T) }
@ -285,7 +285,7 @@ note: `RefPair` must be non-null (in this struct field)
| |
LL | struct Wrap<T> { wrapped: T } LL | struct Wrap<T> { wrapped: T }
| ^^^^^^^^^^ | ^^^^^^^^^^
note: references must be non-null (in this struct field) note: because references must be non-null (in this struct field)
--> $DIR/invalid_value.rs:15:16 --> $DIR/invalid_value.rs:15:16
| |
LL | struct RefPair((&'static i32, i32)); LL | struct RefPair((&'static i32, i32));
@ -305,7 +305,7 @@ note: `RefPair` must be non-null (in this struct field)
| |
LL | struct Wrap<T> { wrapped: T } LL | struct Wrap<T> { wrapped: T }
| ^^^^^^^^^^ | ^^^^^^^^^^
note: references must be non-null (in this struct field) note: because references must be non-null (in this struct field)
--> $DIR/invalid_value.rs:15:16 --> $DIR/invalid_value.rs:15:16
| |
LL | struct RefPair((&'static i32, i32)); LL | struct RefPair((&'static i32, i32));
@ -441,7 +441,7 @@ LL | let _val: OneFruitNonZero = mem::zeroed();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
| |
= note: `OneFruitNonZero` must be non-null = note: `OneFruitNonZero` must be non-null
note: `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant) note: because `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
--> $DIR/invalid_value.rs:39:12 --> $DIR/invalid_value.rs:39:12
| |
LL | Banana(NonZeroU32), LL | Banana(NonZeroU32),
@ -457,7 +457,7 @@ LL | let _val: OneFruitNonZero = mem::uninitialized();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
| |
= note: `OneFruitNonZero` must be non-null = note: `OneFruitNonZero` must be non-null
note: `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant) note: because `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
--> $DIR/invalid_value.rs:39:12 --> $DIR/invalid_value.rs:39:12
| |
LL | Banana(NonZeroU32), LL | Banana(NonZeroU32),