@@ -127,7 +127,7 @@ struct CollectItemTypesVisitor<'tcx> {
127
127
/// all already existing generic type parameters to avoid suggesting a name that is already in use.
128
128
crate fn placeholder_type_error (
129
129
tcx : TyCtxt < ' tcx > ,
130
- ident_span : Span ,
130
+ span : Span ,
131
131
generics : & [ hir:: GenericParam < ' _ > ] ,
132
132
placeholder_types : Vec < Span > ,
133
133
suggest : bool ,
@@ -153,7 +153,14 @@ crate fn placeholder_type_error(
153
153
let mut sugg: Vec < _ > =
154
154
placeholder_types. iter ( ) . map ( |sp| ( * sp, type_name. to_string ( ) ) ) . collect ( ) ;
155
155
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) ) ) ;
157
164
} else {
158
165
sugg. push ( (
159
166
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
175
182
let ( generics, suggest) = match & item. kind {
176
183
hir:: ItemKind :: Union ( _, generics)
177
184
| 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 ) ,
180
191
// `static`, `fn` and `const` are handled elsewhere to suggest appropriate type.
181
192
_ => return ,
182
193
} ;
183
194
184
195
let mut visitor = PlaceholderHirTyCollector :: default ( ) ;
185
196
visitor. visit_item ( item) ;
186
197
187
- placeholder_type_error ( tcx, item . ident . span , generics, visitor. 0 , suggest) ;
198
+ placeholder_type_error ( tcx, generics . span , & generics. params [ .. ] , visitor. 0 , suggest) ;
188
199
}
189
200
190
201
impl Visitor < ' tcx > for CollectItemTypesVisitor < ' tcx > {
@@ -1798,10 +1809,19 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
1798
1809
/// Whether `ty` is a type with `_` placeholders that can be infered. Used in diagnostics only to
1799
1810
/// use inference to provide suggestions for the appropriate type if possible.
1800
1811
fn is_suggestable_infer_ty ( ty : & hir:: Ty < ' _ > ) -> bool {
1812
+ use hir:: TyKind :: * ;
1801
1813
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) ,
1805
1825
_ => false ,
1806
1826
}
1807
1827
}
0 commit comments