@@ -26,7 +26,7 @@ crate trait InferCtxtExt<'tcx> {
26
26
fn suggest_restricting_param_bound (
27
27
& self ,
28
28
err : & mut DiagnosticBuilder < ' _ > ,
29
- trait_ref : & ty:: PolyTraitRef < ' _ > ,
29
+ trait_ref : ty:: PolyTraitRef < ' _ > ,
30
30
body_id : hir:: HirId ,
31
31
) ;
32
32
@@ -167,111 +167,104 @@ fn suggest_restriction(
167
167
err : & mut DiagnosticBuilder < ' _ > ,
168
168
fn_sig : Option < & hir:: FnSig < ' _ > > ,
169
169
projection : Option < & ty:: ProjectionTy < ' _ > > ,
170
- trait_ref : & ty:: PolyTraitRef < ' _ > ,
170
+ trait_ref : ty:: PolyTraitRef < ' _ > ,
171
171
) {
172
172
let span = generics. where_clause . span_for_predicates_or_empty_place ( ) ;
173
- if !span. from_expansion ( ) && span. desugaring_kind ( ) . is_none ( ) {
174
- // Given `fn foo(t: impl Trait)` where `Trait` requires assoc type `A`...
175
- if let Some ( ( name, fn_sig) ) = fn_sig. and_then ( |sig| {
176
- projection. and_then ( |p| {
177
- // Shenanigans to get the `Trait` from the `impl Trait`.
178
- match p. self_ty ( ) . kind {
179
- ty:: Param ( param) => {
180
- // `fn foo(t: impl Trait)`
181
- // ^^^^^ get this string
182
- param
183
- . name
184
- . as_str ( )
185
- . strip_prefix ( "impl" )
186
- . map ( |s| ( s. trim_start ( ) . to_string ( ) , sig) )
187
- }
188
- _ => None ,
189
- }
190
- } )
191
- } ) {
192
- // We know we have an `impl Trait` that doesn't satisfy a required projection.
193
-
194
- // Find all of the ocurrences of `impl Trait` for `Trait` in the function arguments'
195
- // types. There should be at least one, but there might be *more* than one. In that
196
- // case we could just ignore it and try to identify which one needs the restriction,
197
- // but instead we choose to suggest replacing all instances of `impl Trait` with `T`
198
- // where `T: Trait`.
199
- let mut ty_spans = vec ! [ ] ;
200
- let impl_name = format ! ( "impl {}" , name) ;
201
- for input in fn_sig. decl . inputs {
202
- if let hir:: TyKind :: Path ( hir:: QPath :: Resolved (
203
- None ,
204
- hir:: Path { segments : [ segment] , .. } ,
205
- ) ) = input. kind
206
- {
207
- if segment. ident . as_str ( ) == impl_name. as_str ( ) {
208
- // `fn foo(t: impl Trait)`
209
- // ^^^^^^^^^^ get this to suggest
210
- // `T` instead
173
+ if span. from_expansion ( ) || span. desugaring_kind ( ) . is_some ( ) {
174
+ return ;
175
+ }
176
+ // Given `fn foo(t: impl Trait)` where `Trait` requires assoc type `A`...
177
+ if let Some ( ( name, fn_sig) ) =
178
+ fn_sig. zip ( projection) . and_then ( |( sig, p) | match p. self_ty ( ) . kind {
179
+ // Shenanigans to get the `Trait` from the `impl Trait`.
180
+ ty:: Param ( param) => {
181
+ // `fn foo(t: impl Trait)`
182
+ // ^^^^^ get this string
183
+ param. name . as_str ( ) . strip_prefix ( "impl" ) . map ( |s| ( s. trim_start ( ) . to_string ( ) , sig) )
184
+ }
185
+ _ => None ,
186
+ } )
187
+ {
188
+ // We know we have an `impl Trait` that doesn't satisfy a required projection.
189
+
190
+ // Find all of the ocurrences of `impl Trait` for `Trait` in the function arguments'
191
+ // types. There should be at least one, but there might be *more* than one. In that
192
+ // case we could just ignore it and try to identify which one needs the restriction,
193
+ // but instead we choose to suggest replacing all instances of `impl Trait` with `T`
194
+ // where `T: Trait`.
195
+ let mut ty_spans = vec ! [ ] ;
196
+ let impl_name = format ! ( "impl {}" , name) ;
197
+ for input in fn_sig. decl . inputs {
198
+ if let hir:: TyKind :: Path ( hir:: QPath :: Resolved (
199
+ None ,
200
+ hir:: Path { segments : [ segment] , .. } ,
201
+ ) ) = input. kind
202
+ {
203
+ if segment. ident . as_str ( ) == impl_name. as_str ( ) {
204
+ // `fn foo(t: impl Trait)`
205
+ // ^^^^^^^^^^ get this to suggest
206
+ // `T` instead
211
207
212
- // There might be more than one `impl Trait`.
213
- ty_spans. push ( input. span ) ;
214
- }
208
+ // There might be more than one `impl Trait`.
209
+ ty_spans. push ( input. span ) ;
215
210
}
216
211
}
212
+ }
217
213
218
- // The type param `T: Trait` we will suggest to introduce.
219
- let type_param = format ! ( "{}: {}" , "T" , name) ;
220
-
221
- // FIXME: modify the `trait_ref` instead of string shenanigans.
222
- // Turn `<impl Trait as Foo>::Bar: Qux` into `<T as Foo>::Bar: Qux`.
223
- let pred = trait_ref. without_const ( ) . to_predicate ( ) . to_string ( ) ;
224
- let pred = pred. replace ( & impl_name, "T" ) ;
225
- let mut sugg = vec ! [
226
- match generics
227
- . params
228
- . iter( )
229
- . filter( |p| match p. kind {
230
- hir:: GenericParamKind :: Type {
231
- synthetic: Some ( hir:: SyntheticTyParamKind :: ImplTrait ) ,
232
- ..
233
- } => false ,
234
- _ => true ,
235
- } )
236
- . last( )
237
- {
238
- // `fn foo(t: impl Trait)`
239
- // ^ suggest `<T: Trait>` here
240
- None => ( generics. span, format!( "<{}>" , type_param) ) ,
241
- // `fn foo<A>(t: impl Trait)`
242
- // ^^^ suggest `<A, T: Trait>` here
243
- Some ( param) => ( param. span. shrink_to_hi( ) , format!( ", {}" , type_param) ) ,
244
- } ,
214
+ // The type param `T: Trait` we will suggest to introduce.
215
+ let type_param = format ! ( "{}: {}" , "T" , name) ;
216
+
217
+ // FIXME: modify the `trait_ref` instead of string shenanigans.
218
+ // Turn `<impl Trait as Foo>::Bar: Qux` into `<T as Foo>::Bar: Qux`.
219
+ let pred = trait_ref. without_const ( ) . to_predicate ( ) . to_string ( ) ;
220
+ let pred = pred. replace ( & impl_name, "T" ) ;
221
+ let mut sugg = vec ! [
222
+ match generics
223
+ . params
224
+ . iter( )
225
+ . filter( |p| match p. kind {
226
+ hir:: GenericParamKind :: Type {
227
+ synthetic: Some ( hir:: SyntheticTyParamKind :: ImplTrait ) ,
228
+ ..
229
+ } => false ,
230
+ _ => true ,
231
+ } )
232
+ . last( )
233
+ {
245
234
// `fn foo(t: impl Trait)`
246
- // ^ suggest `where <T as Trait>::A: Bound`
247
- predicate_constraint( generics, pred) ,
248
- ] ;
249
- sugg. extend ( ty_spans. into_iter ( ) . map ( |s| ( s, "T" . to_string ( ) ) ) ) ;
250
-
251
- // Suggest `fn foo<T: Trait>(t: T) where <T as Trait>::A: Bound`.
252
- err. multipart_suggestion (
253
- "introduce a type parameter with a trait bound instead of using \
235
+ // ^ suggest `<T: Trait>` here
236
+ None => ( generics. span, format!( "<{}>" , type_param) ) ,
237
+ // `fn foo<A>(t: impl Trait)`
238
+ // ^^^ suggest `<A, T: Trait>` here
239
+ Some ( param) => ( param. span. shrink_to_hi( ) , format!( ", {}" , type_param) ) ,
240
+ } ,
241
+ // `fn foo(t: impl Trait)`
242
+ // ^ suggest `where <T as Trait>::A: Bound`
243
+ predicate_constraint( generics, pred) ,
244
+ ] ;
245
+ sugg. extend ( ty_spans. into_iter ( ) . map ( |s| ( s, "T" . to_string ( ) ) ) ) ;
246
+
247
+ // Suggest `fn foo<T: Trait>(t: T) where <T as Trait>::A: Bound`.
248
+ err. multipart_suggestion (
249
+ "introduce a type parameter with a trait bound instead of using \
254
250
`impl Trait`",
255
- sugg,
256
- Applicability :: MaybeIncorrect ,
257
- ) ;
258
- } else {
259
- // Trivial case: `T` needs an extra bound: `T: Bound`.
260
- let ( sp, s) = predicate_constraint (
261
- generics,
262
- trait_ref. without_const ( ) . to_predicate ( ) . to_string ( ) ,
263
- ) ;
264
- let appl = Applicability :: MachineApplicable ;
265
- err. span_suggestion ( sp, & format ! ( "consider further restricting {}" , msg) , s, appl) ;
266
- }
251
+ sugg,
252
+ Applicability :: MaybeIncorrect ,
253
+ ) ;
254
+ } else {
255
+ // Trivial case: `T` needs an extra bound: `T: Bound`.
256
+ let ( sp, s) =
257
+ predicate_constraint ( generics, trait_ref. without_const ( ) . to_predicate ( ) . to_string ( ) ) ;
258
+ let appl = Applicability :: MachineApplicable ;
259
+ err. span_suggestion ( sp, & format ! ( "consider further restricting {}" , msg) , s, appl) ;
267
260
}
268
261
}
269
262
270
263
impl < ' a , ' tcx > InferCtxtExt < ' tcx > for InferCtxt < ' a , ' tcx > {
271
264
fn suggest_restricting_param_bound (
272
265
& self ,
273
266
mut err : & mut DiagnosticBuilder < ' _ > ,
274
- trait_ref : & ty:: PolyTraitRef < ' _ > ,
267
+ trait_ref : ty:: PolyTraitRef < ' _ > ,
275
268
body_id : hir:: HirId ,
276
269
) {
277
270
let self_ty = trait_ref. self_ty ( ) ;
0 commit comments