@@ -84,9 +84,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
84
84
rustc_errors:: struct_span_code_err!( self . dcx( ) , self_ty. span, E0782 , "{}" , msg) ;
85
85
if self_ty. span . can_be_used_for_suggestions ( )
86
86
&& !self . maybe_suggest_impl_trait ( self_ty, & mut diag)
87
+ && !self . maybe_suggest_dyn_trait ( self_ty, label, sugg, & mut diag)
87
88
{
88
- // FIXME: Only emit this suggestion if the trait is dyn-compatible.
89
- diag. multipart_suggestion_verbose ( label, sugg, Applicability :: MachineApplicable ) ;
89
+ self . maybe_suggest_add_generic_impl_trait ( self_ty, & mut diag) ;
90
90
}
91
91
// Check if the impl trait that we are considering is an impl of a local trait.
92
92
self . maybe_suggest_blanket_trait_impl ( self_ty, & mut diag) ;
@@ -123,6 +123,33 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
123
123
}
124
124
}
125
125
126
+ fn maybe_suggest_add_generic_impl_trait (
127
+ & self ,
128
+ self_ty : & hir:: Ty < ' _ > ,
129
+ diag : & mut Diag < ' _ > ,
130
+ ) -> bool {
131
+ let tcx = self . tcx ( ) ;
132
+ let msg = "you might be missing a type parameter" ;
133
+ let mut sugg = vec ! [ ] ;
134
+
135
+ let parent_id = tcx. hir_get_parent_item ( self_ty. hir_id ) . def_id ;
136
+ let parent_item = tcx. hir_node_by_def_id ( parent_id) . expect_item ( ) ;
137
+ match parent_item. kind {
138
+ hir:: ItemKind :: Struct ( _, generics) | hir:: ItemKind :: Enum ( _, generics) => {
139
+ sugg. push ( (
140
+ generics. where_clause_span ,
141
+ format ! (
142
+ "<T: {}>" ,
143
+ self . tcx( ) . sess. source_map( ) . span_to_snippet( self_ty. span) . unwrap( )
144
+ ) ,
145
+ ) ) ;
146
+ sugg. push ( ( self_ty. span , "T" . to_string ( ) ) ) ;
147
+ }
148
+ _ => { }
149
+ }
150
+ diag. multipart_suggestion_verbose ( msg, sugg, Applicability :: MachineApplicable ) ;
151
+ true
152
+ }
126
153
/// Make sure that we are in the condition to suggest the blanket implementation.
127
154
fn maybe_suggest_blanket_trait_impl < G : EmissionGuarantee > (
128
155
& self ,
@@ -171,6 +198,38 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
171
198
}
172
199
}
173
200
201
+ fn maybe_suggest_dyn_trait (
202
+ & self ,
203
+ self_ty : & hir:: Ty < ' _ > ,
204
+ label : & str ,
205
+ sugg : Vec < ( Span , String ) > ,
206
+ diag : & mut Diag < ' _ > ,
207
+ ) -> bool {
208
+ let tcx = self . tcx ( ) ;
209
+ let parent_id = tcx. hir_get_parent_item ( self_ty. hir_id ) . def_id ;
210
+ let parent_item = tcx. hir_node_by_def_id ( parent_id) . expect_item ( ) ;
211
+
212
+ // If the parent item is an enum, don't suggest the dyn trait.
213
+ if let hir:: ItemKind :: Enum ( ..) = parent_item. kind {
214
+ return false ;
215
+ }
216
+
217
+ // If the parent item is a struct, check if self_ty is the last field.
218
+ if let hir:: ItemKind :: Struct ( variant_data, _) = parent_item. kind {
219
+ if variant_data. fields ( ) . last ( ) . unwrap ( ) . ty . span != self_ty. span {
220
+ return false ;
221
+ }
222
+ }
223
+
224
+ // FIXME: Only emit this suggestion if the trait is dyn-compatible.
225
+ diag. multipart_suggestion_verbose (
226
+ label. to_string ( ) ,
227
+ sugg,
228
+ Applicability :: MachineApplicable ,
229
+ ) ;
230
+ true
231
+ }
232
+
174
233
fn add_generic_param_suggestion (
175
234
& self ,
176
235
generics : & hir:: Generics < ' _ > ,
0 commit comments