@@ -98,6 +98,34 @@ pub trait NonConstOp: std::fmt::Debug {
9898 }
9999}
100100
101+ #[ derive( Debug ) ]
102+ pub struct Abort ;
103+ impl NonConstOp for Abort {
104+ const STOPS_CONST_CHECKING : bool = true ;
105+
106+ fn status_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> Status {
107+ mcf_status_in_item ( ccx)
108+ }
109+
110+ fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
111+ mcf_emit_error ( ccx, span, "abort is not stable in const fn" )
112+ }
113+ }
114+
115+ #[ derive( Debug ) ]
116+ pub struct NonPrimitiveOp ;
117+ impl NonConstOp for NonPrimitiveOp {
118+ const STOPS_CONST_CHECKING : bool = true ;
119+
120+ fn status_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> Status {
121+ mcf_status_in_item ( ccx)
122+ }
123+
124+ fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
125+ mcf_emit_error ( ccx, span, "only int, `bool` and `char` operations are stable in const fn" )
126+ }
127+ }
128+
101129/// A function call where the callee is a pointer.
102130#[ derive( Debug ) ]
103131pub struct FnCallIndirect ;
@@ -130,7 +158,8 @@ impl NonConstOp for FnCallNonConst {
130158///
131159/// Contains the name of the feature that would allow the use of this function.
132160#[ derive( Debug ) ]
133- pub struct FnCallUnstable ( pub DefId , pub Symbol ) ;
161+ pub struct FnCallUnstable ( pub DefId , pub Option < Symbol > ) ;
162+
134163impl NonConstOp for FnCallUnstable {
135164 fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
136165 let FnCallUnstable ( def_id, feature) = * self ;
@@ -139,13 +168,51 @@ impl NonConstOp for FnCallUnstable {
139168 span,
140169 & format ! ( "`{}` is not yet stable as a const fn" , ccx. tcx. def_path_str( def_id) ) ,
141170 ) ;
142- if nightly_options:: is_nightly_build ( ) {
143- err. help ( & format ! ( "add `#![feature({})]` to the crate attributes to enable" , feature) ) ;
171+
172+ if ccx. is_const_stable_const_fn ( ) {
173+ err. help ( "Const-stable functions can only call other const-stable functions" ) ;
174+ } else if nightly_options:: is_nightly_build ( ) {
175+ if let Some ( feature) = feature {
176+ err. help ( & format ! (
177+ "add `#![feature({})]` to the crate attributes to enable" ,
178+ feature
179+ ) ) ;
180+ }
144181 }
145182 err. emit ( ) ;
146183 }
147184}
148185
186+ #[ derive( Debug ) ]
187+ pub struct FnPtrCast ;
188+ impl NonConstOp for FnPtrCast {
189+ const STOPS_CONST_CHECKING : bool = true ;
190+
191+ fn status_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> Status {
192+ mcf_status_in_item ( ccx)
193+ }
194+
195+ fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
196+ mcf_emit_error ( ccx, span, "function pointer casts are not allowed in const fn" ) ;
197+ }
198+ }
199+
200+ #[ derive( Debug ) ]
201+ pub struct Generator ;
202+ impl NonConstOp for Generator {
203+ const STOPS_CONST_CHECKING : bool = true ;
204+
205+ fn status_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> Status {
206+ // FIXME: This means generator-only MIR is only forbidden in const fn. This is for
207+ // compatibility with the old code. Such MIR should be forbidden everywhere.
208+ mcf_status_in_item ( ccx)
209+ }
210+
211+ fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
212+ mcf_emit_error ( ccx, span, "const fn generators are unstable" ) ;
213+ }
214+ }
215+
149216#[ derive( Debug ) ]
150217pub struct HeapAllocation ;
151218impl NonConstOp for HeapAllocation {
@@ -408,6 +475,24 @@ impl NonConstOp for ThreadLocalAccess {
408475 }
409476}
410477
478+ #[ derive( Debug ) ]
479+ pub struct Transmute ;
480+ impl NonConstOp for Transmute {
481+ const STOPS_CONST_CHECKING : bool = true ;
482+
483+ fn status_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> Status {
484+ if ccx. const_kind ( ) != hir:: ConstContext :: ConstFn {
485+ Status :: Allowed
486+ } else {
487+ Status :: Unstable ( sym:: const_fn_transmute)
488+ }
489+ }
490+
491+ fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
492+ mcf_emit_error ( ccx, span, "can only call `transmute` from const items, not `const fn`" ) ;
493+ }
494+ }
495+
411496#[ derive( Debug ) ]
412497pub struct UnionAccess ;
413498impl NonConstOp for UnionAccess {
@@ -430,3 +515,135 @@ impl NonConstOp for UnionAccess {
430515 . emit ( ) ;
431516 }
432517}
518+
519+ /// See [#64992].
520+ ///
521+ /// [#64992]: https://github.com/rust-lang/rust/issues/64992
522+ #[ derive( Debug ) ]
523+ pub struct UnsizingCast ;
524+ impl NonConstOp for UnsizingCast {
525+ fn status_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> Status {
526+ if ccx. const_kind ( ) != hir:: ConstContext :: ConstFn {
527+ Status :: Allowed
528+ } else {
529+ Status :: Unstable ( sym:: const_fn_transmute)
530+ }
531+ }
532+
533+ fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
534+ mcf_emit_error (
535+ ccx,
536+ span,
537+ "unsizing casts to types besides slices are not allowed in const fn" ,
538+ ) ;
539+ }
540+ }
541+
542+ pub mod ty {
543+ use super :: * ;
544+
545+ #[ derive( Debug ) ]
546+ pub struct MutRef ;
547+ impl NonConstOp for MutRef {
548+ const STOPS_CONST_CHECKING : bool = true ;
549+
550+ fn status_in_item ( & self , _ccx : & ConstCx < ' _ , ' _ > ) -> Status {
551+ Status :: Unstable ( sym:: const_mut_refs)
552+ }
553+
554+ fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
555+ mcf_emit_error ( ccx, span, "mutable references in const fn are unstable" ) ;
556+ }
557+ }
558+
559+ #[ derive( Debug ) ]
560+ pub struct FnPtr ;
561+ impl NonConstOp for FnPtr {
562+ const STOPS_CONST_CHECKING : bool = true ;
563+
564+ fn status_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> Status {
565+ // FIXME: This attribute a hack to allow the specialization of the `futures` API. See
566+ // #59739. We should have a proper feature gate for this.
567+ if ccx. tcx . has_attr ( ccx. def_id . to_def_id ( ) , sym:: rustc_allow_const_fn_ptr) {
568+ Status :: Allowed
569+ } else {
570+ mcf_status_in_item ( ccx)
571+ }
572+ }
573+
574+ fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
575+ mcf_emit_error ( ccx, span, "function pointers in const fn are unstable" ) ;
576+ }
577+ }
578+
579+ #[ derive( Debug ) ]
580+ pub struct ImplTrait ;
581+ impl NonConstOp for ImplTrait {
582+ const STOPS_CONST_CHECKING : bool = true ;
583+
584+ fn status_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> Status {
585+ mcf_status_in_item ( ccx)
586+ }
587+
588+ fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
589+ mcf_emit_error ( ccx, span, "`impl Trait` in const fn is unstable" ) ;
590+ }
591+ }
592+
593+ #[ derive( Debug ) ]
594+ pub struct TraitBound ;
595+ impl NonConstOp for TraitBound {
596+ const STOPS_CONST_CHECKING : bool = true ;
597+
598+ fn status_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> Status {
599+ mcf_status_in_item ( ccx)
600+ }
601+
602+ fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
603+ mcf_emit_error (
604+ ccx,
605+ span,
606+ "trait bounds other than `Sized` on const fn parameters are unstable" ,
607+ ) ;
608+ }
609+ }
610+
611+ /// A trait bound with the `?const Trait` opt-out
612+ #[ derive( Debug ) ]
613+ pub struct TraitBoundNotConst ;
614+ impl NonConstOp for TraitBoundNotConst {
615+ const STOPS_CONST_CHECKING : bool = true ;
616+
617+ fn status_in_item ( & self , _: & ConstCx < ' _ , ' _ > ) -> Status {
618+ Status :: Unstable ( sym:: const_trait_bound_opt_out)
619+ }
620+
621+ fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
622+ feature_err (
623+ & ccx. tcx . sess . parse_sess ,
624+ sym:: const_trait_bound_opt_out,
625+ span,
626+ "`?const Trait` syntax is unstable" ,
627+ )
628+ . emit ( )
629+ }
630+ }
631+ }
632+
633+ fn mcf_status_in_item ( ccx : & ConstCx < ' _ , ' _ > ) -> Status {
634+ if ccx. const_kind ( ) != hir:: ConstContext :: ConstFn {
635+ Status :: Allowed
636+ } else {
637+ Status :: Unstable ( sym:: const_fn)
638+ }
639+ }
640+
641+ fn mcf_emit_error ( ccx : & ConstCx < ' _ , ' _ > , span : Span , msg : & str ) {
642+ struct_span_err ! ( ccx. tcx. sess, span, E0723 , "{}" , msg)
643+ . note (
644+ "see issue #57563 <https://github.com/rust-lang/rust/issues/57563> \
645+ for more information",
646+ )
647+ . help ( "add `#![feature(const_fn)]` to the crate attributes to enable" )
648+ . emit ( ) ;
649+ }
0 commit comments