@@ -412,285 +412,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
412
412
} )
413
413
}
414
414
415
- ///////////////////////////////////////////////////////////////////////////
416
- // METHOD MATCHING
417
- //
418
- // Method matching is a variation on the normal select/evaluation
419
- // situation. In this scenario, rather than having a full trait
420
- // reference to select from, we start with an expression like
421
- // `receiver.method(...)`. This means that we have `rcvr_ty`, the
422
- // type of the receiver, and we have a possible trait that
423
- // supplies `method`. We must determine whether the receiver is
424
- // applicable, taking into account the transformed self type
425
- // declared on `method`. We also must consider the possibility
426
- // that `receiver` can be *coerced* into a suitable type (for
427
- // example, a receiver type like `&(Any+Send)` might be coerced
428
- // into a receiver like `&Any` to allow for method dispatch). See
429
- // the body of `evaluate_method_obligation()` for more details on
430
- // the algorithm.
431
-
432
- /// Determine whether a trait-method is applicable to a receiver of
433
- /// type `rcvr_ty`. *Does not affect the inference state.*
434
- ///
435
- /// - `rcvr_ty` -- type of the receiver
436
- /// - `xform_self_ty` -- transformed self type declared on the method, with `Self`
437
- /// to a fresh type variable
438
- /// - `obligation` -- a reference to the trait where the method is declared, with
439
- /// the input types on the trait replaced with fresh type variables
440
- pub fn evaluate_method_obligation ( & mut self ,
441
- rcvr_ty : Ty < ' tcx > ,
442
- xform_self_ty : Ty < ' tcx > ,
443
- obligation : & Obligation < ' tcx > )
444
- -> MethodMatchResult
445
- {
446
- // Here is the situation. We have a trait method declared (say) like so:
447
- //
448
- // trait TheTrait {
449
- // fn the_method(self: Rc<Self>, ...) { ... }
450
- // }
451
- //
452
- // And then we have a call looking (say) like this:
453
- //
454
- // let x: Rc<Foo> = ...;
455
- // x.the_method()
456
- //
457
- // Now we want to decide if `TheTrait` is applicable. As a
458
- // human, we can see that `TheTrait` is applicable if there is
459
- // an impl for the type `Foo`. But how does the compiler know
460
- // what impl to look for, given that our receiver has type
461
- // `Rc<Foo>`? We need to take the method's self type into
462
- // account.
463
- //
464
- // On entry to this function, we have the following inputs:
465
- //
466
- // - `rcvr_ty = Rc<Foo>`
467
- // - `xform_self_ty = Rc<$0>`
468
- // - `obligation = $0 as TheTrait`
469
- //
470
- // We do the match in two phases. The first is a *precise
471
- // match*, which means that no coercion is required. This is
472
- // the preferred way to match. It works by first making
473
- // `rcvr_ty` a subtype of `xform_self_ty`. This unifies `$0`
474
- // and `Foo`. We can then evaluate (roughly as normal) the
475
- // trait reference `Foo as TheTrait`.
476
- //
477
- // If this fails, we fallback to a coercive match, described below.
478
-
479
- match self . infcx . probe ( || self . match_method_precise ( rcvr_ty, xform_self_ty, obligation) ) {
480
- Ok ( ( ) ) => { return MethodMatched ( PreciseMethodMatch ) ; }
481
- Err ( _) => { }
482
- }
483
-
484
- // Coercive matches work slightly differently and cannot
485
- // completely reuse the normal trait matching machinery
486
- // (though they employ many of the same bits and pieces). To
487
- // see how it works, let's continue with our previous example,
488
- // but with the following declarations:
489
- //
490
- // ```
491
- // trait Foo : Bar { .. }
492
- // trait Bar : Baz { ... }
493
- // trait Baz { ... }
494
- // impl TheTrait for Bar {
495
- // fn the_method(self: Rc<Bar>, ...) { ... }
496
- // }
497
- // ```
498
- //
499
- // Now we see that the receiver type `Rc<Foo>` is actually an
500
- // object type. And in fact the impl we want is an impl on the
501
- // supertrait `Rc<Bar>`. The precise matching procedure won't
502
- // find it, however, because `Rc<Foo>` is not a subtype of
503
- // `Rc<Bar>` -- it is *coercible* to `Rc<Bar>` (actually, such
504
- // coercions are not yet implemented, but let's leave that
505
- // aside for now).
506
- //
507
- // To handle this case, we employ a different procedure. Recall
508
- // that our initial state is as follows:
509
- //
510
- // - `rcvr_ty = Rc<Foo>`
511
- // - `xform_self_ty = Rc<$0>`
512
- // - `obligation = $0 as TheTrait`
513
- //
514
- // We now go through each impl and instantiate all of its type
515
- // variables, yielding the trait reference that the impl
516
- // provides. In our example, the impl would provide `Bar as
517
- // TheTrait`. Next we (try to) unify the trait reference that
518
- // the impl provides with the input obligation. This would
519
- // unify `$0` and `Bar`. Now we can see whether the receiver
520
- // type (`Rc<Foo>`) is *coercible to* the transformed self
521
- // type (`Rc<$0> == Rc<Bar>`). In this case, the answer is
522
- // yes, so the impl is considered a candidate.
523
- //
524
- // Note that there is the possibility of ambiguity here, even
525
- // when all types are known. In our example, this might occur
526
- // if there was *also* an impl of `TheTrait` for `Baz`. In
527
- // this case, `Rc<Foo>` would be coercible to both `Rc<Bar>`
528
- // and `Rc<Baz>`. (Note that it is not a *coherence violation*
529
- // to have impls for both `Bar` and `Baz`, despite this
530
- // ambiguity). In this case, we report an error, listing all
531
- // the applicable impls. The user can explicitly "up-coerce"
532
- // to the type they want.
533
- //
534
- // Note that this coercion step only considers actual impls
535
- // found in the source. This is because all the
536
- // compiler-provided impls (such as those for unboxed
537
- // closures) do not have relevant coercions. This simplifies
538
- // life immensely.
539
-
540
- let mut impls =
541
- self . assemble_method_candidates_from_impls ( rcvr_ty, xform_self_ty, obligation) ;
542
-
543
- if impls. len ( ) > 1 {
544
- impls. retain ( |& c| self . winnow_method_impl ( c, rcvr_ty, xform_self_ty, obligation) ) ;
545
- }
546
-
547
- if impls. len ( ) > 1 {
548
- return MethodAmbiguous ( impls) ;
549
- }
550
-
551
- match impls. pop ( ) {
552
- Some ( def_id) => MethodMatched ( CoerciveMethodMatch ( def_id) ) ,
553
- None => MethodDidNotMatch
554
- }
555
- }
556
-
557
- /// Given the successful result of a method match, this function "confirms" the result, which
558
- /// basically repeats the various matching operations, but outside of any snapshot so that
559
- /// their effects are committed into the inference state.
560
- pub fn confirm_method_match ( & mut self ,
561
- rcvr_ty : Ty < ' tcx > ,
562
- xform_self_ty : Ty < ' tcx > ,
563
- obligation : & Obligation < ' tcx > ,
564
- data : MethodMatchedData )
565
- {
566
- let is_ok = match data {
567
- PreciseMethodMatch => {
568
- self . match_method_precise ( rcvr_ty, xform_self_ty, obligation) . is_ok ( )
569
- }
570
-
571
- CoerciveMethodMatch ( impl_def_id) => {
572
- self . match_method_coerce ( impl_def_id, rcvr_ty, xform_self_ty, obligation) . is_ok ( )
573
- }
574
- } ;
575
-
576
- if !is_ok {
577
- self . tcx ( ) . sess . span_bug (
578
- obligation. cause . span ,
579
- format ! ( "match not repeatable: {}, {}, {}, {}" ,
580
- rcvr_ty. repr( self . tcx( ) ) ,
581
- xform_self_ty. repr( self . tcx( ) ) ,
582
- obligation. repr( self . tcx( ) ) ,
583
- data) [ ] ) ;
584
- }
585
- }
586
-
587
- /// Implements the *precise method match* procedure described in
588
- /// `evaluate_method_obligation()`.
589
- fn match_method_precise ( & mut self ,
590
- rcvr_ty : Ty < ' tcx > ,
591
- xform_self_ty : Ty < ' tcx > ,
592
- obligation : & Obligation < ' tcx > )
593
- -> Result < ( ) , ( ) >
594
- {
595
- self . infcx . commit_if_ok ( || {
596
- match self . infcx . sub_types ( false , infer:: RelateSelfType ( obligation. cause . span ) ,
597
- rcvr_ty, xform_self_ty) {
598
- Ok ( ( ) ) => { }
599
- Err ( _) => { return Err ( ( ) ) ; }
600
- }
601
-
602
- if self . evaluate_obligation ( obligation) {
603
- Ok ( ( ) )
604
- } else {
605
- Err ( ( ) )
606
- }
607
- } )
608
- }
609
-
610
- /// Assembles a list of potentially applicable impls using the *coercive match* procedure
611
- /// described in `evaluate_method_obligation()`.
612
- fn assemble_method_candidates_from_impls ( & mut self ,
613
- rcvr_ty : Ty < ' tcx > ,
614
- xform_self_ty : Ty < ' tcx > ,
615
- obligation : & Obligation < ' tcx > )
616
- -> Vec < ast:: DefId >
617
- {
618
- let mut candidates = Vec :: new ( ) ;
619
-
620
- let all_impls = self . all_impls ( obligation. trait_ref . def_id ) ;
621
- for & impl_def_id in all_impls. iter ( ) {
622
- self . infcx . probe ( || {
623
- match self . match_method_coerce ( impl_def_id, rcvr_ty, xform_self_ty, obligation) {
624
- Ok ( _) => { candidates. push ( impl_def_id) ; }
625
- Err ( _) => { }
626
- }
627
- } ) ;
628
- }
629
-
630
- candidates
631
- }
632
-
633
- /// Applies the *coercive match* procedure described in `evaluate_method_obligation()` to a
634
- /// particular impl.
635
- fn match_method_coerce ( & mut self ,
636
- impl_def_id : ast:: DefId ,
637
- rcvr_ty : Ty < ' tcx > ,
638
- xform_self_ty : Ty < ' tcx > ,
639
- obligation : & Obligation < ' tcx > )
640
- -> Result < Substs < ' tcx > , ( ) >
641
- {
642
- // This is almost always expected to succeed. It
643
- // causes the impl's self-type etc to be unified with
644
- // the type variable that is shared between
645
- // obligation/xform_self_ty. In our example, after
646
- // this is done, the type of `xform_self_ty` would
647
- // change from `Rc<$0>` to `Rc<Foo>` (because $0 is
648
- // unified with `Foo`).
649
- let substs = try!( self . match_impl ( impl_def_id, obligation) ) ;
650
-
651
- // Next, check whether we can coerce. For now we require
652
- // that the coercion be a no-op.
653
- let origin = infer:: Misc ( obligation. cause . span ) ;
654
- match infer:: mk_coercety ( self . infcx , true , origin,
655
- rcvr_ty, xform_self_ty) {
656
- Ok ( None ) => { /* Fallthrough */ }
657
- Ok ( Some ( _) ) | Err ( _) => { return Err ( ( ) ) ; }
658
- }
659
-
660
- Ok ( substs)
661
- }
662
-
663
- /// A version of `winnow_impl` applicable to coerice method matching. This is basically the
664
- /// same as `winnow_impl` but it uses the method matching procedure and is specific to impls.
665
- fn winnow_method_impl ( & mut self ,
666
- impl_def_id : ast:: DefId ,
667
- rcvr_ty : Ty < ' tcx > ,
668
- xform_self_ty : Ty < ' tcx > ,
669
- obligation : & Obligation < ' tcx > )
670
- -> bool
671
- {
672
- debug ! ( "winnow_method_impl: impl_def_id={} rcvr_ty={} xform_self_ty={} obligation={}" ,
673
- impl_def_id. repr( self . tcx( ) ) ,
674
- rcvr_ty. repr( self . tcx( ) ) ,
675
- xform_self_ty. repr( self . tcx( ) ) ,
676
- obligation. repr( self . tcx( ) ) ) ;
677
-
678
- self . infcx . probe ( || {
679
- match self . match_method_coerce ( impl_def_id, rcvr_ty, xform_self_ty, obligation) {
680
- Ok ( substs) => {
681
- let vtable_impl = self . vtable_impl ( impl_def_id,
682
- substs,
683
- obligation. cause ,
684
- obligation. recursion_depth + 1 ) ;
685
- self . winnow_selection ( None , VtableImpl ( vtable_impl) ) . may_apply ( )
686
- }
687
- Err ( ( ) ) => {
688
- false
689
- }
690
- }
691
- } )
692
- }
693
-
694
415
///////////////////////////////////////////////////////////////////////////
695
416
// CANDIDATE ASSEMBLY
696
417
//
0 commit comments