@@ -8,7 +8,7 @@ use std::ops::Deref;
88use smol_str:: SmolStr ;
99
1010use crate :: {
11- DbIndex , GenericTpl , GenericTplId , LuaArrayType , LuaMappedType , LuaMemberKey ,
11+ DbIndex , GenericTpl , GenericTplId , LuaAliasCallKind , LuaArrayType , LuaMappedType , LuaMemberKey ,
1212 LuaOperatorMetaMethod , LuaSignatureId , LuaTupleStatus , LuaTupleType , LuaTypeDeclId ,
1313 LuaTypeNode , TypeOps ,
1414 db_index:: {
@@ -664,13 +664,25 @@ fn instantiate_variadic_type(
664664
665665fn instantiate_mapped_type ( context : & GenericInstantiateContext , mapped : & LuaMappedType ) -> LuaType {
666666 let key_context = context. with_resolve_mode ( GenericResolveMode :: Literal ) ;
667+ let homomorphic_source = mapped. param . 1 . constraint . as_ref ( ) . and_then ( |constraint| {
668+ let LuaType :: Call ( alias_call) = constraint else {
669+ return None ;
670+ } ;
671+ if alias_call. get_call_kind ( ) != LuaAliasCallKind :: KeyOf {
672+ return None ;
673+ }
674+
675+ let [ source] = alias_call. get_operands ( ) . as_slice ( ) else {
676+ return None ;
677+ } ;
678+ Some ( instantiate_type_generic_inner ( & key_context, source) )
679+ } ) ;
667680 let constraint = mapped
668681 . param
669682 . 1
670683 . constraint
671684 . as_ref ( )
672685 . map ( |ty| instantiate_type_generic_inner ( & key_context, ty) ) ;
673-
674686 if let Some ( constraint) = constraint {
675687 let mut key_types = Vec :: new ( ) ;
676688 collect_mapped_key_atoms ( & constraint, & mut key_types) ;
@@ -699,28 +711,18 @@ fn instantiate_mapped_type(context: &GenericInstantiateContext, mapped: &LuaMapp
699711 }
700712
701713 if !fields. is_empty ( ) || !index_access. is_empty ( ) {
702- // key 从 0 开始递增才被视为元组
703- if constraint. is_tuple ( ) {
704- let mut index = 0 ;
705- let mut is_tuple = true ;
706- for ( key, _) in & fields {
707- if let LuaMemberKey :: Integer ( i) = key {
708- if * i != index {
709- is_tuple = false ;
710- break ;
711- }
712- index += 1 ;
713- } else {
714- is_tuple = false ;
715- break ;
716- }
717- }
718- if is_tuple {
719- let types = fields. into_iter ( ) . map ( |( _, ty) | ty) . collect ( ) ;
720- return LuaType :: Tuple (
721- LuaTupleType :: new ( types, LuaTupleStatus :: InferResolve ) . into ( ) ,
722- ) ;
714+ // 同态映射会保留源 tuple 或可变返回值的按位形态.
715+ if match & homomorphic_source {
716+ Some ( LuaType :: Tuple ( _) ) => true ,
717+ Some ( LuaType :: Variadic ( variadic) ) => {
718+ matches ! ( variadic. deref( ) , VariadicType :: Multi ( _) )
723719 }
720+ _ => false ,
721+ } {
722+ let types = fields. into_iter ( ) . map ( |( _, ty) | ty) . collect ( ) ;
723+ return LuaType :: Tuple (
724+ LuaTupleType :: new ( types, LuaTupleStatus :: InferResolve ) . into ( ) ,
725+ ) ;
724726 }
725727 let field_map: HashMap < LuaMemberKey , LuaType > = fields. into_iter ( ) . collect ( ) ;
726728 return LuaType :: Object ( LuaObjectType :: new_with_fields ( field_map, index_access) . into ( ) ) ;
0 commit comments