@@ -149,6 +149,12 @@ pub trait TypeErrCtxtExt<'tcx> {
149149 root_obligation : & PredicateObligation < ' tcx > ,
150150 error : & SelectionError < ' tcx > ,
151151 ) ;
152+
153+ fn report_const_param_not_wf (
154+ & self ,
155+ ty : Ty < ' tcx > ,
156+ obligation : & PredicateObligation < ' tcx > ,
157+ ) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > ;
152158}
153159
154160impl < ' tcx > InferCtxtExt < ' tcx > for InferCtxt < ' tcx > {
@@ -641,6 +647,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
641647 span = obligation. cause . span ;
642648 }
643649 }
650+
644651 if let ObligationCauseCode :: CompareImplItemObligation {
645652 impl_item_def_id,
646653 trait_item_def_id,
@@ -657,6 +664,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
657664 return ;
658665 }
659666
667+ // Report a const-param specific error
668+ if let ObligationCauseCode :: ConstParam ( ty) = * obligation. cause . code ( ) . peel_derives ( )
669+ {
670+ self . report_const_param_not_wf ( ty, & obligation) . emit ( ) ;
671+ return ;
672+ }
673+
660674 let bound_predicate = obligation. predicate . kind ( ) ;
661675 match bound_predicate. skip_binder ( ) {
662676 ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( trait_predicate) ) => {
@@ -1163,6 +1177,102 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
11631177 self . point_at_returns_when_relevant ( & mut err, & obligation) ;
11641178 err. emit ( ) ;
11651179 }
1180+
1181+ fn report_const_param_not_wf (
1182+ & self ,
1183+ ty : Ty < ' tcx > ,
1184+ obligation : & PredicateObligation < ' tcx > ,
1185+ ) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > {
1186+ let span = obligation. cause . span ;
1187+
1188+ let mut diag = match ty. kind ( ) {
1189+ _ if ty. has_param ( ) => {
1190+ span_bug ! ( span, "const param tys cannot mention other generic parameters" ) ;
1191+ }
1192+ ty:: Float ( _) => {
1193+ struct_span_err ! (
1194+ self . tcx. sess,
1195+ span,
1196+ E0741 ,
1197+ "`{ty}` is forbidden as the type of a const generic parameter" ,
1198+ )
1199+ }
1200+ ty:: FnPtr ( _) => {
1201+ struct_span_err ! (
1202+ self . tcx. sess,
1203+ span,
1204+ E0741 ,
1205+ "using function pointers as const generic parameters is forbidden" ,
1206+ )
1207+ }
1208+ ty:: RawPtr ( _) => {
1209+ struct_span_err ! (
1210+ self . tcx. sess,
1211+ span,
1212+ E0741 ,
1213+ "using raw pointers as const generic parameters is forbidden" ,
1214+ )
1215+ }
1216+ ty:: Adt ( def, _) => {
1217+ // We should probably see if we're *allowed* to derive `ConstParamTy` on the type...
1218+ let mut diag = struct_span_err ! (
1219+ self . tcx. sess,
1220+ span,
1221+ E0741 ,
1222+ "`{ty}` must implement `ConstParamTy` to be used as the type of a const generic parameter" ,
1223+ ) ;
1224+ // Only suggest derive if this isn't a derived obligation,
1225+ // and the struct is local.
1226+ if let Some ( span) = self . tcx . hir ( ) . span_if_local ( def. did ( ) )
1227+ && obligation. cause . code ( ) . parent ( ) . is_none ( )
1228+ {
1229+ if ty. is_structural_eq_shallow ( self . tcx ) {
1230+ diag. span_suggestion (
1231+ span,
1232+ "add `#[derive(ConstParamTy)]` to the struct" ,
1233+ "#[derive(ConstParamTy)]\n " ,
1234+ Applicability :: MachineApplicable ,
1235+ ) ;
1236+ } else {
1237+ // FIXME(adt_const_params): We should check there's not already an
1238+ // overlapping `Eq`/`PartialEq` impl.
1239+ diag. span_suggestion (
1240+ span,
1241+ "add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct" ,
1242+ "#[derive(ConstParamTy, PartialEq, Eq)]\n " ,
1243+ Applicability :: MachineApplicable ,
1244+ ) ;
1245+ }
1246+ }
1247+ diag
1248+ }
1249+ _ => {
1250+ struct_span_err ! (
1251+ self . tcx. sess,
1252+ span,
1253+ E0741 ,
1254+ "`{ty}` can't be used as a const parameter type" ,
1255+ )
1256+ }
1257+ } ;
1258+
1259+ let mut code = obligation. cause . code ( ) ;
1260+ let mut pred = obligation. predicate . to_opt_poly_trait_pred ( ) ;
1261+ while let Some ( ( next_code, next_pred) ) = code. parent ( ) {
1262+ if let Some ( pred) = pred {
1263+ let pred = self . instantiate_binder_with_placeholders ( pred) ;
1264+ diag. note ( format ! (
1265+ "`{}` must implement `{}`, but it does not" ,
1266+ pred. self_ty( ) ,
1267+ pred. print_modifiers_and_trait_path( )
1268+ ) ) ;
1269+ }
1270+ code = next_code;
1271+ pred = next_pred;
1272+ }
1273+
1274+ diag
1275+ }
11661276}
11671277
11681278trait InferCtxtPrivExt < ' tcx > {
0 commit comments