Rollup merge of #120423 - RalfJung:indirect-structural-match, r=petrochenkov

update indirect structural match lints to match RFC and to show up for dependencies

This is a large step towards implementing https://github.com/rust-lang/rfcs/pull/3535.
We currently have five lints related to "the structural match situation":
- nontrivial_structural_match
- indirect_structural_match
- pointer_structural_match
- const_patterns_without_partial_eq
- illegal_floating_point_literal_pattern

This PR concerns the first 3 of them. (The 4th already is set up to show for dependencies, and the 5th is removed by https://github.com/rust-lang/rust/pull/116284.) nontrivial_structural_match is being removed as per the RFC; the other two are enabled to show up in dependencies.

Fixes https://github.com/rust-lang/rust/issues/73448 by removing the affected analysis.
This commit is contained in:
Matthias Krüger 2024-02-06 22:45:41 +01:00 committed by GitHub
commit 176c4ba5c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 587 additions and 368 deletions

View file

@ -20,7 +20,7 @@ use std::mem;
use std::ops::{ControlFlow, Deref};
use super::ops::{self, NonConstOp, Status};
use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
use super::resolver::FlowSensitiveAnalysis;
use super::{ConstCx, Qualif};
use crate::const_eval::is_unstable_const_fn;
@ -149,37 +149,10 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
let return_loc = ccx.body.terminator_loc(return_block);
let custom_eq = match ccx.const_kind() {
// We don't care whether a `const fn` returns a value that is not structurally
// matchable. Functions calls are opaque and always use type-based qualification, so
// this value should never be used.
hir::ConstContext::ConstFn => true,
// If we know that all values of the return type are structurally matchable, there's no
// need to run dataflow.
// Opaque types do not participate in const generics or pattern matching, so we can safely count them out.
_ if ccx.body.return_ty().has_opaque_types()
|| !CustomEq::in_any_value_of_ty(ccx, ccx.body.return_ty()) =>
{
false
}
hir::ConstContext::Const { .. } | hir::ConstContext::Static(_) => {
let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx)
.into_engine(ccx.tcx, ccx.body)
.iterate_to_fixpoint()
.into_results_cursor(ccx.body);
cursor.seek_after_primary_effect(return_loc);
cursor.get().contains(RETURN_PLACE)
}
};
ConstQualifs {
needs_drop: self.needs_drop(ccx, RETURN_PLACE, return_loc),
needs_non_const_drop: self.needs_non_const_drop(ccx, RETURN_PLACE, return_loc),
has_mut_interior: self.has_mut_interior(ccx, RETURN_PLACE, return_loc),
custom_eq,
tainted_by_errors,
}
}

View file

@ -10,7 +10,7 @@ use rustc_middle::mir::*;
use rustc_middle::traits::BuiltinImplSource;
use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty};
use rustc_trait_selection::traits::{
self, ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext,
ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext,
};
use super::ConstCx;
@ -24,7 +24,6 @@ pub fn in_any_value_of_ty<'tcx>(
has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty),
needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty),
needs_non_const_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty),
custom_eq: CustomEq::in_any_value_of_ty(cx, ty),
tainted_by_errors,
}
}
@ -213,35 +212,6 @@ impl Qualif for NeedsNonConstDrop {
}
}
/// A constant that cannot be used as part of a pattern in a `match` expression.
pub struct CustomEq;
impl Qualif for CustomEq {
const ANALYSIS_NAME: &'static str = "flow_custom_eq";
fn in_qualifs(qualifs: &ConstQualifs) -> bool {
qualifs.custom_eq
}
fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
// If *any* component of a composite data type does not implement `Structural{Partial,}Eq`,
// we know that at least some values of that type are not structural-match. I say "some"
// because that component may be part of an enum variant (e.g.,
// `Option::<NonStructuralMatchTy>::Some`), in which case some values of this type may be
// structural-match (`Option::None`).
traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty).is_some()
}
fn in_adt_inherently<'tcx>(
cx: &ConstCx<'_, 'tcx>,
def: AdtDef<'tcx>,
args: GenericArgsRef<'tcx>,
) -> bool {
let ty = Ty::new_adt(cx.tcx, def, args);
!ty.is_structural_eq_shallow(cx.tcx)
}
}
// FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return.
/// Returns `true` if this `Rvalue` contains qualif `Q`.