Re-do recursive const stability checks
Fundamentally, we have *three* disjoint categories of functions: 1. const-stable functions 2. private/unstable functions that are meant to be callable from const-stable functions 3. functions that can make use of unstable const features This PR implements the following system: - `#[rustc_const_stable]` puts functions in the first category. It may only be applied to `#[stable]` functions. - `#[rustc_const_unstable]` by default puts functions in the third category. The new attribute `#[rustc_const_stable_indirect]` can be added to such a function to move it into the second category. - `const fn` without a const stability marker are in the second category if they are still unstable. They automatically inherit the feature gate for regular calls, it can now also be used for const-calls. Also, several holes in recursive const stability checking are being closed. There's still one potential hole that is hard to avoid, which is when MIR building automatically inserts calls to a particular function in stable functions -- which happens in the panic machinery. Those need to *not* be `rustc_const_unstable` (or manually get a `rustc_const_stable_indirect`) to be sure they follow recursive const stability. But that's a fairly rare and special case so IMO it's fine. The net effect of this is that a `#[unstable]` or unmarked function can be constified simply by marking it as `const fn`, and it will then be const-callable from stable `const fn` and subject to recursive const stability requirements. If it is publicly reachable (which implies it cannot be unmarked), it will be const-unstable under the same feature gate. Only if the function ever becomes `#[stable]` does it need a `#[rustc_const_unstable]` or `#[rustc_const_stable]` marker to decide if this should also imply const-stability. Adding `#[rustc_const_unstable]` is only needed for (a) functions that need to use unstable const lang features (including intrinsics), or (b) `#[stable]` functions that are not yet intended to be const-stable. Adding `#[rustc_const_stable]` is only needed for functions that are actually meant to be directly callable from stable const code. `#[rustc_const_stable_indirect]` is used to mark intrinsics as const-callable and for `#[rustc_const_unstable]` functions that are actually called from other, exposed-on-stable `const fn`. No other attributes are required.
This commit is contained in:
parent
45089ec19e
commit
a0215d8e46
102 changed files with 1520 additions and 663 deletions
|
@ -14,7 +14,7 @@ use rustc_middle::mir::interpret::{
|
|||
UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
|
||||
};
|
||||
use rustc_middle::ty::{self, Mutability, Ty};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_target::abi::WrappingRange;
|
||||
use rustc_target::abi::call::AdjustForForeignAbiError;
|
||||
|
||||
|
@ -44,11 +44,15 @@ pub(crate) struct MutablePtrInFinal {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval_unstable_in_stable)]
|
||||
pub(crate) struct UnstableInStable {
|
||||
#[diag(const_eval_unstable_in_stable_exposed)]
|
||||
pub(crate) struct UnstableInStableExposed {
|
||||
pub gate: String,
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[help(const_eval_is_function_call)]
|
||||
pub is_function_call: bool,
|
||||
/// Need to duplicate the field so that fluent also provides it as a variable...
|
||||
pub is_function_call2: bool,
|
||||
#[suggestion(
|
||||
const_eval_unstable_sugg,
|
||||
code = "#[rustc_const_unstable(feature = \"...\", issue = \"...\")]\n",
|
||||
|
@ -117,6 +121,34 @@ pub(crate) struct UnstableConstFn {
|
|||
pub def_path: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval_unstable_intrinsic)]
|
||||
#[help]
|
||||
pub(crate) struct UnstableIntrinsic {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
pub feature: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval_unmarked_const_fn_exposed)]
|
||||
#[help]
|
||||
pub(crate) struct UnmarkedConstFnExposed {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub def_path: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval_unmarked_intrinsic_exposed)]
|
||||
#[help]
|
||||
pub(crate) struct UnmarkedIntrinsicExposed {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub def_path: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval_mutable_ref_escaping, code = E0764)]
|
||||
pub(crate) struct MutableRefEscaping {
|
||||
|
@ -153,6 +185,15 @@ pub(crate) struct NonConstFnCall {
|
|||
pub kind: ConstContext,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval_non_const_intrinsic)]
|
||||
pub(crate) struct NonConstIntrinsic {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
pub kind: ConstContext,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval_unallowed_op_in_const_context)]
|
||||
pub(crate) struct UnallowedOpInConstContext {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue