Skip to content

Commit 57f2e12

Browse files
Completely deny calling functions with const conditions in MIR const check unless const_trait_impl is enabled
This will help us make sure that we never leak any conditionally const functions into stable.
1 parent e319838 commit 57f2e12

13 files changed

+129
-41
lines changed

compiler/rustc_const_eval/src/check_consts/check.rs

+17-12
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
363363
}
364364

365365
fn revalidate_conditional_constness(
366-
&self,
366+
&mut self,
367367
callee: DefId,
368368
callee_args: ty::GenericArgsRef<'tcx>,
369369
call_source: CallSource,
@@ -374,11 +374,24 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
374374
return;
375375
}
376376

377+
let const_conditions = tcx.const_conditions(callee).instantiate(tcx, callee_args);
378+
// If there are any const conditions on this fn and `const_trait_impl`
379+
// is not enabled, simply bail. We shouldn't be able to call conditionally
380+
// const functions on stable.
381+
if !const_conditions.is_empty() && !tcx.features().const_trait_impl() {
382+
self.check_op(ops::FnCallNonConst {
383+
callee,
384+
args: callee_args,
385+
span: call_span,
386+
call_source,
387+
feature: Some(sym::const_trait_impl),
388+
});
389+
return;
390+
}
391+
377392
let infcx = tcx.infer_ctxt().build(self.body.typing_mode(tcx));
378393
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
379394

380-
let const_conditions = tcx.const_conditions(callee).instantiate(tcx, callee_args);
381-
382395
let body_id = self.body.source.def_id().expect_local();
383396
let host_polarity = match self.const_kind() {
384397
hir::ConstContext::ConstFn => ty::BoundConstness::Maybe,
@@ -621,7 +634,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
621634
};
622635

623636
let ConstCx { tcx, body, param_env, .. } = *self.ccx;
624-
let caller = self.def_id();
625637

626638
let fn_ty = func.ty(body, tcx);
627639

@@ -639,12 +651,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
639651
}
640652
};
641653

642-
self.revalidate_conditional_constness(
643-
callee,
644-
fn_args,
645-
call_source,
646-
terminator.source_info.span,
647-
);
654+
self.revalidate_conditional_constness(callee, fn_args, call_source, *fn_span);
648655

649656
let mut is_trait = false;
650657
// Attempting to call a trait method?
@@ -684,7 +691,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
684691
None
685692
};
686693
self.check_op(ops::FnCallNonConst {
687-
caller,
688694
callee,
689695
args: fn_args,
690696
span: *fn_span,
@@ -774,7 +780,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
774780
// Trait functions are not `const fn` so we have to skip them here.
775781
if !tcx.is_const_fn(callee) && !is_trait {
776782
self.check_op(ops::FnCallNonConst {
777-
caller,
778783
callee,
779784
args: fn_args,
780785
span: *fn_span,

compiler/rustc_const_eval/src/check_consts/ops.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//! Concrete error types for all operations which may be invalid in a certain const context.
22
3-
use hir::def_id::LocalDefId;
43
use hir::{ConstContext, LangItem};
54
use rustc_errors::Diag;
65
use rustc_errors::codes::*;
@@ -74,7 +73,6 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
7473
/// A function call where the callee is not marked as `const`.
7574
#[derive(Debug, Clone, Copy)]
7675
pub(crate) struct FnCallNonConst<'tcx> {
77-
pub caller: LocalDefId,
7876
pub callee: DefId,
7977
pub args: GenericArgsRef<'tcx>,
8078
pub span: Span,
@@ -87,8 +85,9 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
8785
#[allow(rustc::diagnostic_outside_of_impl)]
8886
#[allow(rustc::untranslatable_diagnostic)]
8987
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> {
90-
let FnCallNonConst { caller, callee, args, span, call_source, feature } = *self;
91-
let ConstCx { tcx, param_env, body, .. } = *ccx;
88+
let FnCallNonConst { callee, args, span, call_source, feature } = *self;
89+
let ConstCx { tcx, param_env, .. } = *ccx;
90+
let caller = ccx.def_id();
9291

9392
let diag_trait = |err, self_ty: Ty<'_>, trait_id| {
9493
let trait_ref = TraitRef::from_method(tcx, trait_id, args);
@@ -116,7 +115,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
116115
let obligation =
117116
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
118117

119-
let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx));
118+
let infcx = tcx.infer_ctxt().build(ccx.body.typing_mode(tcx));
120119
let mut selcx = SelectionContext::new(&infcx);
121120
let implsrc = selcx.select(&obligation);
122121

@@ -289,7 +288,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
289288
if let Some(feature) = feature {
290289
ccx.tcx.disabled_nightly_features(
291290
&mut err,
292-
body.source.def_id().as_local().map(|local| ccx.tcx.local_def_id_to_hir_id(local)),
291+
Some(ccx.tcx.local_def_id_to_hir_id(caller)),
293292
[(String::new(), feature)],
294293
);
295294
}

tests/ui/traits/const-traits/const-drop-fail-2.stderr

+8-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ LL | const fn check<T: ~const Destruct>(_: T) {}
2929
| |
3030
| the destructor for this type cannot be evaluated in constant functions
3131

32+
error[E0277]: the trait bound `T: ~const A` is not satisfied
33+
--> $DIR/const-drop-fail-2.rs:41:9
34+
|
35+
LL | T::a();
36+
| ^^^^^^
37+
3238
error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions
3339
--> $DIR/const-drop-fail-2.rs:41:9
3440
|
@@ -41,7 +47,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
4147
LL + #![feature(effects)]
4248
|
4349

44-
error: aborting due to 5 previous errors
50+
error: aborting due to 6 previous errors
4551

46-
Some errors have detailed explanations: E0015, E0493.
52+
Some errors have detailed explanations: E0015, E0277, E0493.
4753
For more information about an error, try `rustc --explain E0015`.

tests/ui/traits/const-traits/const-drop.precise.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ error[E0493]: destructor of `T` cannot be evaluated at compile-time
7878
LL | const fn a<T: ~const Destruct>(_: T) {}
7979
| ^ the destructor for this type cannot be evaluated in constant functions
8080

81+
error[E0277]: the trait bound `T: ~const SomeTrait` is not satisfied
82+
--> $DIR/const-drop.rs:69:13
83+
|
84+
LL | T::foo();
85+
| ^^^^^^^^
86+
8187
error[E0015]: cannot call non-const fn `<T as SomeTrait>::foo` in constant functions
8288
--> $DIR/const-drop.rs:69:13
8389
|
@@ -90,7 +96,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
9096
LL + #![feature(effects)]
9197
|
9298

93-
error: aborting due to 10 previous errors
99+
error: aborting due to 11 previous errors
94100

95101
Some errors have detailed explanations: E0015, E0277, E0493.
96102
For more information about an error, try `rustc --explain E0015`.

tests/ui/traits/const-traits/const-drop.stock.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ LL | const fn a<T: ~const Destruct>(_: T) {}
8080
| |
8181
| the destructor for this type cannot be evaluated in constant functions
8282

83+
error[E0277]: the trait bound `T: ~const SomeTrait` is not satisfied
84+
--> $DIR/const-drop.rs:69:13
85+
|
86+
LL | T::foo();
87+
| ^^^^^^^^
88+
8389
error[E0015]: cannot call non-const fn `<T as SomeTrait>::foo` in constant functions
8490
--> $DIR/const-drop.rs:69:13
8591
|
@@ -92,7 +98,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
9298
LL + #![feature(effects)]
9399
|
94100

95-
error: aborting due to 10 previous errors
101+
error: aborting due to 11 previous errors
96102

97103
Some errors have detailed explanations: E0015, E0277, E0493.
98104
For more information about an error, try `rustc --explain E0015`.

tests/ui/traits/const-traits/cross-crate.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ const fn const_context() {
1818
#[cfg(any(stocknc, gatednc))]
1919
NonConst.func();
2020
//[stocknc]~^ ERROR: cannot call
21-
//[stocknc,gatednc]~^^ ERROR: the trait bound
21+
//[stocknc]~| ERROR: cannot call
22+
//[gatednc]~^^^ ERROR: the trait bound
2223
Const.func();
23-
//[stock]~^ ERROR: cannot call
24-
//[stocknc]~^^ ERROR: cannot call
24+
//[stock,stocknc]~^ ERROR: cannot call
25+
//[stock,stocknc]~| ERROR: cannot call
2526
}
2627

2728
fn main() {}

tests/ui/traits/const-traits/cross-crate.stock.stderr

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
2-
--> $DIR/cross-crate.rs:22:11
2+
--> $DIR/cross-crate.rs:23:11
33
|
44
LL | Const.func();
55
| ^^^^^^
@@ -10,6 +10,19 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
1010
LL + #![feature(const_trait_impl)]
1111
|
1212

13-
error: aborting due to 1 previous error
13+
error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
14+
--> $DIR/cross-crate.rs:23:11
15+
|
16+
LL | Const.func();
17+
| ^^^^^^
18+
|
19+
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
20+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
21+
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
22+
|
23+
LL + #![feature(const_trait_impl)]
24+
|
25+
26+
error: aborting due to 2 previous errors
1427

1528
For more information about this error, try `rustc --explain E0015`.
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
2-
--> $DIR/cross-crate.rs:19:5
1+
error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
2+
--> $DIR/cross-crate.rs:19:14
33
|
44
LL | NonConst.func();
5-
| ^^^^^^^^^^^^^^^
5+
| ^^^^^^
6+
|
7+
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
8+
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
9+
|
10+
LL + #![feature(const_trait_impl)]
11+
|
612

713
error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
814
--> $DIR/cross-crate.rs:19:14
@@ -11,24 +17,37 @@ LL | NonConst.func();
1117
| ^^^^^^
1218
|
1319
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
20+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
21+
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
22+
|
23+
LL + #![feature(const_trait_impl)]
24+
|
25+
26+
error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
27+
--> $DIR/cross-crate.rs:23:11
28+
|
29+
LL | Const.func();
30+
| ^^^^^^
31+
|
32+
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
1433
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
1534
|
1635
LL + #![feature(const_trait_impl)]
1736
|
1837

1938
error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
20-
--> $DIR/cross-crate.rs:22:11
39+
--> $DIR/cross-crate.rs:23:11
2140
|
2241
LL | Const.func();
2342
| ^^^^^^
2443
|
2544
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
45+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
2646
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
2747
|
2848
LL + #![feature(const_trait_impl)]
2949
|
3050

31-
error: aborting due to 3 previous errors
51+
error: aborting due to 4 previous errors
3252

33-
Some errors have detailed explanations: E0015, E0277.
34-
For more information about an error, try `rustc --explain E0015`.
53+
For more information about this error, try `rustc --explain E0015`.

tests/ui/traits/const-traits/default-method-body-is-const-body-checking.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
//@ known-bug: #110395
2-
//@ check-pass
3-
41
#![feature(const_trait_impl)]
52

63
#[const_trait]
@@ -13,7 +10,7 @@ const fn foo<T>() where T: ~const Tr {}
1310
pub trait Foo {
1411
fn foo() {
1512
foo::<()>();
16-
//FIXME ~^ ERROR the trait bound `(): Tr` is not satisfied
13+
//~^ ERROR the trait bound `(): ~const Tr` is not satisfied
1714
}
1815
}
1916

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0277]: the trait bound `(): ~const Tr` is not satisfied
2+
--> $DIR/default-method-body-is-const-body-checking.rs:12:9
3+
|
4+
LL | foo::<()>();
5+
| ^^^^^^^^^^^
6+
|
7+
note: required by a bound in `foo`
8+
--> $DIR/default-method-body-is-const-body-checking.rs:7:28
9+
|
10+
LL | const fn foo<T>() where T: ~const Tr {}
11+
| ^^^^^^ required by this bound in `foo`
12+
13+
error: aborting due to 1 previous error
14+
15+
For more information about this error, try `rustc --explain E0277`.

tests/ui/traits/const-traits/specializing-constness-2.stderr

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
error[E0277]: the trait bound `T: ~const A` is not satisfied
2+
--> $DIR/specializing-constness-2.rs:27:5
3+
|
4+
LL | <T as A>::a();
5+
| ^^^^^^^^^^^^^
6+
17
error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions
28
--> $DIR/specializing-constness-2.rs:27:5
39
|
@@ -10,6 +16,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
1016
LL + #![feature(effects)]
1117
|
1218

13-
error: aborting due to 1 previous error
19+
error: aborting due to 2 previous errors
1420

15-
For more information about this error, try `rustc --explain E0015`.
21+
Some errors have detailed explanations: E0015, E0277.
22+
For more information about an error, try `rustc --explain E0015`.

tests/ui/traits/const-traits/staged-api-user-crate.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ fn non_const_context() {
1111
const fn stable_const_context() {
1212
Unstable::func();
1313
//~^ ERROR cannot call non-const fn `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions
14+
//~| ERROR cannot call non-const fn `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions
1415
}
1516

1617
fn main() {}

tests/ui/traits/const-traits/staged-api-user-crate.stderr

+14-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,19 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
1010
LL + #![feature(const_trait_impl)]
1111
|
1212

13-
error: aborting due to 1 previous error
13+
error[E0015]: cannot call non-const fn `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions
14+
--> $DIR/staged-api-user-crate.rs:12:5
15+
|
16+
LL | Unstable::func();
17+
| ^^^^^^^^^^^^^^^^
18+
|
19+
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
20+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
21+
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
22+
|
23+
LL + #![feature(const_trait_impl)]
24+
|
25+
26+
error: aborting due to 2 previous errors
1427

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

0 commit comments

Comments
 (0)