Skip to content
/ rust Public
forked from rust-lang/rust

Commit e217f94

Browse files
committed
Auto merge of rust-lang#134122 - oli-obk:push-zqnyznxtpnll, r=petrochenkov
Move impl constness into impl trait header This PR is kind of the opposite of the rejected rust-lang#134114 Instead of moving more things into the `constness` query, we want to keep them where their corresponding hir nodes are lowered. So I gave this a spin for impls, which have an obvious place to be (the impl trait header). And surprisingly it's also a perf improvement (likely just slightly better query & cache usage). The issue was that removing anything from the `constness` query makes it just return `NotConst`, which is wrong. So I had to change it to `bug!` out if used wrongly, and only then remove the impl blocks from the `constness` query. I think this change is good in general, because it makes using `constness` more robust (as can be seen by how few sites that had to be changed, so it was almost solely used specifically for the purpose of asking for functions' constness). The main thing where this change was not great was in clippy, which was using the `constness` query as a general DefId -> constness map. I added a `DefKind` filter in front of that. If it becomes a more common pattern we can always move that helper into rustc.
2 parents 4847d6a + 2ffe3b1 commit e217f94

File tree

10 files changed

+99
-44
lines changed

10 files changed

+99
-44
lines changed

compiler/rustc_const_eval/src/const_eval/fn_queries.rs

+17-13
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,29 @@ use rustc_hir::def_id::{DefId, LocalDefId};
44
use rustc_middle::query::Providers;
55
use rustc_middle::ty::TyCtxt;
66

7-
pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
7+
fn parent_impl_constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
88
let parent_id = tcx.local_parent(def_id);
9-
matches!(tcx.def_kind(parent_id), DefKind::Impl { .. })
10-
&& tcx.constness(parent_id) == hir::Constness::Const
9+
if matches!(tcx.def_kind(parent_id), DefKind::Impl { .. })
10+
&& let Some(header) = tcx.impl_trait_header(parent_id)
11+
{
12+
header.constness
13+
} else {
14+
hir::Constness::NotConst
15+
}
1116
}
1217

13-
/// Checks whether an item is considered to be `const`. If it is a constructor, anonymous const,
14-
/// const block, const item or associated const, it is const. If it is a trait impl/function,
18+
/// Checks whether an item is considered to be `const`. If it is a constructor, it is const.
19+
/// If it is an assoc method or function,
1520
/// return if it has a `const` modifier. If it is an intrinsic, report whether said intrinsic
16-
/// has a `rustc_const_{un,}stable` attribute. Otherwise, return `Constness::NotConst`.
21+
/// has a `rustc_const_{un,}stable` attribute. Otherwise, panic.
1722
fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
1823
let node = tcx.hir_node_by_def_id(def_id);
1924

2025
match node {
21-
hir::Node::Ctor(_)
22-
| hir::Node::AnonConst(_)
23-
| hir::Node::ConstBlock(_)
26+
hir::Node::Ctor(hir::VariantData::Tuple(..))
2427
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => {
2528
hir::Constness::Const
2629
}
27-
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness,
2830
hir::Node::ForeignItem(_) => {
2931
// Foreign items cannot be evaluated at compile-time.
3032
hir::Constness::NotConst
@@ -38,10 +40,12 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
3840

3941
// If the function itself is not annotated with `const`, it may still be a `const fn`
4042
// if it resides in a const trait impl.
41-
let is_const = is_parent_const_impl_raw(tcx, def_id);
42-
if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
43+
parent_impl_constness(tcx, def_id)
4344
} else {
44-
hir::Constness::NotConst
45+
tcx.dcx().span_bug(
46+
tcx.def_span(def_id),
47+
format!("should not be requesting the constness of items that can't be const: {node:#?}: {:?}", tcx.def_kind(def_id))
48+
)
4549
}
4650
}
4751
}

compiler/rustc_hir/src/hir.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -4042,9 +4042,7 @@ impl<'hir> Node<'hir> {
40424042
_ => None,
40434043
},
40444044
Node::TraitItem(ti) => match ti.kind {
4045-
TraitItemKind::Fn(ref sig, TraitFn::Provided(_)) => {
4046-
Some(FnKind::Method(ti.ident, sig))
4047-
}
4045+
TraitItemKind::Fn(ref sig, _) => Some(FnKind::Method(ti.ident, sig)),
40484046
_ => None,
40494047
},
40504048
Node::ImplItem(ii) => match ii.kind {

compiler/rustc_hir_analysis/src/collect.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -1611,30 +1611,31 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai
16111611
impl_.of_trait.as_ref().map(|ast_trait_ref| {
16121612
let selfty = tcx.type_of(def_id).instantiate_identity();
16131613

1614-
check_impl_constness(tcx, tcx.is_const_trait_impl(def_id.to_def_id()), ast_trait_ref);
1614+
check_impl_constness(tcx, impl_.constness, ast_trait_ref);
16151615

16161616
let trait_ref = icx.lowerer().lower_impl_trait_ref(ast_trait_ref, selfty);
16171617

16181618
ty::ImplTraitHeader {
16191619
trait_ref: ty::EarlyBinder::bind(trait_ref),
16201620
safety: impl_.safety,
16211621
polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
1622+
constness: impl_.constness,
16221623
}
16231624
})
16241625
}
16251626

16261627
fn check_impl_constness(
16271628
tcx: TyCtxt<'_>,
1628-
is_const: bool,
1629+
constness: hir::Constness,
16291630
hir_trait_ref: &hir::TraitRef<'_>,
1630-
) -> Option<ErrorGuaranteed> {
1631-
if !is_const {
1632-
return None;
1631+
) {
1632+
if let hir::Constness::NotConst = constness {
1633+
return;
16331634
}
16341635

1635-
let trait_def_id = hir_trait_ref.trait_def_id()?;
1636+
let Some(trait_def_id) = hir_trait_ref.trait_def_id() else { return };
16361637
if tcx.is_const_trait(trait_def_id) {
1637-
return None;
1638+
return;
16381639
}
16391640

16401641
let trait_name = tcx.item_name(trait_def_id).to_string();
@@ -1650,14 +1651,14 @@ fn check_impl_constness(
16501651
),
16511652
(false, _) | (_, false) => (None, ""),
16521653
};
1653-
Some(tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
1654+
tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
16541655
trait_ref_span: hir_trait_ref.path.span,
16551656
trait_name,
16561657
local_trait_span,
16571658
suggestion_pre,
16581659
marking: (),
16591660
adding: (),
1660-
}))
1661+
});
16611662
}
16621663

16631664
fn polarity_of_impl(

compiler/rustc_metadata/src/rmeta/encoder.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -1264,12 +1264,7 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool {
12641264

12651265
fn should_encode_constness(def_kind: DefKind) -> bool {
12661266
match def_kind {
1267-
DefKind::Fn
1268-
| DefKind::AssocFn
1269-
| DefKind::Closure
1270-
| DefKind::Impl { of_trait: true }
1271-
| DefKind::Variant
1272-
| DefKind::Ctor(..) => true,
1267+
DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Ctor(_, CtorKind::Fn) => true,
12731268

12741269
DefKind::Struct
12751270
| DefKind::Union
@@ -1281,7 +1276,7 @@ fn should_encode_constness(def_kind: DefKind) -> bool {
12811276
| DefKind::Static { .. }
12821277
| DefKind::TyAlias
12831278
| DefKind::OpaqueTy
1284-
| DefKind::Impl { of_trait: false }
1279+
| DefKind::Impl { .. }
12851280
| DefKind::ForeignTy
12861281
| DefKind::ConstParam
12871282
| DefKind::InlineConst
@@ -1296,6 +1291,8 @@ fn should_encode_constness(def_kind: DefKind) -> bool {
12961291
| DefKind::LifetimeParam
12971292
| DefKind::GlobalAsm
12981293
| DefKind::ExternCrate
1294+
| DefKind::Ctor(_, CtorKind::Const)
1295+
| DefKind::Variant
12991296
| DefKind::SyntheticCoroutineBody => false,
13001297
}
13011298
}

compiler/rustc_middle/src/query/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,10 @@ rustc_queries! {
746746
desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) }
747747
}
748748

749-
/// Returns `true` if this is a const fn / const impl.
749+
/// Returns the constness of function-like things (tuple struct/variant constructors, functions,
750+
/// methods)
751+
///
752+
/// Will ICE if used on things that are always const or never const.
750753
///
751754
/// **Do not call this function manually.** It is only meant to cache the base data for the
752755
/// higher-level functions. Consider using `is_const_fn` or `is_const_trait_impl` instead.

compiler/rustc_middle/src/ty/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3141,7 +3141,7 @@ impl<'tcx> TyCtxt<'tcx> {
31413141
/// Whether the trait impl is marked const. This does not consider stability or feature gates.
31423142
pub fn is_const_trait_impl(self, def_id: DefId) -> bool {
31433143
self.def_kind(def_id) == DefKind::Impl { of_trait: true }
3144-
&& self.constness(def_id) == hir::Constness::Const
3144+
&& self.impl_trait_header(def_id).unwrap().constness == hir::Constness::Const
31453145
}
31463146

31473147
pub fn intrinsic(self, def_id: impl IntoQueryParam<DefId> + Copy) -> Option<ty::IntrinsicDef> {

compiler/rustc_middle/src/ty/mod.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ pub struct ImplTraitHeader<'tcx> {
254254
pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
255255
pub polarity: ImplPolarity,
256256
pub safety: hir::Safety,
257+
pub constness: hir::Constness,
257258
}
258259

259260
#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
@@ -2005,17 +2006,25 @@ impl<'tcx> TyCtxt<'tcx> {
20052006
let def_id: DefId = def_id.into();
20062007
match self.def_kind(def_id) {
20072008
DefKind::Impl { of_trait: true } => {
2008-
self.constness(def_id) == hir::Constness::Const
2009-
&& self.is_const_trait(
2010-
self.trait_id_of_impl(def_id)
2011-
.expect("expected trait for trait implementation"),
2012-
)
2009+
let header = self.impl_trait_header(def_id).unwrap();
2010+
header.constness == hir::Constness::Const
2011+
&& self.is_const_trait(header.trait_ref.skip_binder().def_id)
20132012
}
20142013
DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) => {
20152014
self.constness(def_id) == hir::Constness::Const
20162015
}
20172016
DefKind::Trait => self.is_const_trait(def_id),
2018-
DefKind::AssocTy | DefKind::AssocFn => {
2017+
DefKind::AssocTy => {
2018+
let parent_def_id = self.parent(def_id);
2019+
match self.def_kind(parent_def_id) {
2020+
DefKind::Impl { of_trait: false } => false,
2021+
DefKind::Impl { of_trait: true } | DefKind::Trait => {
2022+
self.is_conditionally_const(parent_def_id)
2023+
}
2024+
_ => bug!("unexpected parent item of associated type: {parent_def_id:?}"),
2025+
}
2026+
}
2027+
DefKind::AssocFn => {
20192028
let parent_def_id = self.parent(def_id);
20202029
match self.def_kind(parent_def_id) {
20212030
DefKind::Impl { of_trait: false } => {
@@ -2024,7 +2033,7 @@ impl<'tcx> TyCtxt<'tcx> {
20242033
DefKind::Impl { of_trait: true } | DefKind::Trait => {
20252034
self.is_conditionally_const(parent_def_id)
20262035
}
2027-
_ => bug!("unexpected parent item of associated item: {parent_def_id:?}"),
2036+
_ => bug!("unexpected parent item of associated fn: {parent_def_id:?}"),
20282037
}
20292038
}
20302039
DefKind::OpaqueTy => match self.opaque_ty_origin(def_id) {

compiler/rustc_middle/src/ty/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ impl<'tcx> TyCtxt<'tcx> {
389389
.delay_as_bug();
390390
}
391391

392-
dtor_candidate = Some((*item_id, self.constness(impl_did)));
392+
dtor_candidate = Some((*item_id, self.impl_trait_header(impl_did).unwrap().constness));
393393
});
394394

395395
let (did, constness) = dtor_candidate?;

compiler/rustc_trait_selection/src/traits/effects.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ fn evaluate_host_effect_from_selection_candiate<'tcx>(
128128
Err(_) => Err(EvaluationFailure::NoSolution),
129129
Ok(Some(source)) => match source {
130130
ImplSource::UserDefined(impl_) => {
131-
if tcx.constness(impl_.impl_def_id) != hir::Constness::Const {
131+
if tcx.impl_trait_header(impl_.impl_def_id).unwrap().constness
132+
!= hir::Constness::Const
133+
{
132134
return Err(EvaluationFailure::NoSolution);
133135
}
134136

src/tools/clippy/clippy_lints/src/manual_float_methods.rs

+42-1
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ use clippy_utils::source::SpanRangeExt;
66
use clippy_utils::{is_from_proc_macro, path_to_local};
77
use rustc_errors::Applicability;
88
use rustc_hir::{BinOpKind, Constness, Expr, ExprKind};
9+
use rustc_hir::def::DefKind;
10+
use rustc_hir::def_id::DefId;
911
use rustc_lint::{LateContext, LateLintPass, Lint, LintContext};
1012
use rustc_middle::lint::in_external_macro;
13+
use rustc_middle::ty::TyCtxt;
1114
use rustc_session::impl_lint_pass;
1215

1316
declare_clippy_lint! {
@@ -94,6 +97,44 @@ impl ManualFloatMethods {
9497
}
9598
}
9699

100+
fn is_not_const(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
101+
match tcx.def_kind(def_id) {
102+
DefKind::Mod
103+
| DefKind::Struct
104+
| DefKind::Union
105+
| DefKind::Enum
106+
| DefKind::Variant
107+
| DefKind::Trait
108+
| DefKind::TyAlias
109+
| DefKind::ForeignTy
110+
| DefKind::TraitAlias
111+
| DefKind::AssocTy
112+
| DefKind::Macro(..)
113+
| DefKind::Field
114+
| DefKind::LifetimeParam
115+
| DefKind::ExternCrate
116+
| DefKind::Use
117+
| DefKind::ForeignMod
118+
| DefKind::GlobalAsm
119+
| DefKind::Impl { .. }
120+
| DefKind::OpaqueTy
121+
| DefKind::SyntheticCoroutineBody
122+
| DefKind::TyParam => true,
123+
124+
DefKind::AnonConst
125+
| DefKind::InlineConst
126+
| DefKind::Const
127+
| DefKind::ConstParam
128+
| DefKind::Static { .. }
129+
| DefKind::Ctor(..)
130+
| DefKind::AssocConst => false,
131+
132+
DefKind::Fn
133+
| DefKind::AssocFn
134+
| DefKind::Closure => tcx.constness(def_id) == Constness::NotConst,
135+
}
136+
}
137+
97138
impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
98139
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
99140
if let ExprKind::Binary(kind, lhs, rhs) = expr.kind
@@ -105,7 +146,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
105146
&& exprs.iter_mut().partition_in_place(|i| path_to_local(i).is_some()) == 2
106147
&& !in_external_macro(cx.sess(), expr.span)
107148
&& (
108-
matches!(cx.tcx.constness(cx.tcx.hir().enclosing_body_owner(expr.hir_id)), Constness::NotConst)
149+
is_not_const(cx.tcx, cx.tcx.hir().enclosing_body_owner(expr.hir_id).into())
109150
|| self.msrv.meets(msrvs::CONST_FLOAT_CLASSIFY)
110151
)
111152
&& let [first, second, const_1, const_2] = exprs

0 commit comments

Comments
 (0)