@@ -27,7 +27,7 @@ pub trait InferCtxtExt<'tcx> {
2727 fn suggest_restricting_param_bound (
2828 & self ,
2929 err : & mut DiagnosticBuilder < ' _ > ,
30- trait_ref : & ty:: PolyTraitRef < ' _ > ,
30+ trait_ref : ty:: PolyTraitRef < ' _ > ,
3131 body_id : hir:: HirId ,
3232 ) ;
3333
@@ -168,111 +168,104 @@ fn suggest_restriction(
168168 err : & mut DiagnosticBuilder < ' _ > ,
169169 fn_sig : Option < & hir:: FnSig < ' _ > > ,
170170 projection : Option < & ty:: ProjectionTy < ' _ > > ,
171- trait_ref : & ty:: PolyTraitRef < ' _ > ,
171+ trait_ref : ty:: PolyTraitRef < ' _ > ,
172172) {
173173 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
212208
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 ) ;
216211 }
217212 }
213+ }
218214
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+ {
246235 // `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 \
255251 `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) ;
268261 }
269262}
270263
271264impl < ' a , ' tcx > InferCtxtExt < ' tcx > for InferCtxt < ' a , ' tcx > {
272265 fn suggest_restricting_param_bound (
273266 & self ,
274267 mut err : & mut DiagnosticBuilder < ' _ > ,
275- trait_ref : & ty:: PolyTraitRef < ' _ > ,
268+ trait_ref : ty:: PolyTraitRef < ' _ > ,
276269 body_id : hir:: HirId ,
277270 ) {
278271 let self_ty = trait_ref. self_ty ( ) ;
0 commit comments