@@ -36,15 +36,14 @@ use hir_def::{
36
36
body:: Body ,
37
37
builtin_type:: { BuiltinInt , BuiltinType , BuiltinUint } ,
38
38
data:: { ConstData , StaticData } ,
39
- hir:: LabelId ,
40
- hir:: { BindingAnnotation , BindingId , ExprId , ExprOrPatId , PatId } ,
39
+ hir:: { BindingAnnotation , BindingId , ExprId , ExprOrPatId , LabelId , PatId } ,
41
40
lang_item:: { LangItem , LangItemTarget } ,
42
41
layout:: Integer ,
43
42
path:: { ModPath , Path } ,
44
43
resolver:: { HasResolver , ResolveValueResult , Resolver , TypeNs , ValueNs } ,
45
44
type_ref:: { LifetimeRef , TypeRef } ,
46
- AdtId , AssocItemId , DefWithBodyId , FieldId , FunctionId , ItemContainerId , Lookup , TraitId ,
47
- TupleFieldId , TupleId , TypeAliasId , VariantId ,
45
+ AdtId , AssocItemId , DefWithBodyId , FieldId , FunctionId , ImplId , ItemContainerId , Lookup ,
46
+ TraitId , TupleFieldId , TupleId , TypeAliasId , VariantId ,
48
47
} ;
49
48
use hir_expand:: name:: Name ;
50
49
use indexmap:: IndexSet ;
@@ -785,14 +784,19 @@ impl<'a> InferenceContext<'a> {
785
784
fn collect_const ( & mut self , data : & ConstData ) {
786
785
let return_ty = self . make_ty ( & data. type_ref ) ;
787
786
788
- // Constants might be associated items that define ATPITs .
789
- self . insert_atpit_coercion_table ( iter:: once ( & return_ty) ) ;
787
+ // Constants might be defining usage sites of TAITs .
788
+ self . make_tait_coercion_table ( iter:: once ( & return_ty) ) ;
790
789
791
790
self . return_ty = return_ty;
792
791
}
793
792
794
793
fn collect_static ( & mut self , data : & StaticData ) {
795
- self . return_ty = self . make_ty ( & data. type_ref ) ;
794
+ let return_ty = self . make_ty ( & data. type_ref ) ;
795
+
796
+ // Statics might be defining usage sites of TAITs.
797
+ self . make_tait_coercion_table ( iter:: once ( & return_ty) ) ;
798
+
799
+ self . return_ty = return_ty;
796
800
}
797
801
798
802
fn collect_fn ( & mut self , func : FunctionId ) {
@@ -857,11 +861,11 @@ impl<'a> InferenceContext<'a> {
857
861
self . return_ty = self . normalize_associated_types_in ( return_ty) ;
858
862
self . return_coercion = Some ( CoerceMany :: new ( self . return_ty . clone ( ) ) ) ;
859
863
860
- // Functions might be associated items that define ATPITs .
861
- // To define an ATPITs , that ATPIT must appear in the function's signatures.
864
+ // Functions might be defining usage sites of TAITs .
865
+ // To define an TAITs , that TAIT must appear in the function's signatures.
862
866
// So, it suffices to check for params and return types.
863
867
params_and_ret_tys. push ( self . return_ty . clone ( ) ) ;
864
- self . insert_atpit_coercion_table ( params_and_ret_tys. iter ( ) ) ;
868
+ self . make_tait_coercion_table ( params_and_ret_tys. iter ( ) ) ;
865
869
}
866
870
867
871
fn insert_inference_vars_for_impl_trait < T > ( & mut self , t : T , placeholders : Substitution ) -> T
@@ -880,7 +884,7 @@ impl<'a> InferenceContext<'a> {
880
884
ImplTraitId :: ReturnTypeImplTrait ( def, idx) => {
881
885
( self . db . return_type_impl_traits ( def) , idx)
882
886
}
883
- ImplTraitId :: AssociatedTypeImplTrait ( def, idx) => {
887
+ ImplTraitId :: TypeAliasImplTrait ( def, idx) => {
884
888
( self . db . type_alias_impl_traits ( def) , idx)
885
889
}
886
890
_ => unreachable ! ( ) ,
@@ -909,23 +913,25 @@ impl<'a> InferenceContext<'a> {
909
913
}
910
914
911
915
/// The coercion of a non-inference var into an opaque type should fail,
912
- /// but not in the defining sites of the ATPITs .
913
- /// In such cases, we insert an proxy inference var for each ATPIT ,
914
- /// and coerce into it instead of ATPIT itself.
916
+ /// but not in the defining sites of the TAITs .
917
+ /// In such cases, we insert an proxy inference var for each TAIT ,
918
+ /// and coerce into it instead of TAIT itself.
915
919
///
916
920
/// The inference var stretagy is effective because;
917
921
///
918
- /// - It can still unify types that coerced into ATPIT
922
+ /// - It can still unify types that coerced into TAITs
919
923
/// - We are pushing `impl Trait` bounds into it
920
924
///
921
925
/// This function inserts a map that maps the opaque type to that proxy inference var.
922
- fn insert_atpit_coercion_table < ' b > ( & mut self , tys : impl Iterator < Item = & ' b Ty > ) {
923
- struct OpaqueTyCollector < ' a , ' b > {
926
+ fn make_tait_coercion_table < ' b > ( & mut self , tait_candidates : impl Iterator < Item = & ' b Ty > ) {
927
+ struct TypeAliasImplTraitCollector < ' a , ' b > {
928
+ db : & ' b dyn HirDatabase ,
924
929
table : & ' b mut InferenceTable < ' a > ,
925
- opaque_tys : FxHashMap < OpaqueTyId , Ty > ,
930
+ assocs : FxHashMap < OpaqueTyId , ( ImplId , Ty ) > ,
931
+ non_assocs : FxHashMap < OpaqueTyId , Ty > ,
926
932
}
927
933
928
- impl < ' a , ' b > TypeVisitor < Interner > for OpaqueTyCollector < ' a , ' b > {
934
+ impl < ' a , ' b > TypeVisitor < Interner > for TypeAliasImplTraitCollector < ' a , ' b > {
929
935
type BreakTy = ( ) ;
930
936
931
937
fn as_dyn ( & mut self ) -> & mut dyn TypeVisitor < Interner , BreakTy = Self :: BreakTy > {
@@ -944,59 +950,105 @@ impl<'a> InferenceContext<'a> {
944
950
let ty = self . table . resolve_ty_shallow ( ty) ;
945
951
946
952
if let TyKind :: OpaqueType ( id, _) = ty. kind ( Interner ) {
947
- self . opaque_tys . insert ( * id, ty. clone ( ) ) ;
953
+ if let ImplTraitId :: TypeAliasImplTrait ( alias_id, _) =
954
+ self . db . lookup_intern_impl_trait_id ( ( * id) . into ( ) )
955
+ {
956
+ let loc = self . db . lookup_intern_type_alias ( alias_id) ;
957
+ match loc. container {
958
+ ItemContainerId :: ImplId ( impl_id) => {
959
+ self . assocs . insert ( * id, ( impl_id, ty. clone ( ) ) ) ;
960
+ }
961
+ ItemContainerId :: ModuleId ( ..) | ItemContainerId :: ExternBlockId ( ..) => {
962
+ self . non_assocs . insert ( * id, ty. clone ( ) ) ;
963
+ }
964
+ _ => { }
965
+ }
966
+ }
948
967
}
949
968
950
969
ty. super_visit_with ( self , outer_binder)
951
970
}
952
971
}
953
972
954
- // Early return if this is not happening inside the impl block
955
- let impl_id = if let Some ( impl_id ) = self . resolver . impl_def ( ) {
956
- impl_id
957
- } else {
958
- return ;
973
+ let mut collector = TypeAliasImplTraitCollector {
974
+ db : self . db ,
975
+ table : & mut self . table ,
976
+ assocs : FxHashMap :: default ( ) ,
977
+ non_assocs : FxHashMap :: default ( ) ,
959
978
} ;
960
-
961
- let assoc_tys: FxHashSet < _ > = self
962
- . db
963
- . impl_data ( impl_id)
964
- . items
965
- . iter ( )
966
- . filter_map ( |item| match item {
967
- AssocItemId :: TypeAliasId ( alias) => Some ( * alias) ,
968
- _ => None ,
969
- } )
970
- . collect ( ) ;
971
- if assoc_tys. is_empty ( ) {
972
- return ;
979
+ for ty in tait_candidates {
980
+ ty. visit_with ( collector. as_dyn ( ) , DebruijnIndex :: INNERMOST ) ;
973
981
}
974
982
975
- let mut collector =
976
- OpaqueTyCollector { table : & mut self . table , opaque_tys : FxHashMap :: default ( ) } ;
977
- for ty in tys {
978
- ty. visit_with ( collector. as_dyn ( ) , DebruijnIndex :: INNERMOST ) ;
983
+ // Non-assoc TAITs can be define-used everywhere as long as they are
984
+ // in function signatures or const types, etc
985
+ let mut taits = collector. non_assocs ;
986
+
987
+ // assoc TAITs(ATPITs) can be only define-used inside their impl block.
988
+ // They cannot be define-used in inner items like in the following;
989
+ //
990
+ // ```
991
+ // impl Trait for Struct {
992
+ // type Assoc = impl Default;
993
+ //
994
+ // fn assoc_fn() -> Self::Assoc {
995
+ // let foo: Self::Assoc = true; // Allowed here
996
+ //
997
+ // fn inner() -> Self::Assoc {
998
+ // false // Not allowed here
999
+ // }
1000
+ //
1001
+ // foo
1002
+ // }
1003
+ // }
1004
+ // ```
1005
+ let impl_id = match self . owner {
1006
+ DefWithBodyId :: FunctionId ( it) => {
1007
+ let loc = self . db . lookup_intern_function ( it) ;
1008
+ if let ItemContainerId :: ImplId ( impl_id) = loc. container {
1009
+ Some ( impl_id)
1010
+ } else {
1011
+ None
1012
+ }
1013
+ }
1014
+ DefWithBodyId :: ConstId ( it) => {
1015
+ let loc = self . db . lookup_intern_const ( it) ;
1016
+ if let ItemContainerId :: ImplId ( impl_id) = loc. container {
1017
+ Some ( impl_id)
1018
+ } else {
1019
+ None
1020
+ }
1021
+ }
1022
+ _ => None ,
1023
+ } ;
1024
+
1025
+ if let Some ( impl_id) = impl_id {
1026
+ taits. extend ( collector. assocs . into_iter ( ) . filter_map ( |( id, ( impl_, ty) ) | {
1027
+ if impl_ == impl_id {
1028
+ Some ( ( id, ty) )
1029
+ } else {
1030
+ None
1031
+ }
1032
+ } ) ) ;
979
1033
}
980
- let atpit_coercion_table : FxHashMap < _ , _ > = collector
981
- . opaque_tys
1034
+
1035
+ let tait_coercion_table : FxHashMap < _ , _ > = taits
982
1036
. into_iter ( )
983
- . filter_map ( |( opaque_ty_id , ty) | {
984
- if let ImplTraitId :: AssociatedTypeImplTrait ( alias_id, _) =
985
- self . db . lookup_intern_impl_trait_id ( opaque_ty_id . into ( ) )
1037
+ . filter_map ( |( id , ty) | {
1038
+ if let ImplTraitId :: TypeAliasImplTrait ( alias_id, _) =
1039
+ self . db . lookup_intern_impl_trait_id ( id . into ( ) )
986
1040
{
987
- if assoc_tys . contains ( & alias_id) {
988
- let alias_placeholders = TyBuilder :: placeholder_subst ( self . db , alias_id ) ;
989
- let ty = self . insert_inference_vars_for_impl_trait ( ty , alias_placeholders ) ;
990
- return Some ( ( opaque_ty_id , ty ) ) ;
991
- }
1041
+ let subst = TyBuilder :: placeholder_subst ( self . db , alias_id) ;
1042
+ let ty = self . insert_inference_vars_for_impl_trait ( ty , subst ) ;
1043
+ Some ( ( id , ty ) )
1044
+ } else {
1045
+ None
992
1046
}
993
-
994
- None
995
1047
} )
996
1048
. collect ( ) ;
997
1049
998
- if !atpit_coercion_table . is_empty ( ) {
999
- self . table . atpit_coercion_table = Some ( atpit_coercion_table ) ;
1050
+ if !tait_coercion_table . is_empty ( ) {
1051
+ self . table . tait_coercion_table = Some ( tait_coercion_table ) ;
1000
1052
}
1001
1053
}
1002
1054
0 commit comments