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,14 @@ 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+ } ;
2428
2529impl < ' tcx > dyn HirTyLowerer < ' tcx > + ' _ {
2630 /// On missing type parameters, emit an E0393 error and provide a structured suggestion using
@@ -1024,15 +1028,179 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10241028 Ok ( ( ) )
10251029 }
10261030 }
1031+
1032+ pub fn report_prohibit_generics_error < ' a > (
1033+ & self ,
1034+ segments : impl Iterator < Item = & ' a hir:: PathSegment < ' a > > + Clone ,
1035+ args_visitors : impl Iterator < Item = & ' a hir:: GenericArg < ' a > > + Clone ,
1036+ extend : impl Fn ( & mut Diag < ' _ > ) ,
1037+ ) -> ErrorGuaranteed {
1038+ #[ derive( PartialEq , Eq , Hash ) ]
1039+ enum ProhibitGenericsArg {
1040+ Lifetime ,
1041+ Type ,
1042+ Const ,
1043+ Infer ,
1044+ }
1045+
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+ regular_traits : & Vec < TraitAliasExpansionInfo < ' _ > > ,
1143+ ) -> ErrorGuaranteed {
1144+ let tcx = self . tcx ( ) ;
1145+ let first_trait = & regular_traits[ 0 ] ;
1146+ let additional_trait = & regular_traits[ 1 ] ;
1147+ let mut err = struct_span_code_err ! (
1148+ tcx. dcx( ) ,
1149+ additional_trait. bottom( ) . 1 ,
1150+ E0225 ,
1151+ "only auto traits can be used as additional traits in a trait object"
1152+ ) ;
1153+ additional_trait. label_with_exp_info (
1154+ & mut err,
1155+ "additional non-auto trait" ,
1156+ "additional use" ,
1157+ ) ;
1158+ first_trait. label_with_exp_info ( & mut err, "first non-auto trait" , "first use" ) ;
1159+ err. help ( format ! (
1160+ "consider creating a new trait with all of these as supertraits and using that \
1161+ trait here instead: `trait NewTrait: {} {{}}`",
1162+ regular_traits
1163+ . iter( )
1164+ // FIXME: This should `print_sugared`, but also needs to integrate projection bounds...
1165+ . map( |t| t. trait_ref( ) . print_only_trait_path( ) . to_string( ) )
1166+ . collect:: <Vec <_>>( )
1167+ . join( " + " ) ,
1168+ ) ) ;
1169+ err. note (
1170+ "auto-traits like `Send` and `Sync` are traits that have special properties; \
1171+ for more information on them, visit \
1172+ <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
1173+ ) ;
1174+ let reported = err. emit ( ) ;
1175+ self . set_tainted_by_errors ( reported) ;
1176+ reported
1177+ }
1178+
1179+ pub fn report_trait_object_with_no_traits_error (
1180+ & self ,
1181+ span : Span ,
1182+ trait_bounds : & Vec < ( Binder < ' tcx , TraitRef < ' tcx > > , Span ) > ,
1183+ ) -> ErrorGuaranteed {
1184+ let tcx = self . tcx ( ) ;
1185+ let trait_alias_span = trait_bounds
1186+ . iter ( )
1187+ . map ( |& ( trait_ref, _) | trait_ref. def_id ( ) )
1188+ . find ( |& trait_ref| tcx. is_trait_alias ( trait_ref) )
1189+ . map ( |trait_ref| tcx. def_span ( trait_ref) ) ;
1190+ let reported =
1191+ tcx. dcx ( ) . emit_err ( TraitObjectDeclaredWithNoTraits { span, trait_alias_span } ) ;
1192+ self . set_tainted_by_errors ( reported) ;
1193+ reported
1194+ }
10271195}
10281196
10291197/// Emits an error regarding forbidden type binding associations
10301198pub fn prohibit_assoc_item_binding (
10311199 tcx : TyCtxt < ' _ > ,
10321200 span : Span ,
10331201 segment : Option < ( & hir:: PathSegment < ' _ > , Span ) > ,
1034- ) {
1035- tcx. dcx ( ) . emit_err ( AssocTypeBindingNotAllowed {
1202+ ) -> ErrorGuaranteed {
1203+ return tcx. dcx ( ) . emit_err ( AssocTypeBindingNotAllowed {
10361204 span,
10371205 fn_trait_expansion : if let Some ( ( segment, span) ) = segment
10381206 && segment. args ( ) . parenthesized == hir:: GenericArgsParentheses :: ParenSugar
0 commit comments