8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use astconv:: ExplicitSelf ;
12
11
use check:: { Inherited , FnCtxt } ;
13
12
use constrained_type_params:: { identify_constrained_type_params, Parameter } ;
14
13
15
14
use hir:: def_id:: DefId ;
16
15
use rustc:: traits:: { self , ObligationCauseCode } ;
17
16
use rustc:: ty:: { self , Ty , TyCtxt } ;
17
+ use rustc:: ty:: util:: ExplicitSelf ;
18
18
use rustc:: util:: nodemap:: { FxHashSet , FxHashMap } ;
19
19
use rustc:: middle:: lang_items;
20
20
21
21
use syntax:: ast;
22
+ use syntax:: feature_gate:: { self , GateIssue } ;
22
23
use syntax_pos:: Span ;
23
- use errors:: DiagnosticBuilder ;
24
+ use errors:: { DiagnosticBuilder , DiagnosticId } ;
24
25
25
26
use rustc:: hir:: intravisit:: { self , Visitor , NestedVisitorMap } ;
26
27
use rustc:: hir;
@@ -451,8 +452,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
451
452
method : & ty:: AssociatedItem ,
452
453
self_ty : Ty < ' tcx > )
453
454
{
454
- // check that the type of the method's receiver matches the
455
- // method's first parameter.
455
+ // check that the method has a valid receiver type, given the type `Self`
456
456
debug ! ( "check_method_receiver({:?}, self_ty={:?})" ,
457
457
method, self_ty) ;
458
458
@@ -468,26 +468,57 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
468
468
469
469
debug ! ( "check_method_receiver: sig={:?}" , sig) ;
470
470
471
+ let self_ty = fcx. normalize_associated_types_in ( span, & self_ty) ;
472
+ let self_ty = fcx. liberate_late_bound_regions (
473
+ method. def_id ,
474
+ & ty:: Binder ( self_ty)
475
+ ) ;
476
+
471
477
let self_arg_ty = sig. inputs ( ) [ 0 ] ;
472
- let rcvr_ty = match ExplicitSelf :: determine ( self_ty, self_arg_ty) {
473
- ExplicitSelf :: ByValue => self_ty,
474
- ExplicitSelf :: ByReference ( region, mutbl) => {
475
- fcx. tcx . mk_ref ( region, ty:: TypeAndMut {
476
- ty : self_ty,
477
- mutbl,
478
- } )
478
+
479
+ let cause = fcx. cause ( span, ObligationCauseCode :: MethodReceiver ) ;
480
+ let self_arg_ty = fcx. normalize_associated_types_in ( span, & self_arg_ty) ;
481
+ let self_arg_ty = fcx. liberate_late_bound_regions (
482
+ method. def_id ,
483
+ & ty:: Binder ( self_arg_ty)
484
+ ) ;
485
+
486
+ let mut autoderef = fcx. autoderef ( span, self_arg_ty) ;
487
+
488
+ loop {
489
+ if let Some ( ( potential_self_ty, _) ) = autoderef. next ( ) {
490
+ debug ! ( "check_method_receiver: potential self type `{:?}` to match `{:?}`" ,
491
+ potential_self_ty, self_ty) ;
492
+
493
+ if fcx. infcx . can_eq ( fcx. param_env , self_ty, potential_self_ty) . is_ok ( ) {
494
+ autoderef. finalize ( ) ;
495
+ if let Some ( mut err) = fcx. demand_eqtype_with_origin (
496
+ & cause, self_ty, potential_self_ty) {
497
+ err. emit ( ) ;
498
+ }
499
+ break
500
+ }
501
+ } else {
502
+ fcx. tcx . sess . diagnostic ( ) . mut_span_err (
503
+ span, & format ! ( "invalid `self` type: {:?}" , self_arg_ty) )
504
+ . note ( & format ! ( "type must be `{:?}` or a type that dereferences to it`" , self_ty) )
505
+ . help ( "consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`" )
506
+ . code ( DiagnosticId :: Error ( "E0307" . into ( ) ) )
507
+ . emit ( ) ;
508
+ return
479
509
}
480
- ExplicitSelf :: ByBox => fcx. tcx . mk_box ( self_ty)
481
- } ;
482
- let rcvr_ty = fcx. normalize_associated_types_in ( span, & rcvr_ty) ;
483
- let rcvr_ty = fcx. liberate_late_bound_regions ( method. def_id ,
484
- & ty:: Binder ( rcvr_ty) ) ;
510
+ }
485
511
486
- debug ! ( "check_method_receiver: receiver ty = {:?}" , rcvr_ty) ;
512
+ let is_self_ty = |ty| fcx. infcx . can_eq ( fcx. param_env , self_ty, ty) . is_ok ( ) ;
513
+ let self_kind = ExplicitSelf :: determine ( self_arg_ty, is_self_ty) ;
487
514
488
- let cause = fcx. cause ( span, ObligationCauseCode :: MethodReceiver ) ;
489
- if let Some ( mut err) = fcx. demand_eqtype_with_origin ( & cause, rcvr_ty, self_arg_ty) {
490
- err. emit ( ) ;
515
+ if let ExplicitSelf :: Other = self_kind {
516
+ if !fcx. tcx . sess . features . borrow ( ) . arbitrary_self_types {
517
+ feature_gate:: feature_err ( & fcx. tcx . sess . parse_sess , "arbitrary_self_types" , span,
518
+ GateIssue :: Language , "arbitrary `self` types are unstable" )
519
+ . help ( "consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`" )
520
+ . emit ( ) ;
521
+ }
491
522
}
492
523
}
493
524
0 commit comments