Skip to content

Commit

Permalink
Rollup merge of #69642 - ecstatic-morse:issue-69615, r=oli-obk
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Dylan-DPC authored Apr 17, 2020
2 parents 8d67f57 + eb74096 commit a12d42b
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 24 deletions.
27 changes: 10 additions & 17 deletions src/librustc_mir/const_eval/fn_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,16 @@ fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {

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

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

/// Const evaluability whitelist is here to check evaluability at the
/// top level beforehand.
fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option<bool> {
if tcx.is_closure(def_id) {
return None;
}

match tcx.fn_sig(def_id).abi() {
Abi::RustIntrinsic | Abi::PlatformIntrinsic => {
Some(tcx.lookup_const_stability(def_id).is_some())
}
_ => None,
}
}

/// Checks whether the given item is an `impl` that has a `const` modifier.
fn is_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
Expand Down
14 changes: 7 additions & 7 deletions src/librustc_passes/check_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,16 @@ enum ConstKind {
}

impl ConstKind {
fn for_body(body: &hir::Body<'_>, hir_map: Map<'_>) -> Option<Self> {
let is_const_fn = |id| hir_map.fn_sig_by_hir_id(id).unwrap().header.is_const();

let owner = hir_map.body_owner(body.id());
let const_kind = match hir_map.body_owner_kind(owner) {
fn for_body(body: &hir::Body<'_>, tcx: TyCtxt<'_>) -> Option<Self> {
let owner = tcx.hir().body_owner(body.id());
let const_kind = match tcx.hir().body_owner_kind(owner) {
hir::BodyOwnerKind::Const => Self::Const,
hir::BodyOwnerKind::Static(Mutability::Mut) => Self::StaticMut,
hir::BodyOwnerKind::Static(Mutability::Not) => Self::Static,

hir::BodyOwnerKind::Fn if is_const_fn(owner) => Self::ConstFn,
hir::BodyOwnerKind::Fn if tcx.is_const_fn_raw(tcx.hir().local_def_id(owner)) => {
Self::ConstFn
}
hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => return None,
};

Expand Down Expand Up @@ -211,7 +211,7 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
}

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

Expand Down
16 changes: 16 additions & 0 deletions src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Regression test for #69615.

#![feature(const_trait_impl, const_fn)]
#![allow(incomplete_features)]

pub trait MyTrait {
fn method(&self);
}

impl const MyTrait for () {
fn method(&self) {
match *self {} //~ ERROR `match` is not allowed in a `const fn`
}
}

fn main() {}
12 changes: 12 additions & 0 deletions src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0658]: `match` is not allowed in a `const fn`
--> $DIR/hir-const-check.rs:12:9
|
LL | match *self {}
| ^^^^^^^^^^^^^^
|
= note: see issue #49146 <https://github.com/rust-lang/rust/issues/49146> for more information
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error: aborting due to previous error

For more information about this error, try `rustc --explain E0658`.

0 comments on commit a12d42b

Please sign in to comment.