@@ -36,15 +36,14 @@ use hir_def::{
3636 body:: Body ,
3737 builtin_type:: { BuiltinInt , BuiltinType , BuiltinUint } ,
3838 data:: { ConstData , StaticData } ,
39- hir:: LabelId ,
40- hir:: { BindingAnnotation , BindingId , ExprId , ExprOrPatId , PatId } ,
39+ hir:: { BindingAnnotation , BindingId , ExprId , ExprOrPatId , LabelId , PatId } ,
4140 lang_item:: { LangItem , LangItemTarget } ,
4241 layout:: Integer ,
4342 path:: { ModPath , Path } ,
4443 resolver:: { HasResolver , ResolveValueResult , Resolver , TypeNs , ValueNs } ,
4544 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 ,
4847} ;
4948use hir_expand:: name:: Name ;
5049use indexmap:: IndexSet ;
@@ -785,14 +784,19 @@ impl<'a> InferenceContext<'a> {
785784 fn collect_const ( & mut self , data : & ConstData ) {
786785 let return_ty = self . make_ty ( & data. type_ref ) ;
787786
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) ) ;
790789
791790 self . return_ty = return_ty;
792791 }
793792
794793 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;
796800 }
797801
798802 fn collect_fn ( & mut self , func : FunctionId ) {
@@ -857,11 +861,11 @@ impl<'a> InferenceContext<'a> {
857861 self . return_ty = self . normalize_associated_types_in ( return_ty) ;
858862 self . return_coercion = Some ( CoerceMany :: new ( self . return_ty . clone ( ) ) ) ;
859863
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.
862866 // So, it suffices to check for params and return types.
863867 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 ( ) ) ;
865869 }
866870
867871 fn insert_inference_vars_for_impl_trait < T > ( & mut self , t : T , placeholders : Substitution ) -> T
@@ -880,7 +884,7 @@ impl<'a> InferenceContext<'a> {
880884 ImplTraitId :: ReturnTypeImplTrait ( def, idx) => {
881885 ( self . db . return_type_impl_traits ( def) , idx)
882886 }
883- ImplTraitId :: AssociatedTypeImplTrait ( def, idx) => {
887+ ImplTraitId :: TypeAliasImplTrait ( def, idx) => {
884888 ( self . db . type_alias_impl_traits ( def) , idx)
885889 }
886890 _ => unreachable ! ( ) ,
@@ -909,23 +913,25 @@ impl<'a> InferenceContext<'a> {
909913 }
910914
911915 /// 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.
915919 ///
916920 /// The inference var stretagy is effective because;
917921 ///
918- /// - It can still unify types that coerced into ATPIT
922+ /// - It can still unify types that coerced into TAITs
919923 /// - We are pushing `impl Trait` bounds into it
920924 ///
921925 /// 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 ,
924929 table : & ' b mut InferenceTable < ' a > ,
925- opaque_tys : FxHashMap < OpaqueTyId , Ty > ,
930+ assocs : FxHashMap < OpaqueTyId , ( ImplId , Ty ) > ,
931+ non_assocs : FxHashMap < OpaqueTyId , Ty > ,
926932 }
927933
928- impl < ' a , ' b > TypeVisitor < Interner > for OpaqueTyCollector < ' a , ' b > {
934+ impl < ' a , ' b > TypeVisitor < Interner > for TypeAliasImplTraitCollector < ' a , ' b > {
929935 type BreakTy = ( ) ;
930936
931937 fn as_dyn ( & mut self ) -> & mut dyn TypeVisitor < Interner , BreakTy = Self :: BreakTy > {
@@ -944,59 +950,105 @@ impl<'a> InferenceContext<'a> {
944950 let ty = self . table . resolve_ty_shallow ( ty) ;
945951
946952 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+ }
948967 }
949968
950969 ty. super_visit_with ( self , outer_binder)
951970 }
952971 }
953972
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 ( ) ,
959978 } ;
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 ) ;
973981 }
974982
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+ } ) ) ;
9791033 }
980- let atpit_coercion_table : FxHashMap < _ , _ > = collector
981- . opaque_tys
1034+
1035+ let tait_coercion_table : FxHashMap < _ , _ > = taits
9821036 . 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 ( ) )
9861040 {
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
9921046 }
993-
994- None
9951047 } )
9961048 . collect ( ) ;
9971049
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 ) ;
10001052 }
10011053 }
10021054
0 commit comments