@@ -650,76 +650,7 @@ fn project_type<'cx,'tcx>(
650
650
651
651
assert ! ( candidates. vec. len( ) <= 1 ) ;
652
652
653
- let possible_candidate = candidates. vec . pop ( ) . and_then ( |candidate| {
654
- // In Any (i.e. trans) mode, all projections succeed;
655
- // otherwise, we need to be sensitive to `default` and
656
- // specialization.
657
- if !selcx. projection_mode ( ) . is_any ( ) {
658
- if let ProjectionTyCandidate :: Impl ( ref impl_data) = candidate {
659
- if let Some ( node_item) = assoc_ty_def ( selcx,
660
- impl_data. impl_def_id ,
661
- obligation. predicate . item_name ) {
662
- if node_item. node . is_from_trait ( ) {
663
- if node_item. item . ty . is_some ( ) {
664
- // If the associated type has a default from the
665
- // trait, that should be considered `default` and
666
- // hence not projected.
667
- //
668
- // Note, however, that we allow a projection from
669
- // the trait specifically in the case that the trait
670
- // does *not* give a default. This is purely to
671
- // avoid spurious errors: the situation can only
672
- // arise when *no* impl in the specialization chain
673
- // has provided a definition for the type. When we
674
- // confirm the candidate, we'll turn the projection
675
- // into a TyError, since the actual error will be
676
- // reported in `check_impl_items_against_trait`.
677
- return None ;
678
- }
679
- } else if node_item. item . defaultness . is_default ( ) {
680
- return None ;
681
- }
682
- } else {
683
- // Normally this situation could only arise througha
684
- // compiler bug, but at coherence-checking time we only look
685
- // at the topmost impl (we don't even consider the trait
686
- // itself) for the definition -- so we can fail to find a
687
- // definition of the type even if it exists.
688
-
689
- // For now, we just unconditionally ICE, because otherwise,
690
- // examples like the following will succeed:
691
- //
692
- // ```
693
- // trait Assoc {
694
- // type Output;
695
- // }
696
- //
697
- // impl<T> Assoc for T {
698
- // default type Output = bool;
699
- // }
700
- //
701
- // impl Assoc for u8 {}
702
- // impl Assoc for u16 {}
703
- //
704
- // trait Foo {}
705
- // impl Foo for <u8 as Assoc>::Output {}
706
- // impl Foo for <u16 as Assoc>::Output {}
707
- // return None;
708
- // }
709
- // ```
710
- //
711
- // The essential problem here is that the projection fails,
712
- // leaving two unnormalized types, which appear not to unify
713
- // -- so the overlap check succeeds, when it should fail.
714
- bug ! ( "Tried to project an inherited associated type during \
715
- coherence checking, which is currently not supported.") ;
716
- }
717
- }
718
- }
719
- Some ( candidate)
720
- } ) ;
721
-
722
- match possible_candidate {
653
+ match candidates. vec . pop ( ) {
723
654
Some ( candidate) => {
724
655
let ( ty, obligations) = confirm_candidate ( selcx,
725
656
obligation,
@@ -866,7 +797,6 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
866
797
} ;
867
798
868
799
match vtable {
869
- super :: VtableImpl ( _) |
870
800
super :: VtableClosure ( _) |
871
801
super :: VtableFnPointer ( _) |
872
802
super :: VtableObject ( _) => {
@@ -875,6 +805,115 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
875
805
876
806
candidate_set. vec . push ( ProjectionTyCandidate :: Select ) ;
877
807
}
808
+ super :: VtableImpl ( ref impl_data) if !selcx. projection_mode ( ) . is_any ( ) => {
809
+ // We have to be careful when projecting out of an
810
+ // impl because of specialization. If we are not in
811
+ // trans (i.e., projection mode is not "any"), and the
812
+ // impl's type is declared as default, then we disable
813
+ // projection (even if the trait ref is fully
814
+ // monomorphic). In the case where trait ref is not
815
+ // fully monomorphic (i.e., includes type parameters),
816
+ // this is because those type parameters may
817
+ // ultimately be bound to types from other crates that
818
+ // may have specialized impls we can't see. In the
819
+ // case where the trait ref IS fully monomorphic, this
820
+ // is a policy decision that we made in the RFC in
821
+ // order to preserve flexibility for the crate that
822
+ // defined the specializable impl to specialize later
823
+ // for existing types.
824
+ //
825
+ // In either case, we handle this by not adding a
826
+ // candidate for an impl if it contains a `default`
827
+ // type.
828
+ let opt_node_item = assoc_ty_def ( selcx,
829
+ impl_data. impl_def_id ,
830
+ obligation. predicate . item_name ) ;
831
+ let new_candidate = if let Some ( node_item) = opt_node_item {
832
+ if node_item. node . is_from_trait ( ) {
833
+ if node_item. item . ty . is_some ( ) {
834
+ // The impl inherited a `type Foo =
835
+ // Bar` given in the trait, which is
836
+ // implicitly default. No candidate.
837
+ None
838
+ } else {
839
+ // The impl did not specify `type` and neither
840
+ // did the trait:
841
+ //
842
+ // ```rust
843
+ // trait Foo { type T; }
844
+ // impl Foo for Bar { }
845
+ // ```
846
+ //
847
+ // This is an error, but it will be
848
+ // reported in `check_impl_items_against_trait`.
849
+ // We accept it here but will flag it as
850
+ // an error when we confirm the candidate
851
+ // (which will ultimately lead to `normalize_to_error`
852
+ // being invoked).
853
+ Some ( ProjectionTyCandidate :: Select )
854
+ }
855
+ } else if node_item. item . defaultness . is_default ( ) {
856
+ // The impl specified `default type Foo =
857
+ // Bar`. No candidate.
858
+ None
859
+ } else {
860
+ // The impl specified `type Foo = Bar`
861
+ // with no default. Add a candidate.
862
+ Some ( ProjectionTyCandidate :: Select )
863
+ }
864
+ } else {
865
+ // This is saying that neither the trait nor
866
+ // the impl contain a definition for this
867
+ // associated type. Normally this situation
868
+ // could only arise through a compiler bug --
869
+ // if the user wrote a bad item name, it
870
+ // should have failed in astconv. **However**,
871
+ // at coherence-checking time, we only look at
872
+ // the topmost impl (we don't even consider
873
+ // the trait itself) for the definition -- and
874
+ // so in that case it may be that the trait
875
+ // *DOES* have a declaration, but we don't see
876
+ // it, and we end up in this branch.
877
+ //
878
+ // This is kind of tricky to handle actually.
879
+ // For now, we just unconditionally ICE,
880
+ // because otherwise, examples like the
881
+ // following will succeed:
882
+ //
883
+ // ```
884
+ // trait Assoc {
885
+ // type Output;
886
+ // }
887
+ //
888
+ // impl<T> Assoc for T {
889
+ // default type Output = bool;
890
+ // }
891
+ //
892
+ // impl Assoc for u8 {}
893
+ // impl Assoc for u16 {}
894
+ //
895
+ // trait Foo {}
896
+ // impl Foo for <u8 as Assoc>::Output {}
897
+ // impl Foo for <u16 as Assoc>::Output {}
898
+ // return None;
899
+ // }
900
+ // ```
901
+ //
902
+ // The essential problem here is that the
903
+ // projection fails, leaving two unnormalized
904
+ // types, which appear not to unify -- so the
905
+ // overlap check succeeds, when it should
906
+ // fail.
907
+ bug ! ( "Tried to project an inherited associated type during \
908
+ coherence checking, which is currently not supported.") ;
909
+ } ;
910
+ candidate_set. vec . extend ( new_candidate) ;
911
+ }
912
+ super :: VtableImpl ( _) => {
913
+ // In trans mode, we can just project out of impls, no prob.
914
+ assert ! ( selcx. projection_mode( ) . is_any( ) ) ;
915
+ candidate_set. vec . push ( ProjectionTyCandidate :: Select ) ;
916
+ }
878
917
super :: VtableParam ( ..) => {
879
918
// This case tell us nothing about the value of an
880
919
// associated type. Consider:
0 commit comments