@@ -152,14 +152,8 @@ enum ProjectionTyCandidate<'tcx> {
152
152
// from the definition of `Trait` when you have something like <<A as Trait>::B as Trait2>::C
153
153
TraitDef ( ty:: PolyProjectionPredicate < ' tcx > ) ,
154
154
155
- // defined in an impl
156
- Impl ( VtableImplData < ' tcx , PredicateObligation < ' tcx > > ) ,
157
-
158
- // closure return type
159
- Closure ( VtableClosureData < ' tcx , PredicateObligation < ' tcx > > ) ,
160
-
161
- // fn pointer return type
162
- FnPointer ( Ty < ' tcx > ) ,
155
+ // from a "impl" (or a "pseudo-impl" returned by select)
156
+ Select ,
163
157
}
164
158
165
159
struct ProjectionTyCandidateSet < ' tcx > {
@@ -645,10 +639,8 @@ fn project_type<'cx,'tcx>(
645
639
debug ! ( "retaining param-env candidates only from {:?}" , candidates. vec) ;
646
640
candidates. vec . retain ( |c| match * c {
647
641
ProjectionTyCandidate :: ParamEnv ( ..) => true ,
648
- ProjectionTyCandidate :: Impl ( ..) |
649
- ProjectionTyCandidate :: Closure ( ..) |
650
642
ProjectionTyCandidate :: TraitDef ( ..) |
651
- ProjectionTyCandidate :: FnPointer ( .. ) => false ,
643
+ ProjectionTyCandidate :: Select => false ,
652
644
} ) ;
653
645
debug ! ( "resulting candidate set: {:?}" , candidates. vec) ;
654
646
if candidates. vec . len ( ) != 1 {
@@ -729,7 +721,10 @@ fn project_type<'cx,'tcx>(
729
721
730
722
match possible_candidate {
731
723
Some ( candidate) => {
732
- let ( ty, obligations) = confirm_candidate ( selcx, obligation, candidate) ;
724
+ let ( ty, obligations) = confirm_candidate ( selcx,
725
+ obligation,
726
+ & obligation_trait_ref,
727
+ candidate) ;
733
728
Ok ( ProjectedTy :: Progress ( ty, obligations) )
734
729
}
735
730
None => {
@@ -845,38 +840,6 @@ fn assemble_candidates_from_predicates<'cx,'tcx,I>(
845
840
}
846
841
}
847
842
848
- fn assemble_candidates_from_object_type < ' cx , ' tcx > (
849
- selcx : & mut SelectionContext < ' cx , ' tcx > ,
850
- obligation : & ProjectionTyObligation < ' tcx > ,
851
- obligation_trait_ref : & ty:: TraitRef < ' tcx > ,
852
- candidate_set : & mut ProjectionTyCandidateSet < ' tcx > )
853
- {
854
- let self_ty = obligation_trait_ref. self_ty ( ) ;
855
- let object_ty = selcx. infcx ( ) . shallow_resolve ( self_ty) ;
856
- debug ! ( "assemble_candidates_from_object_type(object_ty={:?})" ,
857
- object_ty) ;
858
- let data = match object_ty. sty {
859
- ty:: TyTrait ( ref data) => data,
860
- _ => {
861
- span_bug ! (
862
- obligation. cause. span,
863
- "assemble_candidates_from_object_type called with non-object: {:?}" ,
864
- object_ty) ;
865
- }
866
- } ;
867
- let projection_bounds = data. projection_bounds_with_self_ty ( selcx. tcx ( ) , object_ty) ;
868
- let env_predicates = projection_bounds. iter ( )
869
- . map ( |p| p. to_predicate ( ) )
870
- . collect ( ) ;
871
- let env_predicates = elaborate_predicates ( selcx. tcx ( ) , env_predicates) ;
872
- assemble_candidates_from_predicates ( selcx,
873
- obligation,
874
- obligation_trait_ref,
875
- candidate_set,
876
- ProjectionTyCandidate :: ParamEnv ,
877
- env_predicates)
878
- }
879
-
880
843
fn assemble_candidates_from_impls < ' cx , ' tcx > (
881
844
selcx : & mut SelectionContext < ' cx , ' tcx > ,
882
845
obligation : & ProjectionTyObligation < ' tcx > ,
@@ -888,82 +851,75 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
888
851
// start out by selecting the predicate `T as TraitRef<...>`:
889
852
let poly_trait_ref = obligation_trait_ref. to_poly_trait_ref ( ) ;
890
853
let trait_obligation = obligation. with ( poly_trait_ref. to_poly_trait_predicate ( ) ) ;
891
- let vtable = match selcx. select ( & trait_obligation) {
892
- Ok ( Some ( vtable) ) => vtable,
893
- Ok ( None ) => {
894
- candidate_set. ambiguous = true ;
895
- return Ok ( ( ) ) ;
896
- }
897
- Err ( e) => {
898
- debug ! ( "assemble_candidates_from_impls: selection error {:?}" ,
899
- e) ;
900
- return Err ( e) ;
901
- }
902
- } ;
854
+ selcx. infcx ( ) . probe ( |_| {
855
+ let vtable = match selcx. select ( & trait_obligation) {
856
+ Ok ( Some ( vtable) ) => vtable,
857
+ Ok ( None ) => {
858
+ candidate_set. ambiguous = true ;
859
+ return Ok ( ( ) ) ;
860
+ }
861
+ Err ( e) => {
862
+ debug ! ( "assemble_candidates_from_impls: selection error {:?}" ,
863
+ e) ;
864
+ return Err ( e) ;
865
+ }
866
+ } ;
903
867
904
- match vtable {
905
- super :: VtableImpl ( data) => {
906
- debug ! ( "assemble_candidates_from_impls: impl candidate {:?}" ,
907
- data) ;
868
+ match vtable {
869
+ super :: VtableImpl ( _) |
870
+ super :: VtableClosure ( _) |
871
+ super :: VtableFnPointer ( _) |
872
+ super :: VtableObject ( _) => {
873
+ debug ! ( "assemble_candidates_from_impls: vtable={:?}" ,
874
+ vtable) ;
908
875
909
- candidate_set. vec . push (
910
- ProjectionTyCandidate :: Impl ( data) ) ;
911
- }
912
- super :: VtableObject ( _) => {
913
- assemble_candidates_from_object_type (
914
- selcx, obligation, obligation_trait_ref, candidate_set) ;
915
- }
916
- super :: VtableClosure ( data) => {
917
- candidate_set. vec . push (
918
- ProjectionTyCandidate :: Closure ( data) ) ;
919
- }
920
- super :: VtableFnPointer ( fn_type) => {
921
- candidate_set. vec . push (
922
- ProjectionTyCandidate :: FnPointer ( fn_type) ) ;
923
- }
924
- super :: VtableParam ( ..) => {
925
- // This case tell us nothing about the value of an
926
- // associated type. Consider:
927
- //
928
- // ```
929
- // trait SomeTrait { type Foo; }
930
- // fn foo<T:SomeTrait>(...) { }
931
- // ```
932
- //
933
- // If the user writes `<T as SomeTrait>::Foo`, then the `T
934
- // : SomeTrait` binding does not help us decide what the
935
- // type `Foo` is (at least, not more specifically than
936
- // what we already knew).
937
- //
938
- // But wait, you say! What about an example like this:
939
- //
940
- // ```
941
- // fn bar<T:SomeTrait<Foo=usize>>(...) { ... }
942
- // ```
943
- //
944
- // Doesn't the `T : Sometrait<Foo=usize>` predicate help
945
- // resolve `T::Foo`? And of course it does, but in fact
946
- // that single predicate is desugared into two predicates
947
- // in the compiler: a trait predicate (`T : SomeTrait`) and a
948
- // projection. And the projection where clause is handled
949
- // in `assemble_candidates_from_param_env`.
950
- }
951
- super :: VtableDefaultImpl ( ..) |
952
- super :: VtableBuiltin ( ..) => {
953
- // These traits have no associated types.
954
- span_bug ! (
955
- obligation. cause. span,
956
- "Cannot project an associated type from `{:?}`" ,
957
- vtable) ;
876
+ candidate_set. vec . push ( ProjectionTyCandidate :: Select ) ;
877
+ }
878
+ super :: VtableParam ( ..) => {
879
+ // This case tell us nothing about the value of an
880
+ // associated type. Consider:
881
+ //
882
+ // ```
883
+ // trait SomeTrait { type Foo; }
884
+ // fn foo<T:SomeTrait>(...) { }
885
+ // ```
886
+ //
887
+ // If the user writes `<T as SomeTrait>::Foo`, then the `T
888
+ // : SomeTrait` binding does not help us decide what the
889
+ // type `Foo` is (at least, not more specifically than
890
+ // what we already knew).
891
+ //
892
+ // But wait, you say! What about an example like this:
893
+ //
894
+ // ```
895
+ // fn bar<T:SomeTrait<Foo=usize>>(...) { ... }
896
+ // ```
897
+ //
898
+ // Doesn't the `T : Sometrait<Foo=usize>` predicate help
899
+ // resolve `T::Foo`? And of course it does, but in fact
900
+ // that single predicate is desugared into two predicates
901
+ // in the compiler: a trait predicate (`T : SomeTrait`) and a
902
+ // projection. And the projection where clause is handled
903
+ // in `assemble_candidates_from_param_env`.
904
+ }
905
+ super :: VtableDefaultImpl ( ..) |
906
+ super :: VtableBuiltin ( ..) => {
907
+ // These traits have no associated types.
908
+ span_bug ! (
909
+ obligation. cause. span,
910
+ "Cannot project an associated type from `{:?}`" ,
911
+ vtable) ;
912
+ }
958
913
}
959
- }
960
914
961
- Ok ( ( ) )
915
+ Ok ( ( ) )
916
+ } )
962
917
}
963
918
964
919
fn confirm_candidate < ' cx , ' tcx > (
965
920
selcx : & mut SelectionContext < ' cx , ' tcx > ,
966
921
obligation : & ProjectionTyObligation < ' tcx > ,
922
+ obligation_trait_ref : & ty:: TraitRef < ' tcx > ,
967
923
candidate : ProjectionTyCandidate < ' tcx > )
968
924
-> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
969
925
{
@@ -977,20 +933,118 @@ fn confirm_candidate<'cx,'tcx>(
977
933
confirm_param_env_candidate ( selcx, obligation, poly_projection)
978
934
}
979
935
980
- ProjectionTyCandidate :: Impl ( impl_vtable ) => {
981
- confirm_impl_candidate ( selcx, obligation, impl_vtable )
936
+ ProjectionTyCandidate :: Select => {
937
+ confirm_select_candidate ( selcx, obligation, obligation_trait_ref )
982
938
}
939
+ }
940
+ }
983
941
984
- ProjectionTyCandidate :: Closure ( closure_vtable) => {
985
- confirm_closure_candidate ( selcx, obligation, closure_vtable)
942
+ fn confirm_select_candidate < ' cx , ' tcx > (
943
+ selcx : & mut SelectionContext < ' cx , ' tcx > ,
944
+ obligation : & ProjectionTyObligation < ' tcx > ,
945
+ obligation_trait_ref : & ty:: TraitRef < ' tcx > )
946
+ -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
947
+ {
948
+ let poly_trait_ref = obligation_trait_ref. to_poly_trait_ref ( ) ;
949
+ let trait_obligation = obligation. with ( poly_trait_ref. to_poly_trait_predicate ( ) ) ;
950
+ let vtable = match selcx. select ( & trait_obligation) {
951
+ Ok ( Some ( vtable) ) => vtable,
952
+ _ => {
953
+ span_bug ! (
954
+ obligation. cause. span,
955
+ "Failed to select `{:?}`" ,
956
+ trait_obligation) ;
986
957
}
958
+ } ;
987
959
988
- ProjectionTyCandidate :: FnPointer ( fn_type) => {
989
- confirm_fn_pointer_candidate ( selcx, obligation, fn_type)
990
- }
960
+ match vtable {
961
+ super :: VtableImpl ( data) =>
962
+ confirm_impl_candidate ( selcx, obligation, data) ,
963
+ super :: VtableClosure ( data) =>
964
+ confirm_closure_candidate ( selcx, obligation, data) ,
965
+ super :: VtableFnPointer ( data) =>
966
+ confirm_fn_pointer_candidate ( selcx, obligation, data) ,
967
+ super :: VtableObject ( _) =>
968
+ confirm_object_candidate ( selcx, obligation, obligation_trait_ref) ,
969
+ super :: VtableDefaultImpl ( ..) |
970
+ super :: VtableParam ( ..) |
971
+ super :: VtableBuiltin ( ..) =>
972
+ // we don't create Select candidates with this kind of resolution
973
+ span_bug ! (
974
+ obligation. cause. span,
975
+ "Cannot project an associated type from `{:?}`" ,
976
+ vtable) ,
991
977
}
992
978
}
993
979
980
+ fn confirm_object_candidate < ' cx , ' tcx > (
981
+ selcx : & mut SelectionContext < ' cx , ' tcx > ,
982
+ obligation : & ProjectionTyObligation < ' tcx > ,
983
+ obligation_trait_ref : & ty:: TraitRef < ' tcx > )
984
+ -> ( Ty < ' tcx > , Vec < PredicateObligation < ' tcx > > )
985
+ {
986
+ let self_ty = obligation_trait_ref. self_ty ( ) ;
987
+ let object_ty = selcx. infcx ( ) . shallow_resolve ( self_ty) ;
988
+ debug ! ( "assemble_candidates_from_object_type(object_ty={:?})" ,
989
+ object_ty) ;
990
+ let data = match object_ty. sty {
991
+ ty:: TyTrait ( ref data) => data,
992
+ _ => {
993
+ span_bug ! (
994
+ obligation. cause. span,
995
+ "assemble_candidates_from_object_type called with non-object: {:?}" ,
996
+ object_ty) ;
997
+ }
998
+ } ;
999
+ let projection_bounds = data. projection_bounds_with_self_ty ( selcx. tcx ( ) , object_ty) ;
1000
+ let env_predicates = projection_bounds. iter ( )
1001
+ . map ( |p| p. to_predicate ( ) )
1002
+ . collect ( ) ;
1003
+ let env_predicate = {
1004
+ let env_predicates = elaborate_predicates ( selcx. tcx ( ) , env_predicates) ;
1005
+
1006
+ // select only those projections that are actually projecting an
1007
+ // item with the correct name
1008
+ let env_predicates = env_predicates. filter_map ( |p| match p {
1009
+ ty:: Predicate :: Projection ( data) =>
1010
+ if data. item_name ( ) == obligation. predicate . item_name {
1011
+ Some ( data)
1012
+ } else {
1013
+ None
1014
+ } ,
1015
+ _ => None
1016
+ } ) ;
1017
+
1018
+ // select those with a relevant trait-ref
1019
+ let mut env_predicates = env_predicates. filter ( |data| {
1020
+ let origin = TypeOrigin :: RelateOutputImplTypes ( obligation. cause . span ) ;
1021
+ let data_poly_trait_ref = data. to_poly_trait_ref ( ) ;
1022
+ let obligation_poly_trait_ref = obligation_trait_ref. to_poly_trait_ref ( ) ;
1023
+ selcx. infcx ( ) . probe ( |_| {
1024
+ selcx. infcx ( ) . sub_poly_trait_refs ( false ,
1025
+ origin,
1026
+ data_poly_trait_ref,
1027
+ obligation_poly_trait_ref) . is_ok ( )
1028
+ } )
1029
+ } ) ;
1030
+
1031
+ // select the first matching one; there really ought to be one or
1032
+ // else the object type is not WF, since an object type should
1033
+ // include all of its projections explicitly
1034
+ match env_predicates. next ( ) {
1035
+ Some ( env_predicate) => env_predicate,
1036
+ None => {
1037
+ debug ! ( "confirm_object_candidate: no env-predicate \
1038
+ found in object type `{:?}`; ill-formed",
1039
+ object_ty) ;
1040
+ return ( selcx. tcx ( ) . types . err , vec ! ( ) ) ;
1041
+ }
1042
+ }
1043
+ } ;
1044
+
1045
+ confirm_param_env_candidate ( selcx, obligation, env_predicate)
1046
+ }
1047
+
994
1048
fn confirm_fn_pointer_candidate < ' cx , ' tcx > (
995
1049
selcx : & mut SelectionContext < ' cx , ' tcx > ,
996
1050
obligation : & ProjectionTyObligation < ' tcx > ,
0 commit comments