@@ -26,7 +26,7 @@ crate trait InferCtxtExt<'tcx> {
2626 fn suggest_restricting_param_bound (
2727 & self ,
2828 err : & mut DiagnosticBuilder < ' _ > ,
29- trait_ref : & ty:: PolyTraitRef < ' _ > ,
29+ trait_ref : ty:: PolyTraitRef < ' _ > ,
3030 body_id : hir:: HirId ,
3131 ) ;
3232
@@ -167,111 +167,104 @@ fn suggest_restriction(
167167 err : & mut DiagnosticBuilder < ' _ > ,
168168 fn_sig : Option < & hir:: FnSig < ' _ > > ,
169169 projection : Option < & ty:: ProjectionTy < ' _ > > ,
170- trait_ref : & ty:: PolyTraitRef < ' _ > ,
170+ trait_ref : ty:: PolyTraitRef < ' _ > ,
171171) {
172172 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
211207
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 ) ;
215210 }
216211 }
212+ }
217213
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+ {
245234 // `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 \
254250 `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) ;
267260 }
268261}
269262
270263impl < ' a , ' tcx > InferCtxtExt < ' tcx > for InferCtxt < ' a , ' tcx > {
271264 fn suggest_restricting_param_bound (
272265 & self ,
273266 mut err : & mut DiagnosticBuilder < ' _ > ,
274- trait_ref : & ty:: PolyTraitRef < ' _ > ,
267+ trait_ref : ty:: PolyTraitRef < ' _ > ,
275268 body_id : hir:: HirId ,
276269 ) {
277270 let self_ty = trait_ref. self_ty ( ) ;
0 commit comments