@@ -128,7 +128,7 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) {
128128
129129    if  let  Some ( generics)  = node. generics ( )  { 
130130        for  param in  generics. params  { 
131-             check_param_wf ( tcx,  param) 
131+             check_param_wf ( tcx,  param,  def_id . def_id ) 
132132        } 
133133    } 
134134} 
@@ -846,140 +846,136 @@ fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) {
846846    check_associated_item ( tcx,  impl_item. owner_id . def_id ,  span,  method_sig) ; 
847847} 
848848
849- fn  check_param_wf ( tcx :  TyCtxt < ' _ > ,  param :  & hir:: GenericParam < ' _ > )  { 
849+ fn  check_param_wf ( tcx :  TyCtxt < ' _ > ,  param :  & hir:: GenericParam < ' _ > ,   owner_id :   LocalDefId )  { 
850850    match  param. kind  { 
851851        // We currently only check wf of const params here. 
852852        hir:: GenericParamKind :: Lifetime  {  .. }  | hir:: GenericParamKind :: Type  {  .. }  => ( ) , 
853853
854854        // Const parameters are well formed if their type is structural match. 
855855        hir:: GenericParamKind :: Const  {  ty :  hir_ty,  default :  _ }  => { 
856-             let  mut  ty = tcx. type_of ( param. def_id ) ; 
857-             while  let  ty:: Projection ( ty:: ProjectionTy  {  substs,  item_def_id } )  = ty. kind ( )  { 
858-                 let  binder_ty = tcx. bound_type_of ( * item_def_id) ; 
859-                 ty = binder_ty. subst ( tcx,  substs) ; 
860-             } 
856+             enter_wf_checking_ctxt ( tcx,  param. span ,  owner_id,  |wfcx| { 
857+                 let  ty = tcx. type_of ( param. def_id ) ; 
858+                 let  ty = wfcx. normalize ( hir_ty. span ,  None ,  ty) ; 
859+ 
860+                 if  tcx. features ( ) . adt_const_params  { 
861+                     if  let  Some ( non_structural_match_ty)  =
862+                         traits:: search_for_adt_const_param_violation ( param. span ,  tcx,  ty) 
863+                     { 
864+                         // We use the same error code in both branches, because this is really the same 
865+                         // issue: we just special-case the message for type parameters to make it 
866+                         // clearer. 
867+                         match  non_structural_match_ty. kind ( )  { 
868+                             ty:: Param ( _)  => { 
869+                                 // Const parameters may not have type parameters as their types, 
870+                                 // because we cannot be sure that the type parameter derives `PartialEq` 
871+                                 // and `Eq` (just implementing them is not enough for `structural_match`). 
872+                                 struct_span_err ! ( 
873+                                     tcx. sess, 
874+                                     hir_ty. span, 
875+                                     E0741 , 
876+                                     "`{ty}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be \  
877+                                      used as the type of a const parameter", 
878+                                 ) 
879+                                 . span_label ( 
880+                                     hir_ty. span , 
881+                                     format ! ( "`{ty}` may not derive both `PartialEq` and `Eq`" ) , 
882+                                 ) 
883+                                 . note ( 
884+                                     "it is not currently possible to use a type parameter as the type of a \  
885+                                      const parameter", 
886+                                 ) 
887+                                 . emit ( ) ; 
888+                             } 
889+                             ty:: Float ( _)  => { 
890+                                 struct_span_err ! ( 
891+                                     tcx. sess, 
892+                                     hir_ty. span, 
893+                                     E0741 , 
894+                                     "`{ty}` is forbidden as the type of a const generic parameter" , 
895+                                 ) 
896+                                 . note ( "floats do not derive `Eq` or `Ord`, which are required for const parameters" ) 
897+                                 . emit ( ) ; 
898+                             } 
899+                             ty:: FnPtr ( _)  => { 
900+                                 struct_span_err ! ( 
901+                                     tcx. sess, 
902+                                     hir_ty. span, 
903+                                     E0741 , 
904+                                     "using function pointers as const generic parameters is forbidden" , 
905+                                 ) 
906+                                 . emit ( ) ; 
907+                             } 
908+                             ty:: RawPtr ( _)  => { 
909+                                 struct_span_err ! ( 
910+                                     tcx. sess, 
911+                                     hir_ty. span, 
912+                                     E0741 , 
913+                                     "using raw pointers as const generic parameters is forbidden" , 
914+                                 ) 
915+                                 . emit ( ) ; 
916+                             } 
917+                             _ => { 
918+                                 let  mut  diag = struct_span_err ! ( 
919+                                     tcx. sess, 
920+                                     hir_ty. span, 
921+                                     E0741 , 
922+                                     "`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \  
923+                                      the type of a const parameter", 
924+                                     non_structural_match_ty, 
925+                                 ) ; 
861926
862-             if  tcx. features ( ) . adt_const_params  { 
863-                 if  let  Some ( non_structural_match_ty)  =
864-                     traits:: search_for_adt_const_param_violation ( param. span ,  tcx,  ty) 
865-                 { 
866-                     // We use the same error code in both branches, because this is really the same 
867-                     // issue: we just special-case the message for type parameters to make it 
868-                     // clearer. 
869-                     match  non_structural_match_ty. kind ( )  { 
870-                         ty:: Param ( _)  => { 
871-                             // Const parameters may not have type parameters as their types, 
872-                             // because we cannot be sure that the type parameter derives `PartialEq` 
873-                             // and `Eq` (just implementing them is not enough for `structural_match`). 
874-                             struct_span_err ! ( 
875-                                 tcx. sess, 
876-                                 hir_ty. span, 
877-                                 E0741 , 
878-                                 "`{ty}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be \  
879-                                  used as the type of a const parameter", 
880-                             ) 
881-                             . span_label ( 
882-                                 hir_ty. span , 
883-                                 format ! ( "`{ty}` may not derive both `PartialEq` and `Eq`" ) , 
884-                             ) 
885-                             . note ( 
886-                                 "it is not currently possible to use a type parameter as the type of a \  
887-                                  const parameter", 
888-                             ) 
889-                             . emit ( ) ; 
890-                         } 
891-                         ty:: Float ( _)  => { 
892-                             struct_span_err ! ( 
893-                                 tcx. sess, 
894-                                 hir_ty. span, 
895-                                 E0741 , 
896-                                 "`{ty}` is forbidden as the type of a const generic parameter" , 
897-                             ) 
898-                             . note ( "floats do not derive `Eq` or `Ord`, which are required for const parameters" ) 
899-                             . emit ( ) ; 
927+                                 if  ty == non_structural_match_ty { 
928+                                     diag. span_label ( 
929+                                         hir_ty. span , 
930+                                         format ! ( "`{ty}` doesn't derive both `PartialEq` and `Eq`" ) , 
931+                                     ) ; 
932+                                 } 
933+ 
934+                                 diag. emit ( ) ; 
935+                             } 
900936                        } 
901-                         ty:: FnPtr ( _)  => { 
902-                             struct_span_err ! ( 
903-                                 tcx. sess, 
904-                                 hir_ty. span, 
905-                                 E0741 , 
906-                                 "using function pointers as const generic parameters is forbidden" , 
907-                             ) 
908-                             . emit ( ) ; 
937+                     } 
938+                 }  else  { 
939+                     let  err_ty_str; 
940+                     let  mut  is_ptr = true ; 
941+ 
942+                     let  err = match  ty. kind ( )  { 
943+                         ty:: Bool  | ty:: Char  | ty:: Int ( _)  | ty:: Uint ( _)  | ty:: Error ( _)  => None , 
944+                         ty:: FnPtr ( _)  => Some ( "function pointers" ) , 
945+                         ty:: RawPtr ( _)  => Some ( "raw pointers" ) , 
946+                         _ => { 
947+                             is_ptr = false ; 
948+                             err_ty_str = format ! ( "`{ty}`" ) ; 
949+                             Some ( err_ty_str. as_str ( ) ) 
909950                        } 
910-                         ty:: RawPtr ( _)  => { 
911-                             struct_span_err ! ( 
912-                                 tcx. sess, 
951+                     } ; 
952+ 
953+                     if  let  Some ( unsupported_type)  = err { 
954+                         if  is_ptr { 
955+                             tcx. sess . span_err ( 
913956                                hir_ty. span , 
914-                                 E0741 , 
915-                                 "using raw pointers as const generic parameters is forbidden" , 
916-                             ) 
917-                             . emit ( ) ; 
918-                         } 
919-                         // Should have been normalized in 
920-                         // `traits::search_for_adt_const_param_violation` 
921-                         ty:: Projection ( _)  => unreachable ! ( ) , 
922-                         _ => { 
923-                             let  mut  diag = struct_span_err ! ( 
924-                                 tcx. sess, 
957+                                 & format ! ( 
958+                                     "using {unsupported_type} as const generic parameters is forbidden" , 
959+                                 ) , 
960+                             ) ; 
961+                         }  else  { 
962+                             let  mut  err = tcx. sess . struct_span_err ( 
925963                                hir_ty. span , 
926-                                 E0741 , 
927-                                 "`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \  
928-                                  the type of a const parameter", 
929-                                 non_structural_match_ty, 
964+                                 & format ! ( 
965+                                     "{unsupported_type} is forbidden as the type of a const generic parameter" , 
966+                                 ) , 
967+                             ) ; 
968+                             err. note ( "the only supported types are integers, `bool` and `char`" ) ; 
969+                             if  tcx. sess . is_nightly_build ( )  { 
970+                                 err. help ( 
971+                                 "more complex types are supported with `#![feature(adt_const_params)]`" , 
930972                            ) ; 
931- 
932-                             if  ty == non_structural_match_ty { 
933-                                 diag. span_label ( 
934-                                     hir_ty. span , 
935-                                     format ! ( "`{ty}` doesn't derive both `PartialEq` and `Eq`" ) , 
936-                                 ) ; 
937973                            } 
938- 
939-                             diag. emit ( ) ; 
974+                             err. emit ( ) ; 
940975                        } 
941976                    } 
942977                } 
943-             }  else  { 
944-                 let  err_ty_str; 
945-                 let  mut  is_ptr = true ; 
946- 
947-                 let  err = match  ty. kind ( )  { 
948-                     ty:: Bool  | ty:: Char  | ty:: Int ( _)  | ty:: Uint ( _)  | ty:: Error ( _)  => None , 
949-                     ty:: FnPtr ( _)  => Some ( "function pointers" ) , 
950-                     ty:: RawPtr ( _)  => Some ( "raw pointers" ) , 
951-                     _ => { 
952-                         is_ptr = false ; 
953-                         err_ty_str = format ! ( "`{ty}`" ) ; 
954-                         Some ( err_ty_str. as_str ( ) ) 
955-                     } 
956-                 } ; 
957- 
958-                 if  let  Some ( unsupported_type)  = err { 
959-                     if  is_ptr { 
960-                         tcx. sess . span_err ( 
961-                             hir_ty. span , 
962-                             & format ! ( 
963-                                 "using {unsupported_type} as const generic parameters is forbidden" , 
964-                             ) , 
965-                         ) ; 
966-                     }  else  { 
967-                         let  mut  err = tcx. sess . struct_span_err ( 
968-                             hir_ty. span , 
969-                             & format ! ( 
970-                                 "{unsupported_type} is forbidden as the type of a const generic parameter" , 
971-                             ) , 
972-                         ) ; 
973-                         err. note ( "the only supported types are integers, `bool` and `char`" ) ; 
974-                         if  tcx. sess . is_nightly_build ( )  { 
975-                             err. help ( 
976-                             "more complex types are supported with `#![feature(adt_const_params)]`" , 
977-                         ) ; 
978-                         } 
979-                         err. emit ( ) ; 
980-                     } 
981-                 } 
982-             } 
978+             } ) ; 
983979        } 
984980    } 
985981} 
0 commit comments