@@ -48,6 +48,10 @@ crate fn compare_impl_method<'tcx>(
48
48
return ;
49
49
}
50
50
51
+ if let Err ( _) = compare_generic_param_kinds ( tcx, impl_m, trait_m, trait_item_span) {
52
+ return ;
53
+ }
54
+
51
55
if let Err ( _) =
52
56
compare_number_of_method_arguments ( tcx, impl_m, impl_m_span, trait_m, trait_item_span)
53
57
{
@@ -62,10 +66,6 @@ crate fn compare_impl_method<'tcx>(
62
66
{
63
67
return ;
64
68
}
65
-
66
- if let Err ( _) = compare_const_param_types ( tcx, impl_m, trait_m, trait_item_span) {
67
- return ;
68
- }
69
69
}
70
70
71
71
fn compare_predicate_entailment < ' tcx > (
@@ -914,62 +914,165 @@ fn compare_synthetic_generics<'tcx>(
914
914
if let Some ( reported) = error_found { Err ( reported) } else { Ok ( ( ) ) }
915
915
}
916
916
917
- fn compare_const_param_types < ' tcx > (
917
+ /// Checks that all parameters in the generics of a given assoc item in a trait impl have
918
+ /// the same kind as the respective generic parameter in the trait def.
919
+ ///
920
+ /// For example all 4 errors in the following code are emitted here:
921
+ /// ```
922
+ /// trait Foo {
923
+ /// fn foo<const N: u8>();
924
+ /// type bar<const N: u8>;
925
+ /// fn baz<const N: u32>();
926
+ /// type blah<T>;
927
+ /// }
928
+ ///
929
+ /// impl Foo for () {
930
+ /// fn foo<const N: u64>() {}
931
+ /// //~^ error
932
+ /// type bar<const N: u64> {}
933
+ /// //~^ error
934
+ /// fn baz<T>() {}
935
+ /// //~^ error
936
+ /// type blah<const N: i64> = u32;
937
+ /// //~^ error
938
+ /// }
939
+ /// ```
940
+ ///
941
+ /// This function does not handle lifetime parameters
942
+ fn compare_generic_param_kinds < ' tcx > (
918
943
tcx : TyCtxt < ' tcx > ,
919
- impl_m : & ty:: AssocItem ,
920
- trait_m : & ty:: AssocItem ,
944
+ impl_item : & ty:: AssocItem ,
945
+ trait_item : & ty:: AssocItem ,
921
946
trait_item_span : Option < Span > ,
922
947
) -> Result < ( ) , ErrorGuaranteed > {
923
- let const_params_of = |def_id| {
924
- tcx. generics_of ( def_id) . params . iter ( ) . filter_map ( |param| match param. kind {
925
- GenericParamDefKind :: Const { .. } => Some ( param. def_id ) ,
926
- _ => None ,
948
+ assert_eq ! ( impl_item. kind, trait_item. kind) ;
949
+
950
+ let ty_const_params_of = |def_id| {
951
+ tcx. generics_of ( def_id) . params . iter ( ) . filter ( |param| {
952
+ matches ! (
953
+ param. kind,
954
+ GenericParamDefKind :: Const { .. } | GenericParamDefKind :: Type { .. }
955
+ )
927
956
} )
928
957
} ;
929
- let const_params_impl = const_params_of ( impl_m. def_id ) ;
930
- let const_params_trait = const_params_of ( trait_m. def_id ) ;
931
-
932
- for ( const_param_impl, const_param_trait) in iter:: zip ( const_params_impl, const_params_trait) {
933
- let impl_ty = tcx. type_of ( const_param_impl) ;
934
- let trait_ty = tcx. type_of ( const_param_trait) ;
935
- if impl_ty != trait_ty {
936
- let ( impl_span, impl_ident) = match tcx. hir ( ) . get_if_local ( const_param_impl) {
937
- Some ( hir:: Node :: GenericParam ( hir:: GenericParam { span, name, .. } ) ) => (
938
- span,
939
- match name {
940
- hir:: ParamName :: Plain ( ident) => Some ( ident) ,
941
- _ => None ,
942
- } ,
943
- ) ,
944
- other => bug ! (
945
- "expected GenericParam, found {:?}" ,
946
- other. map_or_else( || "nothing" . to_string( ) , |n| format!( "{:?}" , n) )
947
- ) ,
948
- } ;
949
- let trait_span = match tcx. hir ( ) . get_if_local ( const_param_trait) {
950
- Some ( hir:: Node :: GenericParam ( hir:: GenericParam { span, .. } ) ) => Some ( span) ,
951
- _ => None ,
952
- } ;
953
- let mut err = struct_span_err ! (
954
- tcx. sess,
955
- * impl_span,
956
- E0053 ,
957
- "method `{}` has an incompatible const parameter type for trait" ,
958
- trait_m. name
959
- ) ;
960
- err. span_note (
961
- trait_span. map_or_else ( || trait_item_span. unwrap_or ( * impl_span) , |span| * span) ,
962
- & format ! (
963
- "the const parameter{} has type `{}`, but the declaration \
964
- in trait `{}` has type `{}`",
965
- & impl_ident. map_or_else( || "" . to_string( ) , |ident| format!( " `{ident}`" ) ) ,
966
- impl_ty,
967
- tcx. def_path_str( trait_m. def_id) ,
968
- trait_ty
969
- ) ,
970
- ) ;
971
- let reported = err. emit ( ) ;
972
- return Err ( reported) ;
958
+
959
+ let get_param_span = |param : & ty:: GenericParamDef | match tcx. hir ( ) . get_if_local ( param. def_id ) {
960
+ Some ( hir:: Node :: GenericParam ( hir:: GenericParam { span, .. } ) ) => Some ( span) ,
961
+ _ => None ,
962
+ } ;
963
+
964
+ let get_param_ident = |param : & ty:: GenericParamDef | match tcx. hir ( ) . get_if_local ( param. def_id ) {
965
+ Some ( hir:: Node :: GenericParam ( hir:: GenericParam { name, .. } ) ) => match name {
966
+ hir:: ParamName :: Plain ( ident) => Some ( ident) ,
967
+ _ => None ,
968
+ } ,
969
+ other => bug ! (
970
+ "expected GenericParam, found {:?}" ,
971
+ other. map_or_else( || "nothing" . to_string( ) , |n| format!( "{:?}" , n) )
972
+ ) ,
973
+ } ;
974
+
975
+ let ty_const_params_impl = ty_const_params_of ( impl_item. def_id ) ;
976
+ let ty_const_params_trait = ty_const_params_of ( trait_item. def_id ) ;
977
+ let assoc_item_str = assoc_item_kind_str ( & impl_item) ;
978
+
979
+ for ( param_impl, param_trait) in iter:: zip ( ty_const_params_impl, ty_const_params_trait) {
980
+ use GenericParamDefKind :: * ;
981
+ match ( & param_impl. kind , & param_trait. kind ) {
982
+ ( Const { .. } , Const { .. } ) => {
983
+ let impl_ty = tcx. type_of ( param_impl. def_id ) ;
984
+ let trait_ty = tcx. type_of ( param_trait. def_id ) ;
985
+ if impl_ty != trait_ty {
986
+ let param_impl_span = get_param_span ( param_impl) . unwrap ( ) ;
987
+ let param_impl_ident = get_param_ident ( param_impl) ;
988
+ let param_trait_span = get_param_span ( param_trait) ;
989
+
990
+ let mut err = struct_span_err ! (
991
+ tcx. sess,
992
+ * param_impl_span,
993
+ E0053 ,
994
+ "{} `{}` has an incompatible const parameter type for trait" ,
995
+ assoc_item_str,
996
+ trait_item. name,
997
+ ) ;
998
+ err. span_note (
999
+ param_trait_span. map_or_else (
1000
+ || trait_item_span. unwrap_or ( * param_impl_span) ,
1001
+ |span| * span,
1002
+ ) ,
1003
+ & format ! (
1004
+ "the const parameter{} has type `{}`, but the declaration \
1005
+ in trait `{}` has type `{}`",
1006
+ & param_impl_ident
1007
+ . map_or_else( || "" . to_string( ) , |ident| format!( " `{ident}`" ) ) ,
1008
+ impl_ty,
1009
+ tcx. def_path_str( trait_item. def_id) ,
1010
+ trait_ty
1011
+ ) ,
1012
+ ) ;
1013
+ let reported = err. emit ( ) ;
1014
+ return Err ( reported) ;
1015
+ }
1016
+ }
1017
+ ( Const { .. } , Type { .. } ) => {
1018
+ let impl_ty = tcx. type_of ( param_impl. def_id ) ;
1019
+ let param_impl_span = get_param_span ( param_impl) . unwrap ( ) ;
1020
+ let param_impl_ident = get_param_ident ( param_impl) ;
1021
+ let param_trait_span = get_param_span ( param_trait) ;
1022
+
1023
+ let mut err = struct_span_err ! (
1024
+ tcx. sess,
1025
+ * param_impl_span,
1026
+ E0053 ,
1027
+ "{} `{}` has an incompatible generic parameter for trait" ,
1028
+ assoc_item_str,
1029
+ trait_item. name,
1030
+ ) ;
1031
+ err. span_note (
1032
+ param_trait_span
1033
+ . map_or_else ( || trait_item_span. unwrap_or ( * param_impl_span) , |span| * span) ,
1034
+ & format ! (
1035
+ "the trait impl specifies{} a const parameter of type `{}`, but the declaration \
1036
+ in trait `{}` requires it is a type parameter",
1037
+ & param_impl_ident
1038
+ . map_or_else( || "" . to_string( ) , |ident| format!( " `{ident}` is" ) ) ,
1039
+ impl_ty,
1040
+ tcx. def_path_str( trait_item. def_id) ,
1041
+ ) ,
1042
+ ) ;
1043
+ let reported = err. emit ( ) ;
1044
+ return Err ( reported) ;
1045
+ }
1046
+ ( Type { .. } , Const { .. } ) => {
1047
+ let trait_ty = tcx. type_of ( param_trait. def_id ) ;
1048
+ let param_impl_span = get_param_span ( param_impl) . unwrap ( ) ;
1049
+ let param_impl_ident = get_param_ident ( param_impl) ;
1050
+ let param_trait_span = get_param_span ( param_trait) ;
1051
+
1052
+ let mut err = struct_span_err ! (
1053
+ tcx. sess,
1054
+ * param_impl_span,
1055
+ E0053 ,
1056
+ "{} `{}` has an incompatible generic parameter for trait" ,
1057
+ assoc_item_str,
1058
+ trait_item. name,
1059
+ ) ;
1060
+ err. span_note (
1061
+ param_trait_span
1062
+ . map_or_else ( || trait_item_span. unwrap_or ( * param_impl_span) , |span| * span) ,
1063
+ & format ! (
1064
+ "the trait impl specifies{} a type parameter, but the declaration \
1065
+ in trait `{}` requires it is a const parameter of type `{}`",
1066
+ & param_impl_ident
1067
+ . map_or_else( || "" . to_string( ) , |ident| format!( " `{ident}` is" ) ) ,
1068
+ tcx. def_path_str( trait_item. def_id) ,
1069
+ trait_ty,
1070
+ ) ,
1071
+ ) ;
1072
+ let reported = err. emit ( ) ;
1073
+ return Err ( reported) ;
1074
+ }
1075
+ _ => ( ) ,
973
1076
}
974
1077
}
975
1078
@@ -1095,6 +1198,8 @@ crate fn compare_ty_impl<'tcx>(
1095
1198
let _: Result < ( ) , ErrorGuaranteed > = ( || {
1096
1199
compare_number_of_generics ( tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span) ?;
1097
1200
1201
+ compare_generic_param_kinds ( tcx, impl_ty, trait_ty, trait_item_span) ?;
1202
+
1098
1203
let sp = tcx. def_span ( impl_ty. def_id ) ;
1099
1204
compare_type_predicate_entailment ( tcx, impl_ty, sp, trait_ty, impl_trait_ref) ?;
1100
1205
0 commit comments