Add a because
to errors derived from fields
This commit is contained in:
parent
9b6f8e500c
commit
5446a52b4b
2 changed files with 33 additions and 34 deletions
|
@ -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
|
||||||
|
|
|
@ -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),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue