@@ -328,6 +328,26 @@ fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bo
328328 . map_or ( false , |mut features| features. any ( |name| name == feature_gate) )
329329}
330330
331+ /// Returns `true` if the given library feature gate is allowed within the function with the given `DefId`.
332+ pub fn lib_feature_allowed ( tcx : TyCtxt < ' tcx > , def_id : DefId , feature_gate : Symbol ) -> bool {
333+ // All features require that the corresponding gate be enabled,
334+ // even if the function has `#[allow_internal_unstable(the_gate)]`.
335+ if !tcx. features ( ) . declared_lib_features . iter ( ) . any ( |& ( sym, _) | sym == feature_gate) {
336+ return false ;
337+ }
338+
339+ // If this crate is not using stability attributes, or this function is not claiming to be a
340+ // stable `const fn`, that is all that is required.
341+ if !tcx. features ( ) . staged_api || tcx. has_attr ( def_id, sym:: rustc_const_unstable) {
342+ return true ;
343+ }
344+
345+ // However, we cannot allow stable `const fn`s to use unstable features without an explicit
346+ // opt-in via `allow_internal_unstable`.
347+ attr:: allow_internal_unstable ( & tcx. get_attrs ( def_id) , & tcx. sess . diagnostic ( ) )
348+ . map_or ( false , |mut features| features. any ( |name| name == feature_gate) )
349+ }
350+
331351fn check_terminator (
332352 tcx : TyCtxt < ' tcx > ,
333353 body : & ' a Body < ' tcx > ,
@@ -367,8 +387,17 @@ fn check_terminator(
367387 fn_span : _,
368388 } => {
369389 let fn_ty = func. ty ( body, tcx) ;
370- if let ty:: FnDef ( def_id, _) = fn_ty. kind {
371- if !crate :: const_eval:: is_min_const_fn ( tcx, def_id) {
390+ if let ty:: FnDef ( fn_def_id, _) = fn_ty. kind {
391+ // Allow unstable const if we opt in by using #[allow_internal_unstable]
392+ // on function or macro declaration.
393+ if !crate :: const_eval:: is_min_const_fn ( tcx, fn_def_id)
394+ && !crate :: const_eval:: is_unstable_const_fn ( tcx, fn_def_id)
395+ . map ( |feature| {
396+ span. allows_unstable ( feature)
397+ || lib_feature_allowed ( tcx, def_id, feature)
398+ } )
399+ . unwrap_or ( false )
400+ {
372401 return Err ( (
373402 span,
374403 format ! (
@@ -380,10 +409,10 @@ fn check_terminator(
380409 ) ) ;
381410 }
382411
383- check_operand ( tcx, func, span, def_id , body) ?;
412+ check_operand ( tcx, func, span, fn_def_id , body) ?;
384413
385414 for arg in args {
386- check_operand ( tcx, arg, span, def_id , body) ?;
415+ check_operand ( tcx, arg, span, fn_def_id , body) ?;
387416 }
388417 Ok ( ( ) )
389418 } else {
0 commit comments