11use rustc_abi:: { FieldIdx , VariantIdx } ;
22use rustc_apfloat:: Float ;
3+ use rustc_errors:: { Diag , PResult } ;
34use rustc_hir as hir;
45use rustc_index:: Idx ;
56use rustc_infer:: infer:: TyCtxtInferExt ;
@@ -35,11 +36,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
3536 id : hir:: HirId ,
3637 span : Span ,
3738 ) -> Box < Pat < ' tcx > > {
38- let mut convert = ConstToPat :: new ( self , id, span) ;
39+ let mut convert = ConstToPat :: new ( self , id, span, c ) ;
3940
4041 match c. kind ( ) {
4142 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+ } ,
4347 _ => span_bug ! ( span, "Invalid `ConstKind` for `const_to_pat`: {:?}" , c) ,
4448 }
4549 }
@@ -51,10 +55,12 @@ struct ConstToPat<'tcx> {
5155 span : Span ,
5256
5357 treat_byte_string_as_slice : bool ,
58+
59+ c : ty:: Const < ' tcx > ,
5460}
5561
5662impl < ' 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 {
5864 trace ! ( ?pat_ctxt. typeck_results. hir_owner) ;
5965 ConstToPat {
6066 tcx : pat_ctxt. tcx ,
@@ -64,20 +70,40 @@ impl<'tcx> ConstToPat<'tcx> {
6470 . typeck_results
6571 . treat_byte_string_as_slice
6672 . contains ( & id. local_id ) ,
73+ c,
6774 }
6875 }
6976
7077 fn type_marked_structural ( & self , ty : Ty < ' tcx > ) -> bool {
7178 ty. is_structural_eq_shallow ( self . tcx )
7279 }
7380
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+
74101 fn unevaluated_to_pat (
75102 & mut self ,
76103 uv : ty:: UnevaluatedConst < ' tcx > ,
77104 ty : Ty < ' tcx > ,
78105 ) -> Box < Pat < ' tcx > > {
79106 trace ! ( self . treat_byte_string_as_slice) ;
80- let pat_from_kind = |kind| Box :: new ( Pat { span : self . span , ty, kind } ) ;
81107
82108 // It's not *technically* correct to be revealing opaque types here as borrowcheck has
83109 // not run yet. However, CTFE itself uses `TypingMode::PostAnalysis` unconditionally even
@@ -96,44 +122,46 @@ impl<'tcx> ConstToPat<'tcx> {
96122 Ok ( Ok ( c) ) => c,
97123 Err ( ErrorHandled :: Reported ( _, _) ) => {
98124 // 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 ) ;
101127 }
102128 Err ( ErrorHandled :: TooGeneric ( _) ) => {
103129 let e = self
104130 . tcx
105131 . 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 ) ;
108134 }
109135 Ok ( Err ( bad_ty) ) => {
110136 // The pattern cannot be turned into a valtree.
111137 let e = match bad_ty. kind ( ) {
112138 ty:: Adt ( def, ..) => {
113139 assert ! ( def. is_union( ) ) ;
114- self . tcx . dcx ( ) . emit_err ( UnionPattern { span : self . span } )
140+ self . tcx . dcx ( ) . create_err ( UnionPattern { span : self . span } )
115141 }
116142 ty:: FnPtr ( ..) | ty:: RawPtr ( ..) => {
117- self . tcx . dcx ( ) . emit_err ( PointerPattern { span : self . span } )
143+ self . tcx . dcx ( ) . create_err ( PointerPattern { span : self . span } )
118144 }
119145 _ => self
120146 . tcx
121147 . 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 } ) ,
123149 } ;
124- return pat_from_kind ( PatKind :: Error ( e ) ) ;
150+ return self . mk_err ( e , ty ) ;
125151 }
126152 } ;
127153
128154 // 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+ } ;
130159
131160 if !inlined_const_as_pat. references_error ( ) {
132161 // Always check for `PartialEq` if we had no other errors yet.
133162 if !self . type_has_partial_eq_impl ( ty) {
134163 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) ;
137165 }
138166 }
139167
@@ -175,14 +203,20 @@ impl<'tcx> ConstToPat<'tcx> {
175203 let field = FieldIdx :: new ( idx) ;
176204 // Patterns can only use monomorphic types.
177205 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+ }
179213 } )
180214 . collect ( )
181215 }
182216
183217 // Recursive helper for `to_pat`; invoke that (instead of calling this directly).
184218 #[ 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 > > > {
186220 let span = self . span ;
187221 let tcx = self . tcx ;
188222 let kind = match ty. kind ( ) {
@@ -191,9 +225,7 @@ impl<'tcx> ConstToPat<'tcx> {
191225 // patterns.
192226 debug ! ( "adt_def {:?} has !type_marked_structural for cv.ty: {:?}" , adt_def, ty) ;
193227 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) ) ;
197229 }
198230 ty:: Adt ( adt_def, args) if adt_def. is_enum ( ) => {
199231 let ( & variant_index, fields) = cv. unwrap_branch ( ) . split_first ( ) . unwrap ( ) ;
@@ -227,7 +259,10 @@ impl<'tcx> ConstToPat<'tcx> {
227259 prefix : cv
228260 . unwrap_branch ( )
229261 . 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+ } )
231266 . collect ( ) ,
232267 slice : None ,
233268 suffix : Box :: new ( [ ] ) ,
@@ -236,7 +271,10 @@ impl<'tcx> ConstToPat<'tcx> {
236271 prefix : cv
237272 . unwrap_branch ( )
238273 . 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+ } )
240278 . collect ( ) ,
241279 slice : None ,
242280 suffix : Box :: new ( [ ] ) ,
@@ -252,10 +290,9 @@ impl<'tcx> ConstToPat<'tcx> {
252290 // deref pattern.
253291 _ => {
254292 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 } ) ) ;
259296 } else {
260297 // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
261298 // matching against references, you can only use byte string literals.
@@ -270,7 +307,10 @@ impl<'tcx> ConstToPat<'tcx> {
270307 _ => * pointee_ty,
271308 } ;
272309 // 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+ } ;
274314 PatKind :: Deref { subpattern }
275315 }
276316 }
@@ -286,8 +326,7 @@ impl<'tcx> ConstToPat<'tcx> {
286326 if is_nan {
287327 // NaNs are not ever equal to anything so they make no sense as patterns.
288328 // 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 } ) ) ;
291330 } else {
292331 PatKind :: Constant {
293332 value : mir:: Const :: Ty ( ty, ty:: Const :: new_value ( tcx, cv, ty) ) ,
@@ -306,12 +345,10 @@ impl<'tcx> ConstToPat<'tcx> {
306345 }
307346 _ => {
308347 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) ) ;
312349 }
313350 } ;
314351
315- Box :: new ( Pat { span, ty, kind } )
352+ Ok ( Box :: new ( Pat { span, ty, kind } ) )
316353 }
317354}
0 commit comments