diff options
| author | Ralf Jung <post@ralfj.de> | 2022-03-27 13:10:34 -0400 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2022-04-01 09:59:11 -0400 |
| commit | af24588a06b9fbed47495c787c20e930398bbb86 (patch) | |
| tree | afa6a6d48ac4b0f0b7374ad7c979f2584171d949 /compiler/rustc_lint/src | |
| parent | df20355fa9fa5e9fb89be4e4bfee8a643bb7a23e (diff) | |
| download | rust-af24588a06b9fbed47495c787c20e930398bbb86.tar.gz rust-af24588a06b9fbed47495c787c20e930398bbb86.zip | |
invalid_value lint: detect invalid initialization of arrays
Diffstat (limited to 'compiler/rustc_lint/src')
| -rw-r--r-- | compiler/rustc_lint/src/builtin.rs | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 50a3df21a3b..d43c661dda6 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2548,7 +2548,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { /// Return `Some` only if we are sure this type does *not* /// allow zero initialization. fn ty_find_init_error<'tcx>( - tcx: TyCtxt<'tcx>, + cx: &LateContext<'tcx>, ty: Ty<'tcx>, init: InitKind, ) -> Option<InitError> { @@ -2575,7 +2575,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { Adt(adt_def, substs) if !adt_def.is_union() => { // First check if this ADT has a layout attribute (like `NonNull` and friends). use std::ops::Bound; - match tcx.layout_scalar_valid_range(adt_def.did()) { + match cx.tcx.layout_scalar_valid_range(adt_def.did()) { // We exploit here that `layout_scalar_valid_range` will never // return `Bound::Excluded`. (And we have tests checking that we // handle the attribute correctly.) @@ -2603,12 +2603,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { // Proceed recursively, check all fields. let variant = &adt_def.variant(VariantIdx::from_u32(0)); variant.fields.iter().find_map(|field| { - ty_find_init_error(tcx, field.ty(tcx, substs), init).map( + ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map( |(mut msg, span)| { if span.is_none() { // Point to this field, should be helpful for figuring // out where the source of the error is. - let span = tcx.def_span(field.did); + let span = cx.tcx.def_span(field.did); write!( &mut msg, " (in this {} field)", @@ -2627,7 +2627,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { // Multi-variant enum. _ => { if init == InitKind::Uninit && is_multi_variant(*adt_def) { - let span = tcx.def_span(adt_def.did()); + let span = cx.tcx.def_span(adt_def.did()); Some(( "enums have to be initialized to a variant".to_string(), Some(span), @@ -2642,7 +2642,16 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { } Tuple(..) => { // Proceed recursively, check all fields. - ty.tuple_fields().iter().find_map(|field| ty_find_init_error(tcx, field, init)) + ty.tuple_fields().iter().find_map(|field| ty_find_init_error(cx, field, init)) + } + Array(ty, len) => { + if matches!(len.try_eval_usize(cx.tcx, cx.param_env), Some(v) if v > 0) { + // Array length known at array non-empty -- recurse. + ty_find_init_error(cx, *ty, init) + } else { + // Empty array or size unknown. + None + } } // Conservative fallback. _ => None, @@ -2655,7 +2664,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { // We are extremely conservative with what we warn about. let conjured_ty = cx.typeck_results().expr_ty(expr); if let Some((msg, span)) = - with_no_trimmed_paths!(ty_find_init_error(cx.tcx, conjured_ty, init)) + with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init)) { cx.struct_span_lint(INVALID_VALUE, expr.span, |lint| { let mut err = lint.build(&format!( |
