1
1
use crate :: errors:: {
2
2
self , AssocTypeBindingNotAllowed , ManualImplementation , MissingTypeParams ,
3
- ParenthesizedFnTraitExpansion ,
3
+ ParenthesizedFnTraitExpansion , TraitObjectDeclaredWithNoTraits ,
4
4
} ;
5
5
use crate :: fluent_generated as fluent;
6
6
use crate :: hir_ty_lowering:: HirTyLowerer ;
7
7
use crate :: traits:: error_reporting:: report_object_safety_error;
8
8
use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
9
9
use rustc_data_structures:: sorted_map:: SortedMap ;
10
10
use rustc_data_structures:: unord:: UnordMap ;
11
+ use rustc_errors:: MultiSpan ;
11
12
use rustc_errors:: {
12
13
codes:: * , pluralize, struct_span_code_err, Applicability , Diag , ErrorGuaranteed ,
13
14
} ;
@@ -16,11 +17,22 @@ use rustc_hir::def_id::{DefId, LocalDefId};
16
17
use rustc_infer:: traits:: FulfillmentError ;
17
18
use rustc_middle:: query:: Key ;
18
19
use rustc_middle:: ty:: { self , suggest_constraining_type_param, Ty , TyCtxt , TypeVisitableExt } ;
20
+ use rustc_middle:: ty:: { Binder , TraitRef } ;
19
21
use rustc_session:: parse:: feature_err;
20
22
use rustc_span:: edit_distance:: find_best_match_for_name;
21
23
use rustc_span:: symbol:: { sym, Ident } ;
22
24
use 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
+ }
24
36
25
37
impl < ' tcx > dyn HirTyLowerer < ' tcx > + ' _ {
26
38
/// On missing type parameters, emit an E0393 error and provide a structured suggestion using
@@ -1024,6 +1036,159 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1024
1036
Ok ( ( ) )
1025
1037
}
1026
1038
}
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
+ }
1027
1192
}
1028
1193
1029
1194
/// Emits an error regarding forbidden type binding associations
0 commit comments