11use crate :: FnCtxt ;
22use rustc_hir as hir;
3- use rustc_hir:: def:: Res ;
3+ use rustc_hir:: def:: { DefKind , Res } ;
44use rustc_hir:: def_id:: DefId ;
55use rustc_infer:: { infer:: type_variable:: TypeVariableOriginKind , traits:: ObligationCauseCode } ;
66use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable , TypeVisitor } ;
@@ -133,15 +133,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
133133 }
134134 }
135135 }
136- // Notably, we only point to params that are local to the
137- // item we're checking, since those are the ones we are able
138- // to look in the final `hir::PathSegment` for. Everything else
139- // would require a deeper search into the `qpath` than I think
140- // is worthwhile.
141- if let Some ( param_to_point_at) = param_to_point_at
142- && self . point_at_path_if_possible ( error, def_id, param_to_point_at, qpath)
136+
137+ for param in [ param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
138+ . into_iter ( )
139+ . flatten ( )
143140 {
144- return true ;
141+ if self . point_at_path_if_possible ( error, def_id, param, qpath) {
142+ return true ;
143+ }
145144 }
146145 }
147146 hir:: ExprKind :: MethodCall ( segment, receiver, args, ..) => {
@@ -166,12 +165,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
166165 {
167166 return true ;
168167 }
168+ // Handle `Self` param specifically, since it's separated in
169+ // the method call representation
170+ if self_param_to_point_at. is_some ( ) {
171+ error. obligation . cause . span = receiver
172+ . span
173+ . find_ancestor_in_same_ctxt ( error. obligation . cause . span )
174+ . unwrap_or ( receiver. span ) ;
175+ return true ;
176+ }
169177 }
170178 hir:: ExprKind :: Struct ( qpath, fields, ..) => {
171- if let Res :: Def (
172- hir:: def:: DefKind :: Struct | hir:: def:: DefKind :: Variant ,
173- variant_def_id,
174- ) = self . typeck_results . borrow ( ) . qpath_res ( qpath, hir_id)
179+ if let Res :: Def ( DefKind :: Struct | DefKind :: Variant , variant_def_id) =
180+ self . typeck_results . borrow ( ) . qpath_res ( qpath, hir_id)
175181 {
176182 for param in
177183 [ param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
@@ -193,10 +199,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
193199 }
194200 }
195201 }
196- if let Some ( param_to_point_at) = param_to_point_at
197- && self . point_at_path_if_possible ( error, def_id, param_to_point_at, qpath)
202+
203+ for param in [ param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
204+ . into_iter ( )
205+ . flatten ( )
198206 {
199- return true ;
207+ if self . point_at_path_if_possible ( error, def_id, param, qpath) {
208+ return true ;
209+ }
200210 }
201211 }
202212 _ => { }
@@ -213,17 +223,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
213223 qpath : & hir:: QPath < ' tcx > ,
214224 ) -> bool {
215225 match qpath {
216- hir:: QPath :: Resolved ( _, path) => {
217- if let Some ( segment) = path. segments . last ( )
218- && self . point_at_generic_if_possible ( error, def_id, param, segment)
226+ hir:: QPath :: Resolved ( self_ty, path) => {
227+ for segment in path. segments . iter ( ) . rev ( ) {
228+ if let Res :: Def ( kind, def_id) = segment. res
229+ && !matches ! ( kind, DefKind :: Mod | DefKind :: ForeignMod )
230+ && self . point_at_generic_if_possible ( error, def_id, param, segment)
231+ {
232+ return true ;
233+ }
234+ }
235+ // Handle `Self` param specifically, since it's separated in
236+ // the path representation
237+ if let Some ( self_ty) = self_ty
238+ && let ty:: GenericArgKind :: Type ( ty) = param. unpack ( )
239+ && ty == self . tcx . types . self_param
219240 {
241+ error. obligation . cause . span = self_ty
242+ . span
243+ . find_ancestor_in_same_ctxt ( error. obligation . cause . span )
244+ . unwrap_or ( self_ty. span ) ;
220245 return true ;
221246 }
222247 }
223- hir:: QPath :: TypeRelative ( _ , segment) => {
248+ hir:: QPath :: TypeRelative ( self_ty , segment) => {
224249 if self . point_at_generic_if_possible ( error, def_id, param, segment) {
225250 return true ;
226251 }
252+ // Handle `Self` param specifically, since it's separated in
253+ // the path representation
254+ if let ty:: GenericArgKind :: Type ( ty) = param. unpack ( )
255+ && ty == self . tcx . types . self_param
256+ {
257+ error. obligation . cause . span = self_ty
258+ . span
259+ . find_ancestor_in_same_ctxt ( error. obligation . cause . span )
260+ . unwrap_or ( self_ty. span ) ;
261+ return true ;
262+ }
227263 }
228264 _ => { }
229265 }
@@ -618,14 +654,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
618654 } ;
619655
620656 let variant_def_id = match expr_struct_def_kind {
621- hir :: def :: DefKind :: Struct => {
657+ DefKind :: Struct => {
622658 if in_ty_adt. did ( ) != expr_struct_def_id {
623659 // FIXME: Deal with type aliases?
624660 return Err ( expr) ;
625661 }
626662 expr_struct_def_id
627663 }
628- hir :: def :: DefKind :: Variant => {
664+ DefKind :: Variant => {
629665 // If this is a variant, its parent is the type definition.
630666 if in_ty_adt. did ( ) != self . tcx . parent ( expr_struct_def_id) {
631667 // FIXME: Deal with type aliases?
@@ -727,14 +763,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
727763 } ;
728764
729765 let variant_def_id = match expr_struct_def_kind {
730- hir :: def :: DefKind :: Ctor ( hir:: def:: CtorOf :: Struct , hir:: def:: CtorKind :: Fn ) => {
766+ DefKind :: Ctor ( hir:: def:: CtorOf :: Struct , hir:: def:: CtorKind :: Fn ) => {
731767 if in_ty_adt. did ( ) != self . tcx . parent ( expr_ctor_def_id) {
732768 // FIXME: Deal with type aliases?
733769 return Err ( expr) ;
734770 }
735771 self . tcx . parent ( expr_ctor_def_id)
736772 }
737- hir :: def :: DefKind :: Ctor ( hir:: def:: CtorOf :: Variant , hir:: def:: CtorKind :: Fn ) => {
773+ DefKind :: Ctor ( hir:: def:: CtorOf :: Variant , hir:: def:: CtorKind :: Fn ) => {
738774 // For a typical enum like
739775 // `enum Blah<T> { Variant(T) }`
740776 // we get the following resolutions:
0 commit comments