@@ -66,6 +66,10 @@ crate fn compare_impl_method<'tcx>(
6666 {
6767 return ;
6868 }
69+
70+ if let Err ( ErrorReported ) = compare_const_param_types ( tcx, impl_m, trait_m, trait_item_span) {
71+ return ;
72+ }
6973}
7074
7175fn compare_predicate_entailment < ' tcx > (
@@ -929,6 +933,68 @@ fn compare_synthetic_generics<'tcx>(
929933 if error_found { Err ( ErrorReported ) } else { Ok ( ( ) ) }
930934}
931935
936+ fn compare_const_param_types < ' tcx > (
937+ tcx : TyCtxt < ' tcx > ,
938+ impl_m : & ty:: AssocItem ,
939+ trait_m : & ty:: AssocItem ,
940+ trait_item_span : Option < Span > ,
941+ ) -> Result < ( ) , ErrorReported > {
942+ let const_params_of = |def_id| {
943+ tcx. generics_of ( def_id) . params . iter ( ) . filter_map ( |param| match param. kind {
944+ GenericParamDefKind :: Const { .. } => Some ( param. def_id ) ,
945+ _ => None ,
946+ } )
947+ } ;
948+ let const_params_impl = const_params_of ( impl_m. def_id ) ;
949+ let const_params_trait = const_params_of ( trait_m. def_id ) ;
950+
951+ for ( const_param_impl, const_param_trait) in iter:: zip ( const_params_impl, const_params_trait) {
952+ let impl_ty = tcx. type_of ( const_param_impl) ;
953+ let trait_ty = tcx. type_of ( const_param_trait) ;
954+ if impl_ty != trait_ty {
955+ let ( impl_span, impl_ident) = match tcx. hir ( ) . get_if_local ( const_param_impl) {
956+ Some ( hir:: Node :: GenericParam ( hir:: GenericParam { span, name, .. } ) ) => (
957+ span,
958+ match name {
959+ hir:: ParamName :: Plain ( ident) => Some ( ident) ,
960+ _ => None ,
961+ } ,
962+ ) ,
963+ other => bug ! (
964+ "expected GenericParam, found {:?}" ,
965+ other. map_or_else( || "nothing" . to_string( ) , |n| format!( "{:?}" , n) )
966+ ) ,
967+ } ;
968+ let trait_span = match tcx. hir ( ) . get_if_local ( const_param_trait) {
969+ Some ( hir:: Node :: GenericParam ( hir:: GenericParam { span, .. } ) ) => Some ( span) ,
970+ _ => None ,
971+ } ;
972+ let mut err = struct_span_err ! (
973+ tcx. sess,
974+ * impl_span,
975+ E0053 ,
976+ "method `{}` has an incompatible const parameter type for trait" ,
977+ trait_m. ident
978+ ) ;
979+ err. span_note (
980+ trait_span. map_or_else ( || trait_item_span. unwrap_or ( * impl_span) , |span| * span) ,
981+ & format ! (
982+ "the const parameter{} has type `{}`, but the declaration \
983+ in trait `{}` has type `{}`",
984+ & impl_ident. map_or_else( || "" . to_string( ) , |ident| format!( " `{}`" , ident) ) ,
985+ impl_ty,
986+ tcx. def_path_str( trait_m. def_id) ,
987+ trait_ty
988+ ) ,
989+ ) ;
990+ err. emit ( ) ;
991+ return Err ( ErrorReported ) ;
992+ }
993+ }
994+
995+ Ok ( ( ) )
996+ }
997+
932998crate fn compare_const_impl < ' tcx > (
933999 tcx : TyCtxt < ' tcx > ,
9341000 impl_c : & ty:: AssocItem ,
0 commit comments