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:: TyCtxtInferExt ;
@@ -35,11 +36,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
35
36
id : hir:: HirId ,
36
37
span : Span ,
37
38
) -> Box < Pat < ' tcx > > {
38
- let mut convert = ConstToPat :: new ( self , id, span) ;
39
+ let mut convert = ConstToPat :: new ( self , id, span, c ) ;
39
40
40
41
match c. kind ( ) {
41
42
ty:: ConstKind :: Unevaluated ( uv) => convert. unevaluated_to_pat ( uv, ty) ,
42
- ty:: ConstKind :: Value ( _, val) => convert. valtree_to_pat ( val, ty) ,
43
+ ty:: ConstKind :: Value ( _, val) => match convert. valtree_to_pat ( val, ty) {
44
+ Ok ( pat) => pat,
45
+ Err ( err) => convert. mk_err ( err, ty) ,
46
+ } ,
43
47
_ => span_bug ! ( span, "Invalid `ConstKind` for `const_to_pat`: {:?}" , c) ,
44
48
}
45
49
}
@@ -51,10 +55,12 @@ struct ConstToPat<'tcx> {
51
55
span : Span ,
52
56
53
57
treat_byte_string_as_slice : bool ,
58
+
59
+ c : ty:: Const < ' tcx > ,
54
60
}
55
61
56
62
impl < ' tcx > ConstToPat < ' tcx > {
57
- fn new ( pat_ctxt : & PatCtxt < ' _ , ' tcx > , id : hir:: HirId , span : Span ) -> Self {
63
+ fn new ( pat_ctxt : & PatCtxt < ' _ , ' tcx > , id : hir:: HirId , span : Span , c : ty :: Const < ' tcx > ) -> Self {
58
64
trace ! ( ?pat_ctxt. typeck_results. hir_owner) ;
59
65
ConstToPat {
60
66
tcx : pat_ctxt. tcx ,
@@ -64,20 +70,40 @@ impl<'tcx> ConstToPat<'tcx> {
64
70
. typeck_results
65
71
. treat_byte_string_as_slice
66
72
. contains ( & id. local_id ) ,
73
+ c,
67
74
}
68
75
}
69
76
70
77
fn type_marked_structural ( & self , ty : Ty < ' tcx > ) -> bool {
71
78
ty. is_structural_eq_shallow ( self . tcx )
72
79
}
73
80
81
+ /// We errored. Signal that in the pattern, so that follow up errors can be silenced.
82
+ fn mk_err ( & self , mut err : Diag < ' _ > , ty : Ty < ' tcx > ) -> Box < Pat < ' tcx > > {
83
+ if let ty:: ConstKind :: Unevaluated ( uv) = self . c . kind ( ) {
84
+ let def_kind = self . tcx . def_kind ( uv. def ) ;
85
+ if let hir:: def:: DefKind :: AssocConst = def_kind
86
+ && let Some ( def_id) = uv. def . as_local ( )
87
+ {
88
+ // Include the container item in the output.
89
+ err. span_label ( self . tcx . def_span ( self . tcx . local_parent ( def_id) ) , "" ) ;
90
+ }
91
+ if let hir:: def:: DefKind :: Const | hir:: def:: DefKind :: AssocConst = def_kind {
92
+ err. span_label (
93
+ self . tcx . def_span ( uv. def ) ,
94
+ crate :: fluent_generated:: mir_build_const_defined_here,
95
+ ) ;
96
+ }
97
+ }
98
+ Box :: new ( Pat { span : self . span , ty, kind : PatKind :: Error ( err. emit ( ) ) } )
99
+ }
100
+
74
101
fn unevaluated_to_pat (
75
102
& mut self ,
76
103
uv : ty:: UnevaluatedConst < ' tcx > ,
77
104
ty : Ty < ' tcx > ,
78
105
) -> Box < Pat < ' tcx > > {
79
106
trace ! ( self . treat_byte_string_as_slice) ;
80
- let pat_from_kind = |kind| Box :: new ( Pat { span : self . span , ty, kind } ) ;
81
107
82
108
// It's not *technically* correct to be revealing opaque types here as borrowcheck has
83
109
// not run yet. However, CTFE itself uses `Reveal::All` unconditionally even during
@@ -96,44 +122,46 @@ impl<'tcx> ConstToPat<'tcx> {
96
122
Ok ( Ok ( c) ) => c,
97
123
Err ( ErrorHandled :: Reported ( _, _) ) => {
98
124
// Let's tell the use where this failing const occurs.
99
- let e = self . tcx . dcx ( ) . emit_err ( CouldNotEvalConstPattern { span : self . span } ) ;
100
- return pat_from_kind ( PatKind :: Error ( e ) ) ;
125
+ let err = self . tcx . dcx ( ) . create_err ( CouldNotEvalConstPattern { span : self . span } ) ;
126
+ return self . mk_err ( err , ty ) ;
101
127
}
102
128
Err ( ErrorHandled :: TooGeneric ( _) ) => {
103
129
let e = self
104
130
. tcx
105
131
. dcx ( )
106
- . emit_err ( ConstPatternDependsOnGenericParameter { span : self . span } ) ;
107
- return pat_from_kind ( PatKind :: Error ( e ) ) ;
132
+ . create_err ( ConstPatternDependsOnGenericParameter { span : self . span } ) ;
133
+ return self . mk_err ( e , ty ) ;
108
134
}
109
135
Ok ( Err ( bad_ty) ) => {
110
136
// The pattern cannot be turned into a valtree.
111
137
let e = match bad_ty. kind ( ) {
112
138
ty:: Adt ( def, ..) => {
113
139
assert ! ( def. is_union( ) ) ;
114
- self . tcx . dcx ( ) . emit_err ( UnionPattern { span : self . span } )
140
+ self . tcx . dcx ( ) . create_err ( UnionPattern { span : self . span } )
115
141
}
116
142
ty:: FnPtr ( ..) | ty:: RawPtr ( ..) => {
117
- self . tcx . dcx ( ) . emit_err ( PointerPattern { span : self . span } )
143
+ self . tcx . dcx ( ) . create_err ( PointerPattern { span : self . span } )
118
144
}
119
145
_ => self
120
146
. tcx
121
147
. dcx ( )
122
- . emit_err ( InvalidPattern { span : self . span , non_sm_ty : bad_ty } ) ,
148
+ . create_err ( InvalidPattern { span : self . span , non_sm_ty : bad_ty } ) ,
123
149
} ;
124
- return pat_from_kind ( PatKind :: Error ( e ) ) ;
150
+ return self . mk_err ( e , ty ) ;
125
151
}
126
152
} ;
127
153
128
154
// Convert the valtree to a const.
129
- let inlined_const_as_pat = self . valtree_to_pat ( valtree, ty) ;
155
+ let inlined_const_as_pat = match self . valtree_to_pat ( valtree, ty) {
156
+ Ok ( pat) => pat,
157
+ Err ( err) => self . mk_err ( err, ty) ,
158
+ } ;
130
159
131
160
if !inlined_const_as_pat. references_error ( ) {
132
161
// Always check for `PartialEq` if we had no other errors yet.
133
162
if !self . type_has_partial_eq_impl ( ty) {
134
163
let err = TypeNotPartialEq { span : self . span , non_peq_ty : ty } ;
135
- let e = self . tcx . dcx ( ) . emit_err ( err) ;
136
- return pat_from_kind ( PatKind :: Error ( e) ) ;
164
+ return self . mk_err ( self . tcx . dcx ( ) . create_err ( err) , ty) ;
137
165
}
138
166
}
139
167
@@ -175,14 +203,20 @@ impl<'tcx> ConstToPat<'tcx> {
175
203
let field = FieldIdx :: new ( idx) ;
176
204
// Patterns can only use monomorphic types.
177
205
let ty = self . tcx . normalize_erasing_regions ( self . typing_env , ty) ;
178
- FieldPat { field, pattern : self . valtree_to_pat ( val, ty) }
206
+ FieldPat {
207
+ field,
208
+ pattern : match self . valtree_to_pat ( val, ty) {
209
+ Ok ( pat) => pat,
210
+ Err ( err) => self . mk_err ( err, ty) ,
211
+ } ,
212
+ }
179
213
} )
180
214
. collect ( )
181
215
}
182
216
183
217
// Recursive helper for `to_pat`; invoke that (instead of calling this directly).
184
218
#[ instrument( skip( self ) , level = "debug" ) ]
185
- fn valtree_to_pat ( & self , cv : ValTree < ' tcx > , ty : Ty < ' tcx > ) -> Box < Pat < ' tcx > > {
219
+ fn valtree_to_pat ( & self , cv : ValTree < ' tcx > , ty : Ty < ' tcx > ) -> PResult < ' _ , Box < Pat < ' tcx > > > {
186
220
let span = self . span ;
187
221
let tcx = self . tcx ;
188
222
let kind = match ty. kind ( ) {
@@ -191,9 +225,7 @@ impl<'tcx> ConstToPat<'tcx> {
191
225
// patterns.
192
226
debug ! ( "adt_def {:?} has !type_marked_structural for cv.ty: {:?}" , adt_def, ty) ;
193
227
let err = TypeNotStructural { span, non_sm_ty : ty } ;
194
- let e = tcx. dcx ( ) . emit_err ( err) ;
195
- // We errored. Signal that in the pattern, so that follow up errors can be silenced.
196
- PatKind :: Error ( e)
228
+ return Err ( tcx. dcx ( ) . create_err ( err) ) ;
197
229
}
198
230
ty:: Adt ( adt_def, args) if adt_def. is_enum ( ) => {
199
231
let ( & variant_index, fields) = cv. unwrap_branch ( ) . split_first ( ) . unwrap ( ) ;
@@ -227,7 +259,10 @@ impl<'tcx> ConstToPat<'tcx> {
227
259
prefix : cv
228
260
. unwrap_branch ( )
229
261
. iter ( )
230
- . map ( |val| self . valtree_to_pat ( * val, * elem_ty) )
262
+ . map ( |val| match self . valtree_to_pat ( * val, * elem_ty) {
263
+ Ok ( pat) => pat,
264
+ Err ( err) => self . mk_err ( err, ty) ,
265
+ } )
231
266
. collect ( ) ,
232
267
slice : None ,
233
268
suffix : Box :: new ( [ ] ) ,
@@ -236,7 +271,10 @@ impl<'tcx> ConstToPat<'tcx> {
236
271
prefix : cv
237
272
. unwrap_branch ( )
238
273
. iter ( )
239
- . map ( |val| self . valtree_to_pat ( * val, * elem_ty) )
274
+ . map ( |val| match self . valtree_to_pat ( * val, * elem_ty) {
275
+ Ok ( pat) => pat,
276
+ Err ( err) => self . mk_err ( err, ty) ,
277
+ } )
240
278
. collect ( ) ,
241
279
slice : None ,
242
280
suffix : Box :: new ( [ ] ) ,
@@ -252,10 +290,9 @@ impl<'tcx> ConstToPat<'tcx> {
252
290
// deref pattern.
253
291
_ => {
254
292
if !pointee_ty. is_sized ( tcx, self . typing_env ) && !pointee_ty. is_slice ( ) {
255
- let err = UnsizedPattern { span, non_sm_ty : * pointee_ty } ;
256
- let e = tcx. dcx ( ) . emit_err ( err) ;
257
- // We errored. Signal that in the pattern, so that follow up errors can be silenced.
258
- PatKind :: Error ( e)
293
+ return Err ( tcx
294
+ . dcx ( )
295
+ . create_err ( UnsizedPattern { span, non_sm_ty : * pointee_ty } ) ) ;
259
296
} else {
260
297
// `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
261
298
// matching against references, you can only use byte string literals.
@@ -270,7 +307,10 @@ impl<'tcx> ConstToPat<'tcx> {
270
307
_ => * pointee_ty,
271
308
} ;
272
309
// References have the same valtree representation as their pointee.
273
- let subpattern = self . valtree_to_pat ( cv, pointee_ty) ;
310
+ let subpattern = match self . valtree_to_pat ( cv, pointee_ty) {
311
+ Ok ( pat) => pat,
312
+ Err ( err) => self . mk_err ( err, ty) ,
313
+ } ;
274
314
PatKind :: Deref { subpattern }
275
315
}
276
316
}
@@ -286,8 +326,7 @@ impl<'tcx> ConstToPat<'tcx> {
286
326
if is_nan {
287
327
// NaNs are not ever equal to anything so they make no sense as patterns.
288
328
// Also see <https://github.com/rust-lang/rfcs/pull/3535>.
289
- let e = tcx. dcx ( ) . emit_err ( NaNPattern { span } ) ;
290
- PatKind :: Error ( e)
329
+ return Err ( tcx. dcx ( ) . create_err ( NaNPattern { span } ) ) ;
291
330
} else {
292
331
PatKind :: Constant {
293
332
value : mir:: Const :: Ty ( ty, ty:: Const :: new_value ( tcx, cv, ty) ) ,
@@ -306,12 +345,10 @@ impl<'tcx> ConstToPat<'tcx> {
306
345
}
307
346
_ => {
308
347
let err = InvalidPattern { span, non_sm_ty : ty } ;
309
- let e = tcx. dcx ( ) . emit_err ( err) ;
310
- // We errored. Signal that in the pattern, so that follow up errors can be silenced.
311
- PatKind :: Error ( e)
348
+ return Err ( tcx. dcx ( ) . create_err ( err) ) ;
312
349
}
313
350
} ;
314
351
315
- Box :: new ( Pat { span, ty, kind } )
352
+ Ok ( Box :: new ( Pat { span, ty, kind } ) )
316
353
}
317
354
}
0 commit comments