1
1
use crate :: FnCtxt ;
2
2
use rustc_hir as hir;
3
- use rustc_hir:: def:: Res ;
3
+ use rustc_hir:: def:: { DefKind , Res } ;
4
4
use rustc_hir:: def_id:: DefId ;
5
5
use rustc_infer:: { infer:: type_variable:: TypeVariableOriginKind , traits:: ObligationCauseCode } ;
6
6
use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable , TypeVisitor } ;
@@ -133,15 +133,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
133
133
}
134
134
}
135
135
}
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 ( )
143
140
{
144
- return true ;
141
+ if self . point_at_path_if_possible ( error, def_id, param, qpath) {
142
+ return true ;
143
+ }
145
144
}
146
145
}
147
146
hir:: ExprKind :: MethodCall ( segment, receiver, args, ..) => {
@@ -166,12 +165,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
166
165
{
167
166
return true ;
168
167
}
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
+ }
169
177
}
170
178
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)
175
181
{
176
182
for param in
177
183
[ param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
@@ -193,10 +199,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
193
199
}
194
200
}
195
201
}
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 ( )
198
206
{
199
- return true ;
207
+ if self . point_at_path_if_possible ( error, def_id, param, qpath) {
208
+ return true ;
209
+ }
200
210
}
201
211
}
202
212
_ => { }
@@ -213,17 +223,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
213
223
qpath : & hir:: QPath < ' tcx > ,
214
224
) -> bool {
215
225
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
219
240
{
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 ) ;
220
245
return true ;
221
246
}
222
247
}
223
- hir:: QPath :: TypeRelative ( _ , segment) => {
248
+ hir:: QPath :: TypeRelative ( self_ty , segment) => {
224
249
if self . point_at_generic_if_possible ( error, def_id, param, segment) {
225
250
return true ;
226
251
}
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
+ }
227
263
}
228
264
_ => { }
229
265
}
@@ -618,14 +654,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
618
654
} ;
619
655
620
656
let variant_def_id = match expr_struct_def_kind {
621
- hir :: def :: DefKind :: Struct => {
657
+ DefKind :: Struct => {
622
658
if in_ty_adt. did ( ) != expr_struct_def_id {
623
659
// FIXME: Deal with type aliases?
624
660
return Err ( expr) ;
625
661
}
626
662
expr_struct_def_id
627
663
}
628
- hir :: def :: DefKind :: Variant => {
664
+ DefKind :: Variant => {
629
665
// If this is a variant, its parent is the type definition.
630
666
if in_ty_adt. did ( ) != self . tcx . parent ( expr_struct_def_id) {
631
667
// FIXME: Deal with type aliases?
@@ -727,14 +763,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
727
763
} ;
728
764
729
765
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 ) => {
731
767
if in_ty_adt. did ( ) != self . tcx . parent ( expr_ctor_def_id) {
732
768
// FIXME: Deal with type aliases?
733
769
return Err ( expr) ;
734
770
}
735
771
self . tcx . parent ( expr_ctor_def_id)
736
772
}
737
- hir :: def :: DefKind :: Ctor ( hir:: def:: CtorOf :: Variant , hir:: def:: CtorKind :: Fn ) => {
773
+ DefKind :: Ctor ( hir:: def:: CtorOf :: Variant , hir:: def:: CtorKind :: Fn ) => {
738
774
// For a typical enum like
739
775
// `enum Blah<T> { Variant(T) }`
740
776
// we get the following resolutions:
0 commit comments