88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- use astconv:: ExplicitSelf ;
1211use check:: { Inherited , FnCtxt } ;
1312use constrained_type_params:: { identify_constrained_type_params, Parameter } ;
1413
1514use hir:: def_id:: DefId ;
1615use rustc:: traits:: { self , ObligationCauseCode } ;
1716use rustc:: ty:: { self , Ty , TyCtxt } ;
17+ use rustc:: ty:: util:: ExplicitSelf ;
1818use rustc:: util:: nodemap:: { FxHashSet , FxHashMap } ;
1919use rustc:: middle:: lang_items;
2020
2121use syntax:: ast;
22+ use syntax:: feature_gate:: { self , GateIssue } ;
2223use syntax_pos:: Span ;
23- use errors:: DiagnosticBuilder ;
24+ use errors:: { DiagnosticBuilder , DiagnosticId } ;
2425
2526use rustc:: hir:: intravisit:: { self , Visitor , NestedVisitorMap } ;
2627use rustc:: hir;
@@ -451,8 +452,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
451452 method : & ty:: AssociatedItem ,
452453 self_ty : Ty < ' tcx > )
453454 {
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`
456456 debug ! ( "check_method_receiver({:?}, self_ty={:?})" ,
457457 method, self_ty) ;
458458
@@ -468,26 +468,57 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
468468
469469 debug ! ( "check_method_receiver: sig={:?}" , sig) ;
470470
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+
471477 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
479509 }
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+ }
485511
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) ;
487514
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+ }
491522 }
492523 }
493524
0 commit comments