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