@@ -12,7 +12,9 @@ use rustc_infer::traits::Obligation;
1212use rustc_middle:: mir:: interpret:: ErrorHandled ;
1313use rustc_middle:: span_bug;
1414use rustc_middle:: thir:: { FieldPat , Pat , PatKind } ;
15- use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeSuperVisitable , TypeVisitableExt , TypeVisitor } ;
15+ use rustc_middle:: ty:: {
16+ self , Ty , TyCtxt , TypeSuperVisitable , TypeVisitableExt , TypeVisitor , Unnormalized ,
17+ } ;
1618use rustc_span:: def_id:: DefId ;
1719use rustc_span:: { DUMMY_SP , Span } ;
1820use rustc_trait_selection:: traits:: ObligationCause ;
@@ -106,72 +108,92 @@ impl<'tcx> ConstToPat<'tcx> {
106108 self . tcx . erase_and_anonymize_regions ( self . typing_env ) . with_codegen_normalized ( self . tcx ) ;
107109 let uv = self . tcx . erase_and_anonymize_regions ( uv) ;
108110
109- // try to resolve e.g. associated constants to their definition on an impl, and then
110- // evaluate the const.
111- let valtree = match self . tcx . const_eval_resolve_for_typeck ( typing_env, uv, self . span ) {
112- Ok ( Ok ( c) ) => c,
113- Err ( ErrorHandled :: Reported ( _, _) ) => {
114- // Let's tell the use where this failing const occurs.
115- let mut err =
116- self . tcx . dcx ( ) . create_err ( CouldNotEvalConstPattern { span : self . span } ) ;
117- // We've emitted an error on the original const, it would be redundant to complain
118- // on its use as well.
119- if let ty:: ConstKind :: Unevaluated ( uv) = self . c . kind ( )
120- && let ty:: UnevaluatedConstKind :: Projection { .. }
121- | ty:: UnevaluatedConstKind :: Inherent { .. }
122- | ty:: UnevaluatedConstKind :: Free { .. } = uv. kind
123- {
124- err. downgrade_to_delayed_bug ( ) ;
125- }
111+ // FIXME(gca): This will become insufficient once associated constants can be
112+ // implemented as `type` consts (project-const-generics#76). At that point it'll
113+ // become necessary to just use type system normalization for all const patterns
114+ // but that's not yet possible.
115+ let mut thir_pat = if uv. kind . is_type_const ( self . tcx ) {
116+ let Ok ( normalize) = self
117+ . tcx
118+ . try_normalize_erasing_regions ( self . typing_env , Unnormalized :: new_wip ( self . c ) )
119+ else {
120+ let err = self . tcx . dcx ( ) . create_err ( CouldNotEvalConstPattern { span : self . span } ) ;
126121 return self . mk_err ( err, ty) ;
127- }
128- Err ( ErrorHandled :: TooGeneric ( _) ) => {
129- let mut e = self
130- . tcx
131- . dcx ( )
132- . create_err ( ConstPatternDependsOnGenericParameter { span : self . span } ) ;
133- for arg in uv. args {
134- if let ty:: GenericArgKind :: Type ( ty) = arg. kind ( )
135- && let ty:: Param ( param_ty) = ty. kind ( )
122+ } ;
123+
124+ let ty:: ConstKind :: Value ( value) = normalize. kind ( ) else {
125+ let err = self . tcx . dcx ( ) . create_err ( CouldNotEvalConstPattern { span : self . span } ) ;
126+ return self . mk_err ( err, ty) ;
127+ } ;
128+ self . valtree_to_pat ( value)
129+ } else {
130+ // try to resolve e.g. associated constants to their definition on an impl, and then
131+ // evaluate the const.
132+ let valtree = match self . tcx . const_eval_resolve_for_typeck ( typing_env, uv, self . span ) {
133+ Ok ( Ok ( c) ) => c,
134+ Err ( ErrorHandled :: Reported ( _, _) ) => {
135+ // Let's tell the use where this failing const occurs.
136+ let mut err =
137+ self . tcx . dcx ( ) . create_err ( CouldNotEvalConstPattern { span : self . span } ) ;
138+ // We've emitted an error on the original const, it would be redundant to complain
139+ // on its use as well.
140+ if let ty:: ConstKind :: Unevaluated ( uv) = self . c . kind ( )
141+ && let ty:: UnevaluatedConstKind :: Projection { .. }
142+ | ty:: UnevaluatedConstKind :: Inherent { .. }
143+ | ty:: UnevaluatedConstKind :: Free { .. } = uv. kind
136144 {
137- let def_id = self . tcx . hir_enclosing_body_owner ( self . id ) ;
138- let generics = self . tcx . generics_of ( def_id) ;
139- let param = generics. type_param ( * param_ty, self . tcx ) ;
140- let span = self . tcx . def_span ( param. def_id ) ;
141- e. span_label ( span, "constant depends on this generic parameter" ) ;
142- if let Some ( ident) = self . tcx . def_ident_span ( def_id)
143- && self . tcx . sess . source_map ( ) . is_multiline ( ident. between ( span) )
145+ err. downgrade_to_delayed_bug ( ) ;
146+ }
147+ return self . mk_err ( err, ty) ;
148+ }
149+ Err ( ErrorHandled :: TooGeneric ( _) ) => {
150+ let mut e = self
151+ . tcx
152+ . dcx ( )
153+ . create_err ( ConstPatternDependsOnGenericParameter { span : self . span } ) ;
154+ for arg in uv. args {
155+ if let ty:: GenericArgKind :: Type ( ty) = arg. kind ( )
156+ && let ty:: Param ( param_ty) = ty. kind ( )
144157 {
145- // Display the `fn` name as well in the diagnostic, as the generic isn't
146- // in the same line and it could be confusing otherwise.
147- e. span_label ( ident, "" ) ;
158+ let def_id = self . tcx . hir_enclosing_body_owner ( self . id ) ;
159+ let generics = self . tcx . generics_of ( def_id) ;
160+ let param = generics. type_param ( * param_ty, self . tcx ) ;
161+ let span = self . tcx . def_span ( param. def_id ) ;
162+ e. span_label ( span, "constant depends on this generic parameter" ) ;
163+ if let Some ( ident) = self . tcx . def_ident_span ( def_id)
164+ && self . tcx . sess . source_map ( ) . is_multiline ( ident. between ( span) )
165+ {
166+ // Display the `fn` name as well in the diagnostic, as the generic isn't
167+ // in the same line and it could be confusing otherwise.
168+ e. span_label ( ident, "" ) ;
169+ }
148170 }
149171 }
172+ return self . mk_err ( e, ty) ;
150173 }
151- return self . mk_err ( e, ty) ;
152- }
153- Ok ( Err ( bad_ty) ) => {
154- // The pattern cannot be turned into a valtree.
155- let e = match bad_ty. kind ( ) {
156- ty:: Adt ( def, ..) => {
157- assert ! ( def. is_union( ) ) ;
158- self . tcx . dcx ( ) . create_err ( UnionPattern { span : self . span } )
159- }
160- ty:: FnPtr ( ..) | ty:: RawPtr ( ..) => {
161- self . tcx . dcx ( ) . create_err ( PointerPattern { span : self . span } )
162- }
163- _ => self . tcx . dcx ( ) . create_err ( InvalidPattern {
164- span : self . span ,
165- non_sm_ty : bad_ty,
166- prefix : bad_ty. prefix_string ( self . tcx ) . to_string ( ) ,
167- } ) ,
168- } ;
169- return self . mk_err ( e, ty) ;
170- }
171- } ;
174+ Ok ( Err ( bad_ty) ) => {
175+ // The pattern cannot be turned into a valtree.
176+ let e = match bad_ty. kind ( ) {
177+ ty:: Adt ( def, ..) => {
178+ assert ! ( def. is_union( ) ) ;
179+ self . tcx . dcx ( ) . create_err ( UnionPattern { span : self . span } )
180+ }
181+ ty:: FnPtr ( ..) | ty:: RawPtr ( ..) => {
182+ self . tcx . dcx ( ) . create_err ( PointerPattern { span : self . span } )
183+ }
184+ _ => self . tcx . dcx ( ) . create_err ( InvalidPattern {
185+ span : self . span ,
186+ non_sm_ty : bad_ty,
187+ prefix : bad_ty. prefix_string ( self . tcx ) . to_string ( ) ,
188+ } ) ,
189+ } ;
190+ return self . mk_err ( e, ty) ;
191+ }
192+ } ;
172193
173- // Lower the valtree to a THIR pattern.
174- let mut thir_pat = self . valtree_to_pat ( ty:: Value { ty, valtree } ) ;
194+ // Lower the valtree to a THIR pattern.
195+ self . valtree_to_pat ( ty:: Value { ty, valtree } )
196+ } ;
175197
176198 if !thir_pat. references_error ( ) {
177199 // Always check for `PartialEq` if we had no other errors yet.
0 commit comments