11//! Concrete error types for all operations which may be invalid in a certain const context.
22
3- use rustc_errors:: struct_span_err;
3+ use rustc_errors:: { struct_span_err, Applicability } ;
44use rustc_hir as hir;
55use rustc_hir:: def_id:: DefId ;
66use rustc_session:: config:: nightly_options;
@@ -16,7 +16,29 @@ pub fn non_const<O: NonConstOp>(ccx: &ConstCx<'_, '_>, op: O, span: Span) {
1616
1717 let gate = match op. status_in_item ( ccx) {
1818 Status :: Allowed => return ,
19- Status :: Unstable ( gate) if ccx. tcx . features ( ) . enabled ( gate) => return ,
19+
20+ Status :: Unstable ( gate) if ccx. tcx . features ( ) . enabled ( gate) => {
21+ let unstable_in_stable = ccx. const_kind ( ) == hir:: ConstContext :: ConstFn
22+ && ccx. tcx . features ( ) . enabled ( sym:: staged_api)
23+ && !ccx. tcx . has_attr ( ccx. def_id . to_def_id ( ) , sym:: rustc_const_unstable)
24+ && !super :: allow_internal_unstable ( ccx. tcx , ccx. def_id . to_def_id ( ) , gate) ;
25+
26+ if unstable_in_stable {
27+ ccx. tcx . sess
28+ . struct_span_err ( span, & format ! ( "`#[feature({})]` cannot be depended on in a const-stable function" , gate. as_str( ) ) )
29+ . span_suggestion (
30+ ccx. body . span ,
31+ "if it is not part of the public API, make this function unstably const" ,
32+ concat ! ( r#"#[rustc_const_unstable(feature = "...", issue = "...")]"# , '\n' ) . to_owned ( ) ,
33+ Applicability :: HasPlaceholders ,
34+ )
35+ . help ( "otherwise `#[allow_internal_unstable]` can be used to bypass stability checks" )
36+ . emit ( ) ;
37+ }
38+
39+ return ;
40+ }
41+
2042 Status :: Unstable ( gate) => Some ( gate) ,
2143 Status :: Forbidden => None ,
2244 } ;
0 commit comments