8
8
//! through, but errors for structured control flow in a `const` should be emitted here.
9
9
10
10
use rustc_attr as attr;
11
- use rustc_errors:: struct_span_err;
12
11
use rustc_hir as hir;
13
12
use rustc_hir:: def_id:: LocalDefId ;
14
13
use rustc_hir:: intravisit:: { self , Visitor } ;
@@ -18,6 +17,8 @@ use rustc_middle::ty::TyCtxt;
18
17
use rustc_session:: parse:: feature_err;
19
18
use rustc_span:: { sym, Span , Symbol } ;
20
19
20
+ use crate :: errors:: { ConstImplConstTrait , ExprNotAllowedInContext } ;
21
+
21
22
/// An expression that is not *always* legal in a const context.
22
23
#[ derive( Clone , Copy ) ]
23
24
enum NonConstExpr {
@@ -133,18 +134,22 @@ impl<'tcx> CheckConstVisitor<'tcx> {
133
134
let const_kind =
134
135
const_kind. expect ( "`const_check_violated` may only be called inside a const context" ) ;
135
136
136
- let msg = format ! ( "{} is not allowed in a `{}`" , expr. name( ) , const_kind. keyword_name( ) ) ;
137
-
138
137
let required_gates = required_gates. unwrap_or ( & [ ] ) ;
139
138
let missing_gates: Vec < _ > =
140
139
required_gates. iter ( ) . copied ( ) . filter ( |& g| !features. enabled ( g) ) . collect ( ) ;
141
140
142
141
match missing_gates. as_slice ( ) {
143
142
[ ] => {
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
+ } ) ;
145
148
}
146
149
147
150
[ missing_primary, ref missing_secondary @ ..] => {
151
+ let msg =
152
+ format ! ( "{} is not allowed in a `{}`" , expr. name( ) , const_kind. keyword_name( ) ) ;
148
153
let mut err = feature_err ( & tcx. sess . parse_sess , * missing_primary, span, & msg) ;
149
154
150
155
// If multiple feature gates would be required to enable this expression, include
@@ -191,6 +196,26 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
191
196
self . tcx . hir ( )
192
197
}
193
198
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
+
194
219
fn visit_anon_const ( & mut self , anon : & ' tcx hir:: AnonConst ) {
195
220
let kind = Some ( hir:: ConstContext :: Const ) ;
196
221
self . recurse_into ( kind, None , |this| intravisit:: walk_anon_const ( this, anon) ) ;
0 commit comments