Skip to content

Commit f3be931

Browse files
committed
Rollup merge of rust-lang#56337 - phansch:fix_const_ice, r=oli-obk
Fix const_fn ICE with non-const function pointer Fixes rust-lang#56164
2 parents ecfe721 + 247ab49 commit f3be931

File tree

3 files changed

+165
-122
lines changed

3 files changed

+165
-122
lines changed

src/librustc_mir/transform/qualify_consts.rs

+137-122
Original file line numberDiff line numberDiff line change
@@ -895,145 +895,160 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
895895
let mut is_shuffle = false;
896896
let mut is_const_fn = false;
897897
let mut is_promotable_const_fn = false;
898-
if let ty::FnDef(def_id, _) = fn_ty.sty {
899-
callee_def_id = Some(def_id);
900-
match self.tcx.fn_sig(def_id).abi() {
901-
Abi::RustIntrinsic |
902-
Abi::PlatformIntrinsic => {
903-
assert!(!self.tcx.is_const_fn(def_id));
904-
match &self.tcx.item_name(def_id).as_str()[..] {
905-
| "size_of"
906-
| "min_align_of"
907-
| "needs_drop"
908-
| "type_id"
909-
| "bswap"
910-
| "bitreverse"
911-
| "ctpop"
912-
| "cttz"
913-
| "cttz_nonzero"
914-
| "ctlz"
915-
| "ctlz_nonzero"
916-
| "overflowing_add"
917-
| "overflowing_sub"
918-
| "overflowing_mul"
919-
| "unchecked_shl"
920-
| "unchecked_shr"
921-
| "rotate_left"
922-
| "rotate_right"
923-
| "add_with_overflow"
924-
| "sub_with_overflow"
925-
| "mul_with_overflow"
926-
// no need to check feature gates, intrinsics are only callable from the
927-
// libstd or with forever unstable feature gates
928-
=> is_const_fn = true,
929-
// special intrinsic that can be called diretly without an intrinsic
930-
// feature gate needs a language feature gate
931-
"transmute" => {
932-
// never promote transmute calls
933-
if self.mode != Mode::Fn {
934-
is_const_fn = true;
935-
// const eval transmute calls only with the feature gate
936-
if !self.tcx.features().const_transmute {
937-
emit_feature_err(
938-
&self.tcx.sess.parse_sess, "const_transmute",
939-
self.span, GateIssue::Language,
940-
&format!("The use of std::mem::transmute() \
941-
is gated in {}s", self.mode));
898+
match fn_ty.sty {
899+
ty::FnDef(def_id, _) => {
900+
callee_def_id = Some(def_id);
901+
match self.tcx.fn_sig(def_id).abi() {
902+
Abi::RustIntrinsic |
903+
Abi::PlatformIntrinsic => {
904+
assert!(!self.tcx.is_const_fn(def_id));
905+
match &self.tcx.item_name(def_id).as_str()[..] {
906+
| "size_of"
907+
| "min_align_of"
908+
| "needs_drop"
909+
| "type_id"
910+
| "bswap"
911+
| "bitreverse"
912+
| "ctpop"
913+
| "cttz"
914+
| "cttz_nonzero"
915+
| "ctlz"
916+
| "ctlz_nonzero"
917+
| "overflowing_add"
918+
| "overflowing_sub"
919+
| "overflowing_mul"
920+
| "unchecked_shl"
921+
| "unchecked_shr"
922+
| "rotate_left"
923+
| "rotate_right"
924+
| "add_with_overflow"
925+
| "sub_with_overflow"
926+
| "mul_with_overflow"
927+
// no need to check feature gates, intrinsics are only callable
928+
// from the libstd or with forever unstable feature gates
929+
=> is_const_fn = true,
930+
// special intrinsic that can be called diretly without an intrinsic
931+
// feature gate needs a language feature gate
932+
"transmute" => {
933+
// never promote transmute calls
934+
if self.mode != Mode::Fn {
935+
is_const_fn = true;
936+
// const eval transmute calls only with the feature gate
937+
if !self.tcx.features().const_transmute {
938+
emit_feature_err(
939+
&self.tcx.sess.parse_sess, "const_transmute",
940+
self.span, GateIssue::Language,
941+
&format!("The use of std::mem::transmute() \
942+
is gated in {}s", self.mode));
943+
}
942944
}
943945
}
944-
}
945946

946-
name if name.starts_with("simd_shuffle") => {
947-
is_shuffle = true;
948-
}
947+
name if name.starts_with("simd_shuffle") => {
948+
is_shuffle = true;
949+
}
949950

950-
_ => {}
951-
}
952-
}
953-
_ => {
954-
// in normal functions we only care about promotion
955-
if self.mode == Mode::Fn {
956-
// never promote const fn calls of
957-
// functions without #[rustc_promotable]
958-
if self.tcx.is_promotable_const_fn(def_id) {
959-
is_const_fn = true;
960-
is_promotable_const_fn = true;
961-
} else if self.tcx.is_const_fn(def_id) {
962-
is_const_fn = true;
951+
_ => {}
963952
}
964-
} else {
965-
// stable const fn or unstable const fns with their feature gate
966-
// active
967-
if self.tcx.is_const_fn(def_id) {
968-
is_const_fn = true;
969-
} else if self.is_const_panic_fn(def_id) {
970-
// check the const_panic feature gate
971-
// FIXME: cannot allow this inside `allow_internal_unstable` because
972-
// that would make `panic!` insta stable in constants, since the
973-
// macro is marked with the attr
974-
if self.tcx.features().const_panic {
953+
}
954+
_ => {
955+
// in normal functions we only care about promotion
956+
if self.mode == Mode::Fn {
957+
// never promote const fn calls of
958+
// functions without #[rustc_promotable]
959+
if self.tcx.is_promotable_const_fn(def_id) {
975960
is_const_fn = true;
976-
} else {
977-
// don't allow panics in constants without the feature gate
978-
emit_feature_err(
979-
&self.tcx.sess.parse_sess,
980-
"const_panic",
981-
self.span,
982-
GateIssue::Language,
983-
&format!("panicking in {}s is unstable", self.mode),
984-
);
985-
}
986-
} else if let Some(feature) = self.tcx.is_unstable_const_fn(def_id) {
987-
// check `#[unstable]` const fns or `#[rustc_const_unstable]`
988-
// functions without the feature gate active in this crate to report
989-
// a better error message than the one below
990-
if self.span.allows_unstable() {
991-
// `allow_internal_unstable` can make such calls stable
961+
is_promotable_const_fn = true;
962+
} else if self.tcx.is_const_fn(def_id) {
992963
is_const_fn = true;
993-
} else {
994-
let mut err = self.tcx.sess.struct_span_err(self.span,
995-
&format!("`{}` is not yet stable as a const fn",
996-
self.tcx.item_path_str(def_id)));
997-
help!(&mut err,
998-
"in Nightly builds, add `#![feature({})]` \
999-
to the crate attributes to enable",
1000-
feature);
1001-
err.emit();
1002964
}
1003965
} else {
1004-
// FIXME(#24111) Remove this check when const fn stabilizes
1005-
let (msg, note) = if let UnstableFeatures::Disallow =
1006-
self.tcx.sess.opts.unstable_features {
1007-
(format!("calls in {}s are limited to \
1008-
tuple structs and tuple variants",
1009-
self.mode),
1010-
Some("a limited form of compile-time function \
1011-
evaluation is available on a nightly \
1012-
compiler via `const fn`"))
966+
// stable const fn or unstable const fns with their feature gate
967+
// active
968+
if self.tcx.is_const_fn(def_id) {
969+
is_const_fn = true;
970+
} else if self.is_const_panic_fn(def_id) {
971+
// check the const_panic feature gate
972+
// FIXME: cannot allow this inside `allow_internal_unstable`
973+
// because that would make `panic!` insta stable in constants,
974+
// since the macro is marked with the attr
975+
if self.tcx.features().const_panic {
976+
is_const_fn = true;
977+
} else {
978+
// don't allow panics in constants without the feature gate
979+
emit_feature_err(
980+
&self.tcx.sess.parse_sess,
981+
"const_panic",
982+
self.span,
983+
GateIssue::Language,
984+
&format!("panicking in {}s is unstable", self.mode),
985+
);
986+
}
987+
} else if let Some(feat) = self.tcx.is_unstable_const_fn(def_id) {
988+
// check `#[unstable]` const fns or `#[rustc_const_unstable]`
989+
// functions without the feature gate active in this crate to
990+
// report a better error message than the one below
991+
if self.span.allows_unstable() {
992+
// `allow_internal_unstable` can make such calls stable
993+
is_const_fn = true;
994+
} else {
995+
let mut err = self.tcx.sess.struct_span_err(self.span,
996+
&format!("`{}` is not yet stable as a const fn",
997+
self.tcx.item_path_str(def_id)));
998+
help!(&mut err,
999+
"in Nightly builds, add `#![feature({})]` \
1000+
to the crate attributes to enable",
1001+
feat);
1002+
err.emit();
1003+
}
10131004
} else {
1014-
(format!("calls in {}s are limited \
1015-
to constant functions, \
1016-
tuple structs and tuple variants",
1017-
self.mode),
1018-
None)
1019-
};
1020-
let mut err = struct_span_err!(
1021-
self.tcx.sess,
1022-
self.span,
1023-
E0015,
1024-
"{}",
1025-
msg,
1026-
);
1027-
if let Some(note) = note {
1028-
err.span_note(self.span, note);
1005+
// FIXME(#24111) Remove this check when const fn stabilizes
1006+
let (msg, note) = if let UnstableFeatures::Disallow =
1007+
self.tcx.sess.opts.unstable_features {
1008+
(format!("calls in {}s are limited to \
1009+
tuple structs and tuple variants",
1010+
self.mode),
1011+
Some("a limited form of compile-time function \
1012+
evaluation is available on a nightly \
1013+
compiler via `const fn`"))
1014+
} else {
1015+
(format!("calls in {}s are limited \
1016+
to constant functions, \
1017+
tuple structs and tuple variants",
1018+
self.mode),
1019+
None)
1020+
};
1021+
let mut err = struct_span_err!(
1022+
self.tcx.sess,
1023+
self.span,
1024+
E0015,
1025+
"{}",
1026+
msg,
1027+
);
1028+
if let Some(note) = note {
1029+
err.span_note(self.span, note);
1030+
}
1031+
err.emit();
10291032
}
1030-
err.emit();
10311033
}
10321034
}
10331035
}
1036+
},
1037+
ty::FnPtr(_) => {
1038+
if self.mode != Mode::Fn {
1039+
let mut err = self.tcx.sess.struct_span_err(
1040+
self.span,
1041+
&format!("function pointers are not allowed in const fn"));
1042+
err.emit();
1043+
}
1044+
},
1045+
_ => {
1046+
self.not_const();
1047+
return
10341048
}
10351049
}
10361050

1051+
10371052
let constant_arguments = callee_def_id.and_then(|id| {
10381053
args_required_const(self.tcx, id)
10391054
});

src/test/ui/consts/issue-56164.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(const_fn)]
2+
3+
const fn foo() { (||{})() }
4+
//~^ ERROR calls in constant functions are limited to constant functions, tuple structs and tuple
5+
// variants
6+
7+
const fn bad(input: fn()) {
8+
input()
9+
//~^ ERROR function pointers are not allowed in const fn
10+
}
11+
12+
fn main() {
13+
}

src/test/ui/consts/issue-56164.stderr

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
2+
--> $DIR/issue-56164.rs:3:18
3+
|
4+
LL | const fn foo() { (||{})() }
5+
| ^^^^^^^^
6+
7+
error: function pointers are not allowed in const fn
8+
--> $DIR/issue-56164.rs:8:5
9+
|
10+
LL | input()
11+
| ^^^^^^^
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0015`.

0 commit comments

Comments
 (0)