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