@@ -328,6 +328,26 @@ fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bo
328
328
. map_or ( false , |mut features| features. any ( |name| name == feature_gate) )
329
329
}
330
330
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
+
331
351
fn check_terminator (
332
352
tcx : TyCtxt < ' tcx > ,
333
353
body : & ' a Body < ' tcx > ,
@@ -367,8 +387,17 @@ fn check_terminator(
367
387
fn_span : _,
368
388
} => {
369
389
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
+ {
372
401
return Err ( (
373
402
span,
374
403
format ! (
@@ -380,10 +409,10 @@ fn check_terminator(
380
409
) ) ;
381
410
}
382
411
383
- check_operand ( tcx, func, span, def_id , body) ?;
412
+ check_operand ( tcx, func, span, fn_def_id , body) ?;
384
413
385
414
for arg in args {
386
- check_operand ( tcx, arg, span, def_id , body) ?;
415
+ check_operand ( tcx, arg, span, fn_def_id , body) ?;
387
416
}
388
417
Ok ( ( ) )
389
418
} else {
0 commit comments