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