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,14 @@ 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
+ } ;
24
28
25
29
impl < ' tcx > dyn HirTyLowerer < ' tcx > + ' _ {
26
30
/// On missing type parameters, emit an E0393 error and provide a structured suggestion using
@@ -1024,15 +1028,179 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1024
1028
Ok ( ( ) )
1025
1029
}
1026
1030
}
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
+ }
1027
1195
}
1028
1196
1029
1197
/// Emits an error regarding forbidden type binding associations
1030
1198
pub fn prohibit_assoc_item_binding (
1031
1199
tcx : TyCtxt < ' _ > ,
1032
1200
span : Span ,
1033
1201
segment : Option < ( & hir:: PathSegment < ' _ > , Span ) > ,
1034
- ) {
1035
- tcx. dcx ( ) . emit_err ( AssocTypeBindingNotAllowed {
1202
+ ) -> ErrorGuaranteed {
1203
+ return tcx. dcx ( ) . emit_err ( AssocTypeBindingNotAllowed {
1036
1204
span,
1037
1205
fn_trait_expansion : if let Some ( ( segment, span) ) = segment
1038
1206
&& segment. args ( ) . parenthesized == hir:: GenericArgsParentheses :: ParenSugar
0 commit comments