@@ -77,6 +77,12 @@ impl<'a, 'gcx, 'tcx> Deref for ProbeContext<'a, 'gcx, 'tcx> {
77
77
struct CandidateStep < ' tcx > {
78
78
self_ty : Ty < ' tcx > ,
79
79
autoderefs : usize ,
80
+ // true if the type results from a dereference of a raw pointer.
81
+ // when assembling candidates, we include these steps, but not when
82
+ // picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods
83
+ // `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then
84
+ // `foo.by_raw_ptr()` will work and `foo.by_ref()` won't.
85
+ from_unsafe_deref : bool ,
80
86
unsize : bool ,
81
87
}
82
88
@@ -257,6 +263,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
257
263
vec ! [ CandidateStep {
258
264
self_ty,
259
265
autoderefs: 0 ,
266
+ from_unsafe_deref: false ,
260
267
unsize: false ,
261
268
} ]
262
269
} ;
@@ -289,14 +296,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
289
296
-> Option < Vec < CandidateStep < ' tcx > > > {
290
297
// FIXME: we don't need to create the entire steps in one pass
291
298
292
- let mut autoderef = self . autoderef ( span, self_ty) ;
299
+ let mut autoderef = self . autoderef ( span, self_ty) . include_raw_pointers ( ) ;
300
+ let mut reached_raw_pointer = false ;
293
301
let mut steps: Vec < _ > = autoderef. by_ref ( )
294
302
. map ( |( ty, d) | {
295
- CandidateStep {
303
+ let step = CandidateStep {
296
304
self_ty : ty,
297
305
autoderefs : d,
306
+ from_unsafe_deref : reached_raw_pointer,
298
307
unsize : false ,
308
+ } ;
309
+ if let ty:: TyRawPtr ( _) = ty. sty {
310
+ // all the subsequent steps will be from_unsafe_deref
311
+ reached_raw_pointer = true ;
299
312
}
313
+ step
300
314
} )
301
315
. collect ( ) ;
302
316
@@ -307,9 +321,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
307
321
// a real method lookup, this is a hard error (it's an
308
322
// ambiguity and we can't make progress).
309
323
if !is_suggestion. 0 {
310
- let t = self . structurally_resolved_type ( span, final_ty) ;
311
- assert_eq ! ( t, self . tcx. types. err) ;
312
- return None
324
+ if reached_raw_pointer
325
+ && !self . tcx . sess . features . borrow ( ) . arbitrary_self_types {
326
+ // only produce a warning in this case, because inference variables used to
327
+ // be allowed here in some cases for raw pointers
328
+ struct_span_warn ! ( self . tcx. sess, span, E0619 ,
329
+ "the type of this value must be known in this context" )
330
+ . note ( "this will be made into a hard error in a future version of \
331
+ the compiler")
332
+ . emit ( ) ;
333
+ } else {
334
+ let t = self . structurally_resolved_type ( span, final_ty) ;
335
+ assert_eq ! ( t, self . tcx. types. err) ;
336
+ return None
337
+ }
313
338
} else {
314
339
// If we're just looking for suggestions,
315
340
// though, ambiguity is no big thing, we can
@@ -322,6 +347,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
322
347
steps. push ( CandidateStep {
323
348
self_ty : self . tcx . mk_slice ( elem_ty) ,
324
349
autoderefs : dereferences,
350
+ // this could be from an unsafe deref if we had
351
+ // a *mut/const [T; N]
352
+ from_unsafe_deref : reached_raw_pointer,
325
353
unsize : true ,
326
354
} ) ;
327
355
}
@@ -830,7 +858,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
830
858
. iter ( )
831
859
. filter ( |step| {
832
860
debug ! ( "pick_core: step={:?}" , step) ;
833
- !step. self_ty . references_error ( )
861
+ // skip types that are from a type error or that would require dereferencing
862
+ // a raw pointer
863
+ !step. self_ty . references_error ( ) && !step. from_unsafe_deref
834
864
} ) . flat_map ( |step| {
835
865
self . pick_by_value_method ( step) . or_else ( || {
836
866
self . pick_autorefd_method ( step, hir:: MutImmutable ) . or_else ( || {
0 commit comments