@@ -77,6 +77,12 @@ impl<'a, 'gcx, 'tcx> Deref for ProbeContext<'a, 'gcx, 'tcx> {
7777struct CandidateStep < ' tcx > {
7878 self_ty : Ty < ' tcx > ,
7979 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 ,
8086 unsize : bool ,
8187}
8288
@@ -257,6 +263,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
257263 vec ! [ CandidateStep {
258264 self_ty,
259265 autoderefs: 0 ,
266+ from_unsafe_deref: false ,
260267 unsize: false ,
261268 } ]
262269 } ;
@@ -289,14 +296,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
289296 -> Option < Vec < CandidateStep < ' tcx > > > {
290297 // FIXME: we don't need to create the entire steps in one pass
291298
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 ;
293301 let mut steps: Vec < _ > = autoderef. by_ref ( )
294302 . map ( |( ty, d) | {
295- CandidateStep {
303+ let step = CandidateStep {
296304 self_ty : ty,
297305 autoderefs : d,
306+ from_unsafe_deref : reached_raw_pointer,
298307 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 ;
299312 }
313+ step
300314 } )
301315 . collect ( ) ;
302316
@@ -307,9 +321,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
307321 // a real method lookup, this is a hard error (it's an
308322 // ambiguity and we can't make progress).
309323 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+ }
313338 } else {
314339 // If we're just looking for suggestions,
315340 // though, ambiguity is no big thing, we can
@@ -322,6 +347,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
322347 steps. push ( CandidateStep {
323348 self_ty : self . tcx . mk_slice ( elem_ty) ,
324349 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,
325353 unsize : true ,
326354 } ) ;
327355 }
@@ -830,7 +858,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
830858 . iter ( )
831859 . filter ( |step| {
832860 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
834864 } ) . flat_map ( |step| {
835865 self . pick_by_value_method ( step) . or_else ( || {
836866 self . pick_autorefd_method ( step, hir:: MutImmutable ) . or_else ( || {
0 commit comments