@@ -124,7 +124,7 @@ struct CollectItemTypesVisitor<'tcx> {
124124/// all already existing generic type parameters to avoid suggesting a name that is already in use.
125125crate fn placeholder_type_error (
126126 tcx : TyCtxt < ' tcx > ,
127- ident_span : Span ,
127+ span : Span ,
128128 generics : & [ hir:: GenericParam < ' _ > ] ,
129129 placeholder_types : Vec < Span > ,
130130 suggest : bool ,
@@ -150,7 +150,14 @@ crate fn placeholder_type_error(
150150 let mut sugg: Vec < _ > =
151151 placeholder_types. iter ( ) . map ( |sp| ( * sp, type_name. to_string ( ) ) ) . collect ( ) ;
152152 if generics. is_empty ( ) {
153- sugg. push ( ( ident_span. shrink_to_hi ( ) , format ! ( "<{}>" , type_name) ) ) ;
153+ sugg. push ( ( span, format ! ( "<{}>" , type_name) ) ) ;
154+ } else if let Some ( arg) = generics. iter ( ) . find ( |arg| match arg. name {
155+ hir:: ParamName :: Plain ( Ident { name : kw:: Underscore , .. } ) => true ,
156+ _ => false ,
157+ } ) {
158+ // Account for `_` already present in cases like `struct S<_>(_);` and suggest
159+ // `struct S<T>(T);` instead of `struct S<_, T>(T);`.
160+ sugg. push ( ( arg. span , format ! ( "{}" , type_name) ) ) ;
154161 } else {
155162 sugg. push ( (
156163 generics. iter ( ) . last ( ) . unwrap ( ) . span . shrink_to_hi ( ) ,
@@ -172,16 +179,20 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir
172179 let ( generics, suggest) = match & item. kind {
173180 hir:: ItemKind :: Union ( _, generics)
174181 | hir:: ItemKind :: Enum ( _, generics)
175- | hir:: ItemKind :: Struct ( _, generics) => ( & generics. params [ ..] , true ) ,
176- hir:: ItemKind :: TyAlias ( _, generics) => ( & generics. params [ ..] , false ) ,
182+ | hir:: ItemKind :: TraitAlias ( generics, _)
183+ | hir:: ItemKind :: Trait ( _, _, generics, ..)
184+ | hir:: ItemKind :: Impl ( _, _, _, generics, ..)
185+ | hir:: ItemKind :: Struct ( _, generics) => ( generics, true ) ,
186+ hir:: ItemKind :: OpaqueTy ( hir:: OpaqueTy { generics, .. } )
187+ | hir:: ItemKind :: TyAlias ( _, generics) => ( generics, false ) ,
177188 // `static`, `fn` and `const` are handled elsewhere to suggest appropriate type.
178189 _ => return ,
179190 } ;
180191
181192 let mut visitor = PlaceholderHirTyCollector :: default ( ) ;
182193 visitor. visit_item ( item) ;
183194
184- placeholder_type_error ( tcx, item . ident . span , generics, visitor. 0 , suggest) ;
195+ placeholder_type_error ( tcx, generics . span , & generics. params [ .. ] , visitor. 0 , suggest) ;
185196}
186197
187198impl Visitor < ' tcx > for CollectItemTypesVisitor < ' tcx > {
@@ -1789,10 +1800,19 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
17891800/// Whether `ty` is a type with `_` placeholders that can be infered. Used in diagnostics only to
17901801/// use inference to provide suggestions for the appropriate type if possible.
17911802fn is_suggestable_infer_ty ( ty : & hir:: Ty < ' _ > ) -> bool {
1803+ use hir:: TyKind :: * ;
17921804 match & ty. kind {
1793- hir:: TyKind :: Infer => true ,
1794- hir:: TyKind :: Slice ( ty) | hir:: TyKind :: Array ( ty, _) => is_suggestable_infer_ty ( ty) ,
1795- hir:: TyKind :: Tup ( tys) => tys. iter ( ) . any ( |ty| is_suggestable_infer_ty ( ty) ) ,
1805+ Infer => true ,
1806+ Slice ( ty) | Array ( ty, _) => is_suggestable_infer_ty ( ty) ,
1807+ Tup ( tys) => tys. iter ( ) . any ( is_suggestable_infer_ty) ,
1808+ Ptr ( mut_ty) | Rptr ( _, mut_ty) => is_suggestable_infer_ty ( mut_ty. ty ) ,
1809+ Def ( _, generic_args) => generic_args
1810+ . iter ( )
1811+ . filter_map ( |arg| match arg {
1812+ hir:: GenericArg :: Type ( ty) => Some ( ty) ,
1813+ _ => None ,
1814+ } )
1815+ . any ( is_suggestable_infer_ty) ,
17961816 _ => false ,
17971817 }
17981818}
0 commit comments