@@ -84,9 +84,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
8484 rustc_errors:: struct_span_code_err!( self . dcx( ) , self_ty. span, E0782 , "{}" , msg) ;
8585 if self_ty. span . can_be_used_for_suggestions ( )
8686 && !self . maybe_suggest_impl_trait ( self_ty, & mut diag)
87+ && !self . maybe_suggest_dyn_trait ( self_ty, label, sugg, & mut diag)
8788 {
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) ;
9090 }
9191 // Check if the impl trait that we are considering is an impl of a local trait.
9292 self . maybe_suggest_blanket_trait_impl ( self_ty, & mut diag) ;
@@ -123,6 +123,33 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
123123 }
124124 }
125125
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+ }
126153 /// Make sure that we are in the condition to suggest the blanket implementation.
127154 fn maybe_suggest_blanket_trait_impl < G : EmissionGuarantee > (
128155 & self ,
@@ -171,6 +198,38 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
171198 }
172199 }
173200
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+
174233 fn add_generic_param_suggestion (
175234 & self ,
176235 generics : & hir:: Generics < ' _ > ,
0 commit comments