Skip to content

Commit a12d42b

Browse files
authored
Rollup merge of #69642 - ecstatic-morse:issue-69615, r=oli-obk
Use query to determine whether function needs const checking Resolves #69615. The HIR const-checker was checking the `constness` of a function's `fn_sig` to determine whether a function needed const-checking. Now that const trait impls are a thing, this is no longer enough. All code should use the `is_const_fn_raw` query instead, which takes the constness of the impl block into account. r? @oli-obk
2 parents 8d67f57 + eb74096 commit a12d42b

File tree

4 files changed

+45
-24
lines changed

4 files changed

+45
-24
lines changed

src/librustc_mir/const_eval/fn_queries.rs

+10-17
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,16 @@ fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
9595

9696
let node = tcx.hir().get(hir_id);
9797

98-
if let Some(whitelisted) = is_const_intrinsic(tcx, def_id) {
99-
whitelisted
98+
if let hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) =
99+
node
100+
{
101+
// Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other
102+
// foreign items cannot be evaluated at compile-time.
103+
if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = tcx.hir().get_foreign_abi(hir_id) {
104+
tcx.lookup_const_stability(def_id).is_some()
105+
} else {
106+
false
107+
}
100108
} else if let Some(fn_like) = FnLikeNode::from_node(node) {
101109
if fn_like.constness() == hir::Constness::Const {
102110
return true;
@@ -112,21 +120,6 @@ fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
112120
}
113121
}
114122

115-
/// Const evaluability whitelist is here to check evaluability at the
116-
/// top level beforehand.
117-
fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option<bool> {
118-
if tcx.is_closure(def_id) {
119-
return None;
120-
}
121-
122-
match tcx.fn_sig(def_id).abi() {
123-
Abi::RustIntrinsic | Abi::PlatformIntrinsic => {
124-
Some(tcx.lookup_const_stability(def_id).is_some())
125-
}
126-
_ => None,
127-
}
128-
}
129-
130123
/// Checks whether the given item is an `impl` that has a `const` modifier.
131124
fn is_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
132125
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);

src/librustc_passes/check_const.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,16 @@ enum ConstKind {
7474
}
7575

7676
impl ConstKind {
77-
fn for_body(body: &hir::Body<'_>, hir_map: Map<'_>) -> Option<Self> {
78-
let is_const_fn = |id| hir_map.fn_sig_by_hir_id(id).unwrap().header.is_const();
79-
80-
let owner = hir_map.body_owner(body.id());
81-
let const_kind = match hir_map.body_owner_kind(owner) {
77+
fn for_body(body: &hir::Body<'_>, tcx: TyCtxt<'_>) -> Option<Self> {
78+
let owner = tcx.hir().body_owner(body.id());
79+
let const_kind = match tcx.hir().body_owner_kind(owner) {
8280
hir::BodyOwnerKind::Const => Self::Const,
8381
hir::BodyOwnerKind::Static(Mutability::Mut) => Self::StaticMut,
8482
hir::BodyOwnerKind::Static(Mutability::Not) => Self::Static,
8583

86-
hir::BodyOwnerKind::Fn if is_const_fn(owner) => Self::ConstFn,
84+
hir::BodyOwnerKind::Fn if tcx.is_const_fn_raw(tcx.hir().local_def_id(owner)) => {
85+
Self::ConstFn
86+
}
8787
hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => return None,
8888
};
8989

@@ -211,7 +211,7 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
211211
}
212212

213213
fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
214-
let kind = ConstKind::for_body(body, self.tcx.hir());
214+
let kind = ConstKind::for_body(body, self.tcx);
215215
self.recurse_into(kind, |this| intravisit::walk_body(this, body));
216216
}
217217

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Regression test for #69615.
2+
3+
#![feature(const_trait_impl, const_fn)]
4+
#![allow(incomplete_features)]
5+
6+
pub trait MyTrait {
7+
fn method(&self);
8+
}
9+
10+
impl const MyTrait for () {
11+
fn method(&self) {
12+
match *self {} //~ ERROR `match` is not allowed in a `const fn`
13+
}
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0658]: `match` is not allowed in a `const fn`
2+
--> $DIR/hir-const-check.rs:12:9
3+
|
4+
LL | match *self {}
5+
| ^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #49146 <https://github.com/rust-lang/rust/issues/49146> for more information
8+
= help: add `#![feature(const_if_match)]` to the crate attributes to enable
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)