11use crate :: errors:: {
22 self , AssocTypeBindingNotAllowed , ManualImplementation , MissingTypeParams ,
3- ParenthesizedFnTraitExpansion ,
3+ ParenthesizedFnTraitExpansion , TraitObjectDeclaredWithNoTraits ,
44} ;
55use crate :: fluent_generated as fluent;
66use crate :: hir_ty_lowering:: HirTyLowerer ;
77use crate :: traits:: error_reporting:: report_object_safety_error;
88use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
99use rustc_data_structures:: sorted_map:: SortedMap ;
1010use rustc_data_structures:: unord:: UnordMap ;
11+ use rustc_errors:: MultiSpan ;
1112use rustc_errors:: {
1213 codes:: * , pluralize, struct_span_code_err, Applicability , Diag , ErrorGuaranteed ,
1314} ;
@@ -16,11 +17,22 @@ use rustc_hir::def_id::{DefId, LocalDefId};
1617use rustc_infer:: traits:: FulfillmentError ;
1718use rustc_middle:: query:: Key ;
1819use rustc_middle:: ty:: { self , suggest_constraining_type_param, Ty , TyCtxt , TypeVisitableExt } ;
20+ use rustc_middle:: ty:: { Binder , TraitRef } ;
1921use rustc_session:: parse:: feature_err;
2022use rustc_span:: edit_distance:: find_best_match_for_name;
2123use rustc_span:: symbol:: { sym, Ident } ;
2224use rustc_span:: { Span , Symbol , DUMMY_SP } ;
23- use rustc_trait_selection:: traits:: object_safety_violations_for_assoc_item;
25+ use rustc_trait_selection:: traits:: {
26+ object_safety_violations_for_assoc_item, TraitAliasExpansionInfo ,
27+ } ;
28+
29+ #[ derive( PartialEq , Eq , Hash ) ]
30+ pub enum ProhibitGenericsArg {
31+ Lifetime ,
32+ Type ,
33+ Const ,
34+ Infer ,
35+ }
2436
2537impl < ' tcx > dyn HirTyLowerer < ' tcx > + ' _ {
2638 /// On missing type parameters, emit an E0393 error and provide a structured suggestion using
@@ -1024,6 +1036,159 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10241036 Ok ( ( ) )
10251037 }
10261038 }
1039+
1040+ pub fn report_prohibit_generics_error < ' a > (
1041+ & self ,
1042+ segments : impl Iterator < Item = & ' a hir:: PathSegment < ' a > > + Clone ,
1043+ args_visitors : impl Iterator < Item = & ' a hir:: GenericArg < ' a > > + Clone ,
1044+ extend : impl Fn ( & mut Diag < ' _ > ) ,
1045+ ) -> ErrorGuaranteed {
1046+ let mut prohibit_args = FxIndexSet :: default ( ) ;
1047+ args_visitors. for_each ( |arg| {
1048+ match arg {
1049+ hir:: GenericArg :: Lifetime ( _) => prohibit_args. insert ( ProhibitGenericsArg :: Lifetime ) ,
1050+ hir:: GenericArg :: Type ( _) => prohibit_args. insert ( ProhibitGenericsArg :: Type ) ,
1051+ hir:: GenericArg :: Const ( _) => prohibit_args. insert ( ProhibitGenericsArg :: Const ) ,
1052+ hir:: GenericArg :: Infer ( _) => prohibit_args. insert ( ProhibitGenericsArg :: Infer ) ,
1053+ } ;
1054+ } ) ;
1055+
1056+ let types_and_spans: Vec < _ > = segments
1057+ . clone ( )
1058+ . flat_map ( |segment| {
1059+ if segment. args ( ) . args . is_empty ( ) {
1060+ None
1061+ } else {
1062+ Some ( (
1063+ match segment. res {
1064+ hir:: def:: Res :: PrimTy ( ty) => {
1065+ format ! ( "{} `{}`" , segment. res. descr( ) , ty. name( ) )
1066+ }
1067+ hir:: def:: Res :: Def ( _, def_id)
1068+ if let Some ( name) = self . tcx ( ) . opt_item_name ( def_id) =>
1069+ {
1070+ format ! ( "{} `{name}`" , segment. res. descr( ) )
1071+ }
1072+ hir:: def:: Res :: Err => "this type" . to_string ( ) ,
1073+ _ => segment. res . descr ( ) . to_string ( ) ,
1074+ } ,
1075+ segment. ident . span ,
1076+ ) )
1077+ }
1078+ } )
1079+ . collect ( ) ;
1080+ let this_type = match & types_and_spans[ ..] {
1081+ [ .., _, ( last, _) ] => format ! (
1082+ "{} and {last}" ,
1083+ types_and_spans[ ..types_and_spans. len( ) - 1 ]
1084+ . iter( )
1085+ . map( |( x, _) | x. as_str( ) )
1086+ . intersperse( ", " )
1087+ . collect:: <String >( )
1088+ ) ,
1089+ [ ( only, _) ] => only. to_string ( ) ,
1090+ [ ] => "this type" . to_string ( ) ,
1091+ } ;
1092+
1093+ let arg_spans: Vec < Span > = segments
1094+ . clone ( )
1095+ . flat_map ( |segment| segment. args ( ) . args )
1096+ . map ( |arg| arg. span ( ) )
1097+ . collect ( ) ;
1098+
1099+ let mut kinds = Vec :: with_capacity ( 4 ) ;
1100+ prohibit_args. iter ( ) . for_each ( |arg| match arg {
1101+ ProhibitGenericsArg :: Lifetime => kinds. push ( "lifetime" ) ,
1102+ ProhibitGenericsArg :: Type => kinds. push ( "type" ) ,
1103+ ProhibitGenericsArg :: Const => kinds. push ( "const" ) ,
1104+ ProhibitGenericsArg :: Infer => kinds. push ( "generic" ) ,
1105+ } ) ;
1106+
1107+ let ( kind, s) = match kinds[ ..] {
1108+ [ .., _, last] => (
1109+ format ! (
1110+ "{} and {last}" ,
1111+ kinds[ ..kinds. len( ) - 1 ]
1112+ . iter( )
1113+ . map( |& x| x)
1114+ . intersperse( ", " )
1115+ . collect:: <String >( )
1116+ ) ,
1117+ "s" ,
1118+ ) ,
1119+ [ only] => ( only. to_string ( ) , "" ) ,
1120+ [ ] => unreachable ! ( "expected at least one generic to prohibit" ) ,
1121+ } ;
1122+ let last_span = * arg_spans. last ( ) . unwrap ( ) ;
1123+ let span: MultiSpan = arg_spans. into ( ) ;
1124+ let mut err = struct_span_code_err ! (
1125+ self . tcx( ) . dcx( ) ,
1126+ span,
1127+ E0109 ,
1128+ "{kind} arguments are not allowed on {this_type}" ,
1129+ ) ;
1130+ err. span_label ( last_span, format ! ( "{kind} argument{s} not allowed" ) ) ;
1131+ for ( what, span) in types_and_spans {
1132+ err. span_label ( span, format ! ( "not allowed on {what}" ) ) ;
1133+ }
1134+ extend ( & mut err) ;
1135+ let reported = err. emit ( ) ;
1136+ self . set_tainted_by_errors ( reported) ;
1137+ reported
1138+ }
1139+
1140+ pub fn report_trait_object_addition_traits_error (
1141+ & self ,
1142+ span : Span ,
1143+ trait_bounds : & Vec < ( Binder < ' tcx , TraitRef < ' tcx > > , Span ) > ,
1144+ regular_traits : & Vec < TraitAliasExpansionInfo < ' _ > > ,
1145+ ) -> ErrorGuaranteed {
1146+ let tcx = self . tcx ( ) ;
1147+ if regular_traits. len ( ) > 1 {
1148+ let first_trait = & regular_traits[ 0 ] ;
1149+ let additional_trait = & regular_traits[ 1 ] ;
1150+ let mut err = struct_span_code_err ! (
1151+ tcx. dcx( ) ,
1152+ additional_trait. bottom( ) . 1 ,
1153+ E0225 ,
1154+ "only auto traits can be used as additional traits in a trait object"
1155+ ) ;
1156+ additional_trait. label_with_exp_info (
1157+ & mut err,
1158+ "additional non-auto trait" ,
1159+ "additional use" ,
1160+ ) ;
1161+ first_trait. label_with_exp_info ( & mut err, "first non-auto trait" , "first use" ) ;
1162+ err. help ( format ! (
1163+ "consider creating a new trait with all of these as supertraits and using that \
1164+ trait here instead: `trait NewTrait: {} {{}}`",
1165+ regular_traits
1166+ . iter( )
1167+ // FIXME: This should `print_sugared`, but also needs to integrate projection bounds...
1168+ . map( |t| t. trait_ref( ) . print_only_trait_path( ) . to_string( ) )
1169+ . collect:: <Vec <_>>( )
1170+ . join( " + " ) ,
1171+ ) ) ;
1172+ err. note (
1173+ "auto-traits like `Send` and `Sync` are traits that have special properties; \
1174+ for more information on them, visit \
1175+ <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
1176+ ) ;
1177+ let reported = err. emit ( ) ;
1178+ self . set_tainted_by_errors ( reported) ;
1179+ reported
1180+ } else {
1181+ let trait_alias_span = trait_bounds
1182+ . iter ( )
1183+ . map ( |& ( trait_ref, _) | trait_ref. def_id ( ) )
1184+ . find ( |& trait_ref| tcx. is_trait_alias ( trait_ref) )
1185+ . map ( |trait_ref| tcx. def_span ( trait_ref) ) ;
1186+ let reported =
1187+ tcx. dcx ( ) . emit_err ( TraitObjectDeclaredWithNoTraits { span, trait_alias_span } ) ;
1188+ self . set_tainted_by_errors ( reported) ;
1189+ reported
1190+ }
1191+ }
10271192}
10281193
10291194/// Emits an error regarding forbidden type binding associations
0 commit comments