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