@@ -127,7 +127,7 @@ struct CollectItemTypesVisitor<'tcx> {
127127/// all already existing generic type parameters to avoid suggesting a name that is already in use.
128128crate fn placeholder_type_error (
129129 tcx : TyCtxt < ' tcx > ,
130- ident_span : Span ,
130+ span : Span ,
131131 generics : & [ hir:: GenericParam < ' _ > ] ,
132132 placeholder_types : Vec < Span > ,
133133 suggest : bool ,
@@ -153,7 +153,14 @@ crate fn placeholder_type_error(
153153 let mut sugg: Vec < _ > =
154154 placeholder_types. iter ( ) . map ( |sp| ( * sp, type_name. to_string ( ) ) ) . collect ( ) ;
155155 if generics. is_empty ( ) {
156- sugg. push ( ( ident_span. shrink_to_hi ( ) , format ! ( "<{}>" , type_name) ) ) ;
156+ sugg. push ( ( span, format ! ( "<{}>" , type_name) ) ) ;
157+ } else if let Some ( arg) = generics. iter ( ) . find ( |arg| match arg. name {
158+ hir:: ParamName :: Plain ( Ident { name : kw:: Underscore , .. } ) => true ,
159+ _ => false ,
160+ } ) {
161+ // Account for `_` already present in cases like `struct S<_>(_);` and suggest
162+ // `struct S<T>(T);` instead of `struct S<_, T>(T);`.
163+ sugg. push ( ( arg. span , format ! ( "{}" , type_name) ) ) ;
157164 } else {
158165 sugg. push ( (
159166 generics. iter ( ) . last ( ) . unwrap ( ) . span . shrink_to_hi ( ) ,
@@ -175,16 +182,20 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir
175182 let ( generics, suggest) = match & item. kind {
176183 hir:: ItemKind :: Union ( _, generics)
177184 | hir:: ItemKind :: Enum ( _, generics)
178- | hir:: ItemKind :: Struct ( _, generics) => ( & generics. params [ ..] , true ) ,
179- hir:: ItemKind :: TyAlias ( _, generics) => ( & generics. params [ ..] , false ) ,
185+ | hir:: ItemKind :: TraitAlias ( generics, _)
186+ | hir:: ItemKind :: Trait ( _, _, generics, ..)
187+ | hir:: ItemKind :: Impl ( _, _, _, generics, ..)
188+ | hir:: ItemKind :: Struct ( _, generics) => ( generics, true ) ,
189+ hir:: ItemKind :: OpaqueTy ( hir:: OpaqueTy { generics, .. } )
190+ | hir:: ItemKind :: TyAlias ( _, generics) => ( generics, false ) ,
180191 // `static`, `fn` and `const` are handled elsewhere to suggest appropriate type.
181192 _ => return ,
182193 } ;
183194
184195 let mut visitor = PlaceholderHirTyCollector :: default ( ) ;
185196 visitor. visit_item ( item) ;
186197
187- placeholder_type_error ( tcx, item . ident . span , generics, visitor. 0 , suggest) ;
198+ placeholder_type_error ( tcx, generics . span , & generics. params [ .. ] , visitor. 0 , suggest) ;
188199}
189200
190201impl Visitor < ' tcx > for CollectItemTypesVisitor < ' tcx > {
@@ -1798,10 +1809,19 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
17981809/// Whether `ty` is a type with `_` placeholders that can be infered. Used in diagnostics only to
17991810/// use inference to provide suggestions for the appropriate type if possible.
18001811fn is_suggestable_infer_ty ( ty : & hir:: Ty < ' _ > ) -> bool {
1812+ use hir:: TyKind :: * ;
18011813 match & ty. kind {
1802- hir:: TyKind :: Infer => true ,
1803- hir:: TyKind :: Slice ( ty) | hir:: TyKind :: Array ( ty, _) => is_suggestable_infer_ty ( ty) ,
1804- hir:: TyKind :: Tup ( tys) => tys. iter ( ) . any ( |ty| is_suggestable_infer_ty ( ty) ) ,
1814+ Infer => true ,
1815+ Slice ( ty) | Array ( ty, _) => is_suggestable_infer_ty ( ty) ,
1816+ Tup ( tys) => tys. iter ( ) . any ( is_suggestable_infer_ty) ,
1817+ Ptr ( mut_ty) | Rptr ( _, mut_ty) => is_suggestable_infer_ty ( mut_ty. ty ) ,
1818+ Def ( _, generic_args) => generic_args
1819+ . iter ( )
1820+ . filter_map ( |arg| match arg {
1821+ hir:: GenericArg :: Type ( ty) => Some ( ty) ,
1822+ _ => None ,
1823+ } )
1824+ . any ( is_suggestable_infer_ty) ,
18051825 _ => false ,
18061826 }
18071827}
0 commit comments