1
Fork 0

Require the constness query to only be invoked on things that can have constness

This commit is contained in:
Oli Scherer 2024-12-10 10:12:36 +00:00
parent 3d0bf68625
commit c0e0d8f874
6 changed files with 66 additions and 13 deletions

View file

@ -18,9 +18,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
let node = tcx.hir_node_by_def_id(def_id); let node = tcx.hir_node_by_def_id(def_id);
match node { match node {
hir::Node::Ctor(_) hir::Node::Ctor(hir::VariantData::Tuple(..))
| hir::Node::AnonConst(_)
| hir::Node::ConstBlock(_)
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => { | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => {
hir::Constness::Const hir::Constness::Const
} }
@ -41,7 +39,10 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
let is_const = is_parent_const_impl_raw(tcx, def_id); let is_const = is_parent_const_impl_raw(tcx, def_id);
if is_const { hir::Constness::Const } else { hir::Constness::NotConst } if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
} else { } else {
hir::Constness::NotConst tcx.dcx().span_bug(
tcx.def_span(def_id),
format!("should not be requesting the constness of items that can't be const: {node:#?}: {:?}", tcx.def_kind(def_id))
)
} }
} }
} }

View file

@ -4044,9 +4044,7 @@ impl<'hir> Node<'hir> {
_ => None, _ => None,
}, },
Node::TraitItem(ti) => match ti.kind { Node::TraitItem(ti) => match ti.kind {
TraitItemKind::Fn(ref sig, TraitFn::Provided(_)) => { TraitItemKind::Fn(ref sig, _) => Some(FnKind::Method(ti.ident, sig)),
Some(FnKind::Method(ti.ident, sig))
}
_ => None, _ => None,
}, },
Node::ImplItem(ii) => match ii.kind { Node::ImplItem(ii) => match ii.kind {

View file

@ -1268,8 +1268,7 @@ fn should_encode_constness(def_kind: DefKind) -> bool {
| DefKind::AssocFn | DefKind::AssocFn
| DefKind::Closure | DefKind::Closure
| DefKind::Impl { of_trait: true } | DefKind::Impl { of_trait: true }
| DefKind::Variant | DefKind::Ctor(_, CtorKind::Fn) => true,
| DefKind::Ctor(..) => true,
DefKind::Struct DefKind::Struct
| DefKind::Union | DefKind::Union
@ -1296,6 +1295,8 @@ fn should_encode_constness(def_kind: DefKind) -> bool {
| DefKind::LifetimeParam | DefKind::LifetimeParam
| DefKind::GlobalAsm | DefKind::GlobalAsm
| DefKind::ExternCrate | DefKind::ExternCrate
| DefKind::Ctor(_, CtorKind::Const)
| DefKind::Variant
| DefKind::SyntheticCoroutineBody => false, | DefKind::SyntheticCoroutineBody => false,
} }
} }

View file

@ -746,7 +746,9 @@ rustc_queries! {
desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) } desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) }
} }
/// Returns `true` if this is a const fn / const impl. /// Returns the constness of functions and impls.
///
/// Will ICE if used on things that are always const or never const.
/// ///
/// **Do not call this function manually.** It is only meant to cache the base data for the /// **Do not call this function manually.** It is only meant to cache the base data for the
/// higher-level functions. Consider using `is_const_fn` or `is_const_trait_impl` instead. /// higher-level functions. Consider using `is_const_fn` or `is_const_trait_impl` instead.

View file

@ -2014,7 +2014,17 @@ impl<'tcx> TyCtxt<'tcx> {
self.constness(def_id) == hir::Constness::Const self.constness(def_id) == hir::Constness::Const
} }
DefKind::Trait => self.is_const_trait(def_id), DefKind::Trait => self.is_const_trait(def_id),
DefKind::AssocTy | DefKind::AssocFn => { DefKind::AssocTy => {
let parent_def_id = self.parent(def_id);
match self.def_kind(parent_def_id) {
DefKind::Impl { of_trait: false } => false,
DefKind::Impl { of_trait: true } | DefKind::Trait => {
self.is_conditionally_const(parent_def_id)
}
_ => bug!("unexpected parent item of associated type: {parent_def_id:?}"),
}
}
DefKind::AssocFn => {
let parent_def_id = self.parent(def_id); let parent_def_id = self.parent(def_id);
match self.def_kind(parent_def_id) { match self.def_kind(parent_def_id) {
DefKind::Impl { of_trait: false } => { DefKind::Impl { of_trait: false } => {
@ -2023,7 +2033,7 @@ impl<'tcx> TyCtxt<'tcx> {
DefKind::Impl { of_trait: true } | DefKind::Trait => { DefKind::Impl { of_trait: true } | DefKind::Trait => {
self.is_conditionally_const(parent_def_id) self.is_conditionally_const(parent_def_id)
} }
_ => bug!("unexpected parent item of associated item: {parent_def_id:?}"), _ => bug!("unexpected parent item of associated fn: {parent_def_id:?}"),
} }
} }
DefKind::OpaqueTy => match self.opaque_ty_origin(def_id) { DefKind::OpaqueTy => match self.opaque_ty_origin(def_id) {

View file

@ -6,8 +6,11 @@ use clippy_utils::source::SpanRangeExt;
use clippy_utils::{is_from_proc_macro, path_to_local}; use clippy_utils::{is_from_proc_macro, path_to_local};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Constness, Expr, ExprKind}; use rustc_hir::{BinOpKind, Constness, Expr, ExprKind};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_lint::{LateContext, LateLintPass, Lint, LintContext}; use rustc_lint::{LateContext, LateLintPass, Lint, LintContext};
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::TyCtxt;
use rustc_session::impl_lint_pass; use rustc_session::impl_lint_pass;
declare_clippy_lint! { declare_clippy_lint! {
@ -94,6 +97,44 @@ impl ManualFloatMethods {
} }
} }
fn is_not_const(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
match tcx.def_kind(def_id) {
DefKind::Mod
| DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::Variant
| DefKind::Trait
| DefKind::TyAlias
| DefKind::ForeignTy
| DefKind::TraitAlias
| DefKind::AssocTy
| DefKind::Macro(..)
| DefKind::Field
| DefKind::LifetimeParam
| DefKind::ExternCrate
| DefKind::Use
| DefKind::ForeignMod
| DefKind::GlobalAsm
| DefKind::Impl { .. }
| DefKind::OpaqueTy
| DefKind::SyntheticCoroutineBody
| DefKind::TyParam => true,
DefKind::AnonConst
| DefKind::InlineConst
| DefKind::Const
| DefKind::ConstParam
| DefKind::Static { .. }
| DefKind::Ctor(..)
| DefKind::AssocConst => false,
DefKind::Fn
| DefKind::AssocFn
| DefKind::Closure => tcx.constness(def_id) == Constness::NotConst,
}
}
impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if let ExprKind::Binary(kind, lhs, rhs) = expr.kind if let ExprKind::Binary(kind, lhs, rhs) = expr.kind
@ -105,7 +146,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
&& exprs.iter_mut().partition_in_place(|i| path_to_local(i).is_some()) == 2 && exprs.iter_mut().partition_in_place(|i| path_to_local(i).is_some()) == 2
&& !in_external_macro(cx.sess(), expr.span) && !in_external_macro(cx.sess(), expr.span)
&& ( && (
matches!(cx.tcx.constness(cx.tcx.hir().enclosing_body_owner(expr.hir_id)), Constness::NotConst) is_not_const(cx.tcx, cx.tcx.hir().enclosing_body_owner(expr.hir_id).into())
|| self.msrv.meets(msrvs::CONST_FLOAT_CLASSIFY) || self.msrv.meets(msrvs::CONST_FLOAT_CLASSIFY)
) )
&& let [first, second, const_1, const_2] = exprs && let [first, second, const_1, const_2] = exprs