1
1
use rustc_abi:: { FieldIdx , VariantIdx } ;
2
2
use rustc_apfloat:: Float ;
3
+ use rustc_errors:: { Diag , PResult } ;
3
4
use rustc_hir as hir;
4
5
use rustc_index:: Idx ;
5
6
use rustc_infer:: infer:: { InferCtxt , TyCtxtInferExt } ;
@@ -38,11 +39,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
38
39
// FIXME(#132279): We likely want to be able to reveal the hidden types
39
40
// of opaques defined in this function here.
40
41
let infcx = self . tcx . infer_ctxt ( ) . build ( TypingMode :: non_body_analysis ( ) ) ;
41
- let mut convert = ConstToPat :: new ( self , id, span, infcx) ;
42
+ let mut convert = ConstToPat :: new ( self , id, span, infcx, c ) ;
42
43
43
44
match c. kind ( ) {
44
45
ty:: ConstKind :: Unevaluated ( uv) => convert. unevaluated_to_pat ( uv, ty) ,
45
- ty:: ConstKind :: Value ( _, val) => convert. valtree_to_pat ( val, ty) ,
46
+ ty:: ConstKind :: Value ( _, val) => match convert. valtree_to_pat ( val, ty) {
47
+ Ok ( pat) => pat,
48
+ Err ( err) => convert. mk_err ( err, ty) ,
49
+ } ,
46
50
_ => span_bug ! ( span, "Invalid `ConstKind` for `const_to_pat`: {:?}" , c) ,
47
51
}
48
52
}
@@ -56,6 +60,8 @@ struct ConstToPat<'tcx> {
56
60
param_env : ty:: ParamEnv < ' tcx > ,
57
61
58
62
treat_byte_string_as_slice : bool ,
63
+
64
+ c : ty:: Const < ' tcx > ,
59
65
}
60
66
61
67
impl < ' tcx > ConstToPat < ' tcx > {
@@ -64,6 +70,7 @@ impl<'tcx> ConstToPat<'tcx> {
64
70
id : hir:: HirId ,
65
71
span : Span ,
66
72
infcx : InferCtxt < ' tcx > ,
73
+ c : ty:: Const < ' tcx > ,
67
74
) -> Self {
68
75
trace ! ( ?pat_ctxt. typeck_results. hir_owner) ;
69
76
ConstToPat {
@@ -74,6 +81,7 @@ impl<'tcx> ConstToPat<'tcx> {
74
81
. typeck_results
75
82
. treat_byte_string_as_slice
76
83
. contains ( & id. local_id ) ,
84
+ c,
77
85
}
78
86
}
79
87
@@ -89,13 +97,32 @@ impl<'tcx> ConstToPat<'tcx> {
89
97
ty. is_structural_eq_shallow ( self . infcx . tcx )
90
98
}
91
99
100
+ /// We errored. Signal that in the pattern, so that follow up errors can be silenced.
101
+ fn mk_err ( & self , mut err : Diag < ' _ > , ty : Ty < ' tcx > ) -> Box < Pat < ' tcx > > {
102
+ if let ty:: ConstKind :: Unevaluated ( uv) = self . c . kind ( ) {
103
+ let def_kind = self . tcx ( ) . def_kind ( uv. def ) ;
104
+ if let hir:: def:: DefKind :: AssocConst = def_kind
105
+ && let Some ( def_id) = uv. def . as_local ( )
106
+ {
107
+ // Include the container item in the output.
108
+ err. span_label ( self . tcx ( ) . def_span ( self . tcx ( ) . local_parent ( def_id) ) , "" ) ;
109
+ }
110
+ if let hir:: def:: DefKind :: Const | hir:: def:: DefKind :: AssocConst = def_kind {
111
+ err. span_label (
112
+ self . tcx ( ) . def_span ( uv. def ) ,
113
+ crate :: fluent_generated:: mir_build_const_defined_here,
114
+ ) ;
115
+ }
116
+ }
117
+ Box :: new ( Pat { span : self . span , ty, kind : PatKind :: Error ( err. emit ( ) ) } )
118
+ }
119
+
92
120
fn unevaluated_to_pat (
93
121
& mut self ,
94
122
uv : ty:: UnevaluatedConst < ' tcx > ,
95
123
ty : Ty < ' tcx > ,
96
124
) -> Box < Pat < ' tcx > > {
97
125
trace ! ( self . treat_byte_string_as_slice) ;
98
- let pat_from_kind = |kind| Box :: new ( Pat { span : self . span , ty, kind } ) ;
99
126
100
127
// It's not *technically* correct to be revealing opaque types here as borrowcheck has
101
128
// not run yet. However, CTFE itself uses `Reveal::All` unconditionally even during
@@ -115,44 +142,46 @@ impl<'tcx> ConstToPat<'tcx> {
115
142
Ok ( Ok ( c) ) => c,
116
143
Err ( ErrorHandled :: Reported ( _, _) ) => {
117
144
// Let's tell the use where this failing const occurs.
118
- let e = self . tcx ( ) . dcx ( ) . emit_err ( CouldNotEvalConstPattern { span : self . span } ) ;
119
- return pat_from_kind ( PatKind :: Error ( e ) ) ;
145
+ let err = self . tcx ( ) . dcx ( ) . create_err ( CouldNotEvalConstPattern { span : self . span } ) ;
146
+ return self . mk_err ( err , ty ) ;
120
147
}
121
148
Err ( ErrorHandled :: TooGeneric ( _) ) => {
122
149
let e = self
123
150
. tcx ( )
124
151
. dcx ( )
125
- . emit_err ( ConstPatternDependsOnGenericParameter { span : self . span } ) ;
126
- return pat_from_kind ( PatKind :: Error ( e ) ) ;
152
+ . create_err ( ConstPatternDependsOnGenericParameter { span : self . span } ) ;
153
+ return self . mk_err ( e , ty ) ;
127
154
}
128
155
Ok ( Err ( bad_ty) ) => {
129
156
// The pattern cannot be turned into a valtree.
130
157
let e = match bad_ty. kind ( ) {
131
158
ty:: Adt ( def, ..) => {
132
159
assert ! ( def. is_union( ) ) ;
133
- self . tcx ( ) . dcx ( ) . emit_err ( UnionPattern { span : self . span } )
160
+ self . tcx ( ) . dcx ( ) . create_err ( UnionPattern { span : self . span } )
134
161
}
135
162
ty:: FnPtr ( ..) | ty:: RawPtr ( ..) => {
136
- self . tcx ( ) . dcx ( ) . emit_err ( PointerPattern { span : self . span } )
163
+ self . tcx ( ) . dcx ( ) . create_err ( PointerPattern { span : self . span } )
137
164
}
138
165
_ => self
139
166
. tcx ( )
140
167
. dcx ( )
141
- . emit_err ( InvalidPattern { span : self . span , non_sm_ty : bad_ty } ) ,
168
+ . create_err ( InvalidPattern { span : self . span , non_sm_ty : bad_ty } ) ,
142
169
} ;
143
- return pat_from_kind ( PatKind :: Error ( e ) ) ;
170
+ return self . mk_err ( e , ty ) ;
144
171
}
145
172
} ;
146
173
147
174
// Convert the valtree to a const.
148
- let inlined_const_as_pat = self . valtree_to_pat ( valtree, ty) ;
175
+ let inlined_const_as_pat = match self . valtree_to_pat ( valtree, ty) {
176
+ Ok ( pat) => pat,
177
+ Err ( err) => self . mk_err ( err, ty) ,
178
+ } ;
149
179
150
180
if !inlined_const_as_pat. references_error ( ) {
151
181
// Always check for `PartialEq` if we had no other errors yet.
152
182
if !self . type_has_partial_eq_impl ( ty) {
153
183
let err = TypeNotPartialEq { span : self . span , non_peq_ty : ty } ;
154
- let e = self . tcx ( ) . dcx ( ) . emit_err ( err) ;
155
- return pat_from_kind ( PatKind :: Error ( e) ) ;
184
+ return self . mk_err ( self . tcx ( ) . dcx ( ) . create_err ( err) , ty) ;
156
185
}
157
186
}
158
187
@@ -193,14 +222,20 @@ impl<'tcx> ConstToPat<'tcx> {
193
222
let field = FieldIdx :: new ( idx) ;
194
223
// Patterns can only use monomorphic types.
195
224
let ty = self . tcx ( ) . normalize_erasing_regions ( self . typing_env ( ) , ty) ;
196
- FieldPat { field, pattern : self . valtree_to_pat ( val, ty) }
225
+ FieldPat {
226
+ field,
227
+ pattern : match self . valtree_to_pat ( val, ty) {
228
+ Ok ( pat) => pat,
229
+ Err ( err) => self . mk_err ( err, ty) ,
230
+ } ,
231
+ }
197
232
} )
198
233
. collect ( )
199
234
}
200
235
201
236
// Recursive helper for `to_pat`; invoke that (instead of calling this directly).
202
237
#[ instrument( skip( self ) , level = "debug" ) ]
203
- fn valtree_to_pat ( & self , cv : ValTree < ' tcx > , ty : Ty < ' tcx > ) -> Box < Pat < ' tcx > > {
238
+ fn valtree_to_pat ( & self , cv : ValTree < ' tcx > , ty : Ty < ' tcx > ) -> PResult < ' _ , Box < Pat < ' tcx > > > {
204
239
let span = self . span ;
205
240
let tcx = self . tcx ( ) ;
206
241
let param_env = self . param_env ;
@@ -211,9 +246,7 @@ impl<'tcx> ConstToPat<'tcx> {
211
246
// patterns.
212
247
debug ! ( "adt_def {:?} has !type_marked_structural for cv.ty: {:?}" , adt_def, ty, ) ;
213
248
let err = TypeNotStructural { span, non_sm_ty : ty } ;
214
- let e = tcx. dcx ( ) . emit_err ( err) ;
215
- // We errored. Signal that in the pattern, so that follow up errors can be silenced.
216
- PatKind :: Error ( e)
249
+ return Err ( tcx. dcx ( ) . create_err ( err) ) ;
217
250
}
218
251
ty:: Adt ( adt_def, args) if adt_def. is_enum ( ) => {
219
252
let ( & variant_index, fields) = cv. unwrap_branch ( ) . split_first ( ) . unwrap ( ) ;
@@ -252,7 +285,10 @@ impl<'tcx> ConstToPat<'tcx> {
252
285
prefix : cv
253
286
. unwrap_branch ( )
254
287
. iter ( )
255
- . map ( |val| self . valtree_to_pat ( * val, * elem_ty) )
288
+ . map ( |val| match self . valtree_to_pat ( * val, * elem_ty) {
289
+ Ok ( pat) => pat,
290
+ Err ( err) => self . mk_err ( err, ty) ,
291
+ } )
256
292
. collect ( ) ,
257
293
slice : None ,
258
294
suffix : Box :: new ( [ ] ) ,
@@ -261,7 +297,10 @@ impl<'tcx> ConstToPat<'tcx> {
261
297
prefix : cv
262
298
. unwrap_branch ( )
263
299
. iter ( )
264
- . map ( |val| self . valtree_to_pat ( * val, * elem_ty) )
300
+ . map ( |val| match self . valtree_to_pat ( * val, * elem_ty) {
301
+ Ok ( pat) => pat,
302
+ Err ( err) => self . mk_err ( err, ty) ,
303
+ } )
265
304
. collect ( ) ,
266
305
slice : None ,
267
306
suffix : Box :: new ( [ ] ) ,
@@ -277,10 +316,9 @@ impl<'tcx> ConstToPat<'tcx> {
277
316
// deref pattern.
278
317
_ => {
279
318
if !pointee_ty. is_sized ( tcx, param_env) && !pointee_ty. is_slice ( ) {
280
- let err = UnsizedPattern { span, non_sm_ty : * pointee_ty } ;
281
- let e = tcx. dcx ( ) . emit_err ( err) ;
282
- // We errored. Signal that in the pattern, so that follow up errors can be silenced.
283
- PatKind :: Error ( e)
319
+ return Err ( tcx
320
+ . dcx ( )
321
+ . create_err ( UnsizedPattern { span, non_sm_ty : * pointee_ty } ) ) ;
284
322
} else {
285
323
// `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
286
324
// matching against references, you can only use byte string literals.
@@ -295,7 +333,10 @@ impl<'tcx> ConstToPat<'tcx> {
295
333
_ => * pointee_ty,
296
334
} ;
297
335
// References have the same valtree representation as their pointee.
298
- let subpattern = self . valtree_to_pat ( cv, pointee_ty) ;
336
+ let subpattern = match self . valtree_to_pat ( cv, pointee_ty) {
337
+ Ok ( pat) => pat,
338
+ Err ( err) => self . mk_err ( err, ty) ,
339
+ } ;
299
340
PatKind :: Deref { subpattern }
300
341
}
301
342
}
@@ -311,8 +352,7 @@ impl<'tcx> ConstToPat<'tcx> {
311
352
if is_nan {
312
353
// NaNs are not ever equal to anything so they make no sense as patterns.
313
354
// Also see <https://github.com/rust-lang/rfcs/pull/3535>.
314
- let e = tcx. dcx ( ) . emit_err ( NaNPattern { span } ) ;
315
- PatKind :: Error ( e)
355
+ return Err ( tcx. dcx ( ) . create_err ( NaNPattern { span } ) ) ;
316
356
} else {
317
357
PatKind :: Constant {
318
358
value : mir:: Const :: Ty ( ty, ty:: Const :: new_value ( tcx, cv, ty) ) ,
@@ -331,12 +371,10 @@ impl<'tcx> ConstToPat<'tcx> {
331
371
}
332
372
_ => {
333
373
let err = InvalidPattern { span, non_sm_ty : ty } ;
334
- let e = tcx. dcx ( ) . emit_err ( err) ;
335
- // We errored. Signal that in the pattern, so that follow up errors can be silenced.
336
- PatKind :: Error ( e)
374
+ return Err ( tcx. dcx ( ) . create_err ( err) ) ;
337
375
}
338
376
} ;
339
377
340
- Box :: new ( Pat { span, ty, kind } )
378
+ Ok ( Box :: new ( Pat { span, ty, kind } ) )
341
379
}
342
380
}
0 commit comments