Stabilize const_fn_fn_ptr_basics and const_fn_trait_bound

This commit is contained in:
Eric Holk 2022-02-08 16:33:15 -08:00
parent d137c3a7bd
commit 7723506d13
9 changed files with 16 additions and 157 deletions

View File

@ -359,7 +359,6 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
match *ty.kind() { match *ty.kind() {
ty::Ref(_, _, hir::Mutability::Mut) => self.check_op(ops::ty::MutRef(kind)), ty::Ref(_, _, hir::Mutability::Mut) => self.check_op(ops::ty::MutRef(kind)),
ty::Opaque(..) => self.check_op(ops::ty::ImplTrait), ty::Opaque(..) => self.check_op(ops::ty::ImplTrait),
ty::FnPtr(..) => self.check_op(ops::ty::FnPtr(kind)),
ty::Dynamic(preds, _) => { ty::Dynamic(preds, _) => {
for pred in preds.iter() { for pred in preds.iter() {
@ -395,6 +394,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
| ty::PredicateKind::Projection(_) | ty::PredicateKind::Projection(_)
| ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Trait(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
ty::PredicateKind::ObjectSafe(_) => { ty::PredicateKind::ObjectSafe(_) => {
bug!("object safe predicate on function: {:#?}", predicate) bug!("object safe predicate on function: {:#?}", predicate)
@ -405,27 +405,6 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
ty::PredicateKind::Subtype(_) | ty::PredicateKind::Coerce(_) => { ty::PredicateKind::Subtype(_) | ty::PredicateKind::Coerce(_) => {
bug!("subtype/coerce predicate on function: {:#?}", predicate) bug!("subtype/coerce predicate on function: {:#?}", predicate)
} }
ty::PredicateKind::Trait(pred) => {
if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
continue;
}
match pred.self_ty().kind() {
ty::Param(p) => {
let generics = tcx.generics_of(current);
let def = generics.type_param(p, tcx);
let span = tcx.def_span(def.def_id);
// These are part of the function signature, so treat them like
// arguments when determining importance.
let kind = LocalKind::Arg;
self.check_op_spanned(ops::ty::TraitBound(kind), span);
}
// other kinds of bounds are either tautologies
// or cause errors in other passes
_ => continue,
}
}
} }
} }
match predicates.parent { match predicates.parent {
@ -613,7 +592,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
), ),
_, _,
_, _,
) => self.check_op(ops::FnPtrCast), ) => {
// Nothing to do here. Function pointer casts are allowed now.
}
Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), _, _) => { Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), _, _) => {
// Nothing to check here (`check_local_or_return_ty` ensures no trait objects occur // Nothing to check here (`check_local_or_return_ty` ensures no trait objects occur

View File

@ -355,31 +355,6 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
} }
} }
#[derive(Debug)]
pub struct FnPtrCast;
impl<'tcx> NonConstOp<'tcx> for FnPtrCast {
fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status {
if ccx.const_kind() != hir::ConstContext::ConstFn {
Status::Allowed
} else {
Status::Unstable(sym::const_fn_fn_ptr_basics)
}
}
fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_fn_fn_ptr_basics,
span,
&format!("function pointer casts are not allowed in {}s", ccx.const_kind()),
)
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct Generator(pub hir::GeneratorKind); pub struct Generator(pub hir::GeneratorKind);
impl<'tcx> NonConstOp<'tcx> for Generator { impl<'tcx> NonConstOp<'tcx> for Generator {
@ -821,40 +796,6 @@ pub mod ty {
} }
} }
#[derive(Debug)]
pub struct FnPtr(pub mir::LocalKind);
impl<'tcx> NonConstOp<'tcx> for FnPtr {
fn importance(&self) -> DiagnosticImportance {
match self.0 {
mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary,
mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => {
DiagnosticImportance::Primary
}
}
}
fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status {
if ccx.const_kind() != hir::ConstContext::ConstFn {
Status::Allowed
} else {
Status::Unstable(sym::const_fn_fn_ptr_basics)
}
}
fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_fn_fn_ptr_basics,
span,
&format!("function pointers cannot appear in {}s", ccx.const_kind()),
)
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct ImplTrait; pub struct ImplTrait;
impl<'tcx> NonConstOp<'tcx> for ImplTrait { impl<'tcx> NonConstOp<'tcx> for ImplTrait {
@ -876,49 +817,6 @@ pub mod ty {
} }
} }
#[derive(Debug)]
pub struct TraitBound(pub mir::LocalKind);
impl<'tcx> NonConstOp<'tcx> for TraitBound {
fn importance(&self) -> DiagnosticImportance {
match self.0 {
mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary,
mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => {
DiagnosticImportance::Primary
}
}
}
fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status {
if ccx.const_kind() != hir::ConstContext::ConstFn {
Status::Allowed
} else {
Status::Unstable(sym::const_fn_trait_bound)
}
}
fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let mut err = feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_fn_trait_bound,
span,
"trait bounds other than `Sized` on const fn parameters are unstable",
);
match ccx.fn_sig() {
Some(fn_sig) if !fn_sig.span.contains(span) => {
err.span_label(fn_sig.span, "function declared as const here");
}
_ => {}
}
err
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct DynTrait(pub mir::LocalKind); pub struct DynTrait(pub mir::LocalKind);
impl<'tcx> NonConstOp<'tcx> for DynTrait { impl<'tcx> NonConstOp<'tcx> for DynTrait {

View File

@ -86,6 +86,10 @@ declare_features! (
(accepted, conservative_impl_trait, "1.26.0", Some(34511), None), (accepted, conservative_impl_trait, "1.26.0", Some(34511), None),
/// Allows calling constructor functions in `const fn`. /// Allows calling constructor functions in `const fn`.
(accepted, const_constructor, "1.40.0", Some(61456), None), (accepted, const_constructor, "1.40.0", Some(61456), None),
/// Allows using and casting function pointers in a `const fn`.
(accepted, const_fn_fn_ptr_basics, "1.60.0", Some(57563), None),
/// Allows trait bounds in `const fn`.
(accepted, const_fn_trait_bound, "1.60.0", Some(93706), None),
/// Allows calling `transmute` in const fn /// Allows calling `transmute` in const fn
(accepted, const_fn_transmute, "1.56.0", Some(53605), None), (accepted, const_fn_transmute, "1.56.0", Some(53605), None),
/// Allows accessing fields of unions inside `const` functions. /// Allows accessing fields of unions inside `const` functions.

View File

@ -338,10 +338,6 @@ declare_features! (
(active, const_extern_fn, "1.40.0", Some(64926), None), (active, const_extern_fn, "1.40.0", Some(64926), None),
/// Allows basic arithmetic on floating point types in a `const fn`. /// Allows basic arithmetic on floating point types in a `const fn`.
(active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None), (active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None),
/// Allows using and casting function pointers in a `const fn`.
(active, const_fn_fn_ptr_basics, "1.48.0", Some(57563), None),
/// Allows trait bounds in `const fn`.
(active, const_fn_trait_bound, "1.53.0", Some(93706), None),
/// Allows `for _ in _` loops in const contexts. /// Allows `for _ in _` loops in const contexts.
(active, const_for, "1.56.0", Some(87575), None), (active, const_for, "1.56.0", Some(87575), None),
/// Allows argument and return position `impl Trait` in a `const fn`. /// Allows argument and return position `impl Trait` in a `const fn`.

View File

@ -140,7 +140,7 @@
#![feature(box_syntax)] #![feature(box_syntax)]
#![feature(cfg_sanitize)] #![feature(cfg_sanitize)]
#![feature(const_deref)] #![feature(const_deref)]
#![feature(const_fn_trait_bound)] #![cfg_attr(bootstrap, feature(const_fn_trait_bound))]
#![feature(const_mut_refs)] #![feature(const_mut_refs)]
#![feature(const_ptr_write)] #![feature(const_ptr_write)]
#![feature(const_precise_live_drops)] #![feature(const_precise_live_drops)]

View File

@ -158,8 +158,8 @@
#![feature(cfg_target_has_atomic)] #![feature(cfg_target_has_atomic)]
#![feature(cfg_target_has_atomic_equal_alignment)] #![feature(cfg_target_has_atomic_equal_alignment)]
#![feature(const_fn_floating_point_arithmetic)] #![feature(const_fn_floating_point_arithmetic)]
#![feature(const_fn_fn_ptr_basics)] #![cfg_attr(bootstrap, feature(const_fn_fn_ptr_basics))]
#![feature(const_fn_trait_bound)] #![cfg_attr(bootstrap, feature(const_fn_trait_bound))]
#![feature(const_impl_trait)] #![feature(const_impl_trait)]
#![feature(const_mut_refs)] #![feature(const_mut_refs)]
#![feature(const_precise_live_drops)] #![feature(const_precise_live_drops)]

View File

@ -20,8 +20,8 @@
#![feature(rustc_allow_const_fn_unstable)] #![feature(rustc_allow_const_fn_unstable)]
#![feature(nll)] #![feature(nll)]
#![feature(staged_api)] #![feature(staged_api)]
#![feature(const_fn_trait_bound)] #![cfg_attr(bootstrap, feature(const_fn_trait_bound))]
#![feature(const_fn_fn_ptr_basics)] #![cfg_attr(bootstrap, feature(const_fn_fn_ptr_basics))]
#![feature(allow_internal_unstable)] #![feature(allow_internal_unstable)]
#![feature(decl_macro)] #![feature(decl_macro)]
#![feature(extern_types)] #![feature(extern_types)]

View File

@ -242,8 +242,8 @@
#![feature(char_internals)] #![feature(char_internals)]
#![feature(concat_bytes)] #![feature(concat_bytes)]
#![feature(concat_idents)] #![feature(concat_idents)]
#![feature(const_fn_fn_ptr_basics)] #![cfg_attr(bootstrap, feature(const_fn_fn_ptr_basics))]
#![feature(const_fn_trait_bound)] #![cfg_attr(bootstrap, feature(const_fn_trait_bound))]
#![feature(const_format_args)] #![feature(const_format_args)]
#![feature(const_io_structs)] #![feature(const_io_structs)]
#![feature(const_ip)] #![feature(const_ip)]

View File

@ -32,32 +32,12 @@ pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv:
| ty::PredicateKind::Projection(_) | ty::PredicateKind::Projection(_)
| ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Trait(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {:#?}", predicate), ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {:#?}", predicate),
ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {:#?}", predicate), ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {:#?}", predicate),
ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {:#?}", predicate), ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {:#?}", predicate),
ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {:#?}", predicate), ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {:#?}", predicate),
ty::PredicateKind::Trait(pred) => {
if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
continue;
}
match pred.self_ty().kind() {
ty::Param(ref p) => {
let generics = tcx.generics_of(current);
let def = generics.type_param(p, tcx);
let span = tcx.def_span(def.def_id);
return Err((
span,
"trait bounds other than `Sized` \
on const fn parameters are unstable"
.into(),
));
},
// other kinds of bounds are either tautologies
// or cause errors in other passes
_ => continue,
}
},
} }
} }
match predicates.parent { match predicates.parent {