@@ -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