88//! through, but errors for structured control flow in a `const` should be emitted here.
99
1010use rustc_attr as attr;
11- use rustc_errors:: struct_span_err;
1211use rustc_hir as hir;
1312use rustc_hir:: def_id:: LocalDefId ;
1413use rustc_hir:: intravisit:: { self , Visitor } ;
@@ -18,6 +17,8 @@ use rustc_middle::ty::TyCtxt;
1817use rustc_session:: parse:: feature_err;
1918use rustc_span:: { sym, Span , Symbol } ;
2019
20+ use crate :: errors:: { ConstImplConstTrait , ExprNotAllowedInContext } ;
21+
2122/// An expression that is not *always* legal in a const context.
2223#[ derive( Clone , Copy ) ]
2324enum NonConstExpr {
@@ -133,18 +134,22 @@ impl<'tcx> CheckConstVisitor<'tcx> {
133134 let const_kind =
134135 const_kind. expect ( "`const_check_violated` may only be called inside a const context" ) ;
135136
136- let msg = format ! ( "{} is not allowed in a `{}`" , expr. name( ) , const_kind. keyword_name( ) ) ;
137-
138137 let required_gates = required_gates. unwrap_or ( & [ ] ) ;
139138 let missing_gates: Vec < _ > =
140139 required_gates. iter ( ) . copied ( ) . filter ( |& g| !features. enabled ( g) ) . collect ( ) ;
141140
142141 match missing_gates. as_slice ( ) {
143142 [ ] => {
144- struct_span_err ! ( tcx. sess, span, E0744 , "{}" , msg) . emit ( ) ;
143+ tcx. sess . emit_err ( ExprNotAllowedInContext {
144+ span,
145+ expr : expr. name ( ) ,
146+ context : const_kind. keyword_name ( ) ,
147+ } ) ;
145148 }
146149
147150 [ missing_primary, ref missing_secondary @ ..] => {
151+ let msg =
152+ format ! ( "{} is not allowed in a `{}`" , expr. name( ) , const_kind. keyword_name( ) ) ;
148153 let mut err = feature_err ( & tcx. sess . parse_sess , * missing_primary, span, & msg) ;
149154
150155 // If multiple feature gates would be required to enable this expression, include
@@ -191,6 +196,26 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
191196 self . tcx . hir ( )
192197 }
193198
199+ fn visit_item ( & mut self , item : & ' tcx hir:: Item < ' tcx > ) {
200+ let tcx = self . tcx ;
201+ if let hir:: ItemKind :: Impl ( hir:: Impl {
202+ constness : hir:: Constness :: Const ,
203+ of_trait : Some ( trait_ref) ,
204+ ..
205+ } ) = item. kind
206+ && let Some ( def_id) = trait_ref. trait_def_id ( )
207+ {
208+ let source_map = tcx. sess . source_map ( ) ;
209+ if !tcx. has_attr ( def_id, sym:: const_trait) {
210+ tcx. sess . emit_err ( ConstImplConstTrait {
211+ span : source_map. guess_head_span ( item. span ) ,
212+ def_span : source_map. guess_head_span ( tcx. def_span ( def_id) ) ,
213+ } ) ;
214+ }
215+ }
216+ intravisit:: walk_item ( self , item) ;
217+ }
218+
194219 fn visit_anon_const ( & mut self , anon : & ' tcx hir:: AnonConst ) {
195220 let kind = Some ( hir:: ConstContext :: Const ) ;
196221 self . recurse_into ( kind, None , |this| intravisit:: walk_anon_const ( this, anon) ) ;
0 commit comments