@@ -24,6 +24,9 @@ use rustc_span::symbol::{sym, Ident, Symbol};
24
24
use rustc_span:: { Span , DUMMY_SP } ;
25
25
use rustc_target:: spec:: abi:: Abi ;
26
26
use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt ;
27
+ use rustc_trait_selection:: traits:: misc:: {
28
+ type_allowed_to_implement_const_param_ty, ConstParamTyImplementationError ,
29
+ } ;
27
30
use rustc_trait_selection:: traits:: outlives_bounds:: InferCtxtExt as _;
28
31
use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
29
32
use rustc_trait_selection:: traits:: {
@@ -865,43 +868,65 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
865
868
) ;
866
869
} ) ;
867
870
} else {
868
- let err_ty_str;
869
- let mut is_ptr = true ;
870
-
871
- let err = match ty. kind ( ) {
871
+ let diag = match ty. kind ( ) {
872
872
ty:: Bool | ty:: Char | ty:: Int ( _) | ty:: Uint ( _) | ty:: Error ( _) => None ,
873
- ty:: FnPtr ( _) => Some ( "function pointers" ) ,
874
- ty:: RawPtr ( _) => Some ( "raw pointers" ) ,
875
- _ => {
876
- is_ptr = false ;
877
- err_ty_str = format ! ( "`{ty}`" ) ;
878
- Some ( err_ty_str. as_str ( ) )
879
- }
873
+ ty:: FnPtr ( _) => Some ( tcx. sess . struct_span_err (
874
+ hir_ty. span ,
875
+ "using function pointers as const generic parameters is forbidden" ,
876
+ ) ) ,
877
+ ty:: RawPtr ( _) => Some ( tcx. sess . struct_span_err (
878
+ hir_ty. span ,
879
+ "using raw pointers as const generic parameters is forbidden" ,
880
+ ) ) ,
881
+ _ => Some ( tcx. sess . struct_span_err (
882
+ hir_ty. span ,
883
+ format ! ( "`{}` is forbidden as the type of a const generic parameter" , ty) ,
884
+ ) ) ,
880
885
} ;
881
886
882
- if let Some ( unsupported_type) = err {
883
- if is_ptr {
884
- tcx. sess . span_err (
885
- hir_ty. span ,
886
- format ! (
887
- "using {unsupported_type} as const generic parameters is forbidden" ,
888
- ) ,
889
- ) ;
890
- } else {
891
- let mut err = tcx. sess . struct_span_err (
892
- hir_ty. span ,
893
- format ! (
894
- "{unsupported_type} is forbidden as the type of a const generic parameter" ,
895
- ) ,
896
- ) ;
897
- err. note ( "the only supported types are integers, `bool` and `char`" ) ;
898
- if tcx. sess . is_nightly_build ( ) {
899
- err. help (
900
- "more complex types are supported with `#![feature(adt_const_params)]`" ,
901
- ) ;
887
+ if let Some ( mut diag) = diag {
888
+ diag. note ( "the only supported types are integers, `bool` and `char`" ) ;
889
+
890
+ let cause = ObligationCause :: misc ( hir_ty. span , param. def_id ) ;
891
+ let may_suggest_feature = match type_allowed_to_implement_const_param_ty (
892
+ tcx,
893
+ tcx. param_env ( param. def_id ) ,
894
+ ty,
895
+ cause,
896
+ ) {
897
+ // Can never implement `ConstParamTy`, don't suggest anything.
898
+ Err ( ConstParamTyImplementationError :: NotAnAdtOrBuiltinAllowed ) => false ,
899
+ // May be able to implement `ConstParamTy`. Only emit the feature help
900
+ // if the type is local, since the user may be able to fix the local type.
901
+ Err ( ConstParamTyImplementationError :: InfrigingFields ( ..) ) => {
902
+ fn ty_is_local ( ty : Ty < ' _ > ) -> bool {
903
+ match ty. kind ( ) {
904
+ ty:: Adt ( adt_def, ..) => adt_def. did ( ) . is_local ( ) ,
905
+ // Arrays and slices use the inner type's `ConstParamTy`.
906
+ ty:: Array ( ty, ..) => ty_is_local ( * ty) ,
907
+ ty:: Slice ( ty) => ty_is_local ( * ty) ,
908
+ // `&` references use the inner type's `ConstParamTy`.
909
+ // `&mut` are not supported.
910
+ ty:: Ref ( _, ty, ast:: Mutability :: Not ) => ty_is_local ( * ty) ,
911
+ // Say that a tuple is local if any of its components are local.
912
+ // This is not strictly correct, but it's likely that the user can fix the local component.
913
+ ty:: Tuple ( tys) => tys. iter ( ) . any ( |ty| ty_is_local ( ty) ) ,
914
+ _ => false ,
915
+ }
916
+ }
917
+
918
+ ty_is_local ( ty)
902
919
}
903
- err. emit ( ) ;
920
+ // Implments `ConstParamTy`, suggest adding the feature to enable.
921
+ Ok ( ..) => true ,
922
+ } ;
923
+ if may_suggest_feature && tcx. sess . is_nightly_build ( ) {
924
+ diag. help (
925
+ "add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types" ,
926
+ ) ;
904
927
}
928
+
929
+ diag. emit ( ) ;
905
930
}
906
931
}
907
932
}
0 commit comments