@@ -13,6 +13,7 @@ use check::{Inherited, FnCtxt};
13
13
use constrained_type_params:: { identify_constrained_type_params, Parameter } ;
14
14
15
15
use hir:: def_id:: DefId ;
16
+ use rustc:: infer:: InferOk ;
16
17
use rustc:: traits:: { self , ObligationCauseCode } ;
17
18
use rustc:: ty:: { self , Ty , TyCtxt } ;
18
19
use rustc:: util:: nodemap:: { FxHashSet , FxHashMap } ;
@@ -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
@@ -470,47 +470,29 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
470
470
471
471
let self_arg_ty = sig. inputs ( ) [ 0 ] ;
472
472
473
- if fcx. tcx . sess . features . borrow ( ) . arbitrary_self_types {
474
- let cause = fcx. cause ( span, ObligationCauseCode :: MethodReceiver ) ;
473
+ let cause = fcx. cause ( span, ObligationCauseCode :: MethodReceiver ) ;
474
+ let at = fcx. at ( & cause, fcx. param_env ) ;
475
+ let mut autoderef = fcx. autoderef ( span, self_arg_ty) ;
475
476
476
- let mut autoderef = fcx . autoderef ( span , self_arg_ty ) ;
477
- while let Some ( ( potential_self_ty, _) ) = autoderef. next ( ) {
477
+ loop {
478
+ if let Some ( ( potential_self_ty, _) ) = autoderef. next ( ) {
478
479
debug ! ( "check_method_receiver: potential self type `{:?}` to match `{:?}`" , potential_self_ty, self_ty) ;
479
480
480
- // there's gotta be a more idiomatic way of checking if types are equal than this
481
- if let Some ( mut err) = fcx. demand_eqtype_with_origin ( & cause, self_ty, potential_self_ty) {
482
- err. cancel ( ) ;
483
- continue ;
484
- } else {
485
- // we found a type that matches `self_ty`
481
+ if let Ok ( InferOk { obligations, value : ( ) } ) = at. eq ( self_ty, potential_self_ty) {
482
+ fcx. register_predicates ( obligations) ;
486
483
autoderef. finalize ( ) ;
487
- return ;
484
+ break ;
488
485
}
489
- }
490
486
491
- span_err ! ( fcx. tcx. sess, span, E0307 , "invalid `self` type: {:?}" , self_arg_ty) ;
492
- return ;
487
+ } else {
488
+ span_err ! ( fcx. tcx. sess, span, E0307 , "invalid self type: {:?}" , self_arg_ty) ;
489
+ }
493
490
}
494
491
495
- let rcvr_ty = match ExplicitSelf :: determine ( self_ty, self_arg_ty) {
496
- ExplicitSelf :: ByValue => self_ty,
497
- ExplicitSelf :: ByReference ( region, mutbl) => {
498
- fcx. tcx . mk_ref ( region, ty:: TypeAndMut {
499
- ty : self_ty,
500
- mutbl,
501
- } )
492
+ if let ExplicitSelf :: Other = ExplicitSelf :: determine ( fcx. tcx , fcx. param_env , self_ty, self_arg_ty) {
493
+ if !fcx. tcx . sess . features . borrow ( ) . arbitrary_self_types {
494
+ fcx. tcx . sess . span_err ( span, "Arbitrary `self` types are experimental" ) ;
502
495
}
503
- ExplicitSelf :: ByBox => fcx. tcx . mk_box ( self_ty)
504
- } ;
505
- let rcvr_ty = fcx. normalize_associated_types_in ( span, & rcvr_ty) ;
506
- let rcvr_ty = fcx. liberate_late_bound_regions ( method. def_id ,
507
- & ty:: Binder ( rcvr_ty) ) ;
508
-
509
- debug ! ( "check_method_receiver: receiver ty = {:?}" , rcvr_ty) ;
510
-
511
- let cause = fcx. cause ( span, ObligationCauseCode :: MethodReceiver ) ;
512
- if let Some ( mut err) = fcx. demand_eqtype_with_origin ( & cause, rcvr_ty, self_arg_ty) {
513
- err. emit ( ) ;
514
496
}
515
497
}
516
498
0 commit comments