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