@@ -511,7 +511,7 @@ function fieldcount_noerror(@nospecialize t)
511511end 
512512
513513
514- function  try_compute_fieldidx (@nospecialize ( typ) , @nospecialize (field))
514+ function  try_compute_fieldidx (typ:: DataType , @nospecialize (field))
515515    if  isa (field, Symbol)
516516        field =  fieldindex (typ, field, false )
517517        field ==  0  &&  return  nothing 
@@ -710,6 +710,7 @@ fieldtype_tfunc(@nospecialize(s0), @nospecialize(name), @nospecialize(inbounds))
710710    fieldtype_tfunc (s0, name)
711711
712712function  fieldtype_nothrow (@nospecialize (s0), @nospecialize (name))
713+     s0 ===  Bottom &&  return  true  #  unreachable
713714    if  s0 ===  Any ||  s0 ===  Type ||  DataType ⊑  s0 ||  UnionAll ⊑  s0
714715        #  We have no idea
715716        return  false 
@@ -721,14 +722,29 @@ function fieldtype_nothrow(@nospecialize(s0), @nospecialize(name))
721722        return  false 
722723    end 
723724
724-     s =  instanceof_tfunc (s0)[1 ]
725-     u =  unwrap_unionall (s)
726-     return  _fieldtype_nothrow (u, name)
725+     su =  unwrap_unionall (s0)
726+     if  isa (su, Union)
727+         return  fieldtype_nothrow (rewrap_unionall (su. a, s0), name) && 
728+                fieldtype_nothrow (rewrap_unionall (su. b, s0), name)
729+     end 
730+ 
731+     s, exact =  instanceof_tfunc (s0)
732+     s ===  Bottom &&  return  false  #  always
733+     return  _fieldtype_nothrow (s, exact, name)
727734end 
728735
729- function  _fieldtype_nothrow (@nospecialize (u), name:: Const )
736+ function  _fieldtype_nothrow (@nospecialize (s), exact:: Bool , name:: Const )
737+     u =  unwrap_unionall (s)
730738    if  isa (u, Union)
731-         return  _fieldtype_nothrow (u. a, name) &&  _fieldtype_nothrow (u. b, name)
739+         a =  _fieldtype_nothrow (u. a, exact, name)
740+         b =  _fieldtype_nothrow (u. b, exact, name)
741+         return  exact ?  (a ||  b) :  (a &&  b)
742+     end 
743+     u isa  DataType ||  return  false 
744+     u. abstract &&  return  false 
745+     if  u. name ===  _NAMEDTUPLE_NAME &&  ! isconcretetype (u)
746+         #  TODO : better approximate inference
747+         return  false 
732748    end 
733749    fld =  name. val
734750    if  isa (fld, Symbol)
@@ -747,6 +763,9 @@ function _fieldtype_nothrow(@nospecialize(u), name::Const)
747763end 
748764
749765function  fieldtype_tfunc (@nospecialize (s0), @nospecialize (name))
766+     if  s0 ===  Bottom
767+         return  Bottom
768+     end 
750769    if  s0 ===  Any ||  s0 ===  Type ||  DataType ⊑  s0 ||  UnionAll ⊑  s0
751770        return  Type
752771    end 
@@ -758,18 +777,28 @@ function fieldtype_tfunc(@nospecialize(s0), @nospecialize(name))
758777        return  Bottom
759778    end 
760779
761-     s =  instanceof_tfunc (s0)[1 ]
762-     u =  unwrap_unionall (s)
763- 
764-     if  isa (u, Union)
765-         return  tmerge (rewrap (fieldtype_tfunc (Type{u. a}, name), s),
766-                       rewrap (fieldtype_tfunc (Type{u. b}, name), s))
780+     su =  unwrap_unionall (s0)
781+     if  isa (su, Union)
782+         return  tmerge (fieldtype_tfunc (rewrap (su. a, s0), name),
783+                       fieldtype_tfunc (rewrap (su. b, s0), name))
767784    end 
768785
769-     if  ! isa (u, DataType) ||  u. abstract
770-         return  Type
786+     s, exact =  instanceof_tfunc (s0)
787+     s ===  Bottom &&  return  Bottom
788+     return  _fieldtype_tfunc (s, exact, name)
789+ end 
790+ 
791+ function  _fieldtype_tfunc (@nospecialize (s), exact:: Bool , @nospecialize (name))
792+     exact =  exact &&  ! has_free_typevars (s)
793+     u =  unwrap_unionall (s)
794+     if  isa (u, Union)
795+         return  tmerge (_fieldtype_tfunc (rewrap (u. a, s), exact, name),
796+                       _fieldtype_tfunc (rewrap (u. b, s), exact, name))
771797    end 
798+     u isa  DataType ||  return  Type
799+     u. abstract &&  return  Type
772800    if  u. name ===  _NAMEDTUPLE_NAME &&  ! isconcretetype (u)
801+         #  TODO : better approximate inference
773802        return  Type
774803    end 
775804    ftypes =  u. types
@@ -778,12 +807,25 @@ function fieldtype_tfunc(@nospecialize(s0), @nospecialize(name))
778807    end 
779808
780809    if  ! isa (name, Const)
810+         name =  widenconst (name)
781811        if  ! (Int <:  name  ||  Symbol <:  name )
782812            return  Bottom
783813        end 
784814        t =  Bottom
785815        for  i in  1 : length (ftypes)
786-             t =  tmerge (t, fieldtype_tfunc (s0, Const (i)))
816+             ft1 =  unwrapva (ftypes[i])
817+             exactft1 =  exact ||  ! has_free_typevars (ft1)
818+             ft1 =  rewrap_unionall (ft1, s)
819+             if  exactft1
820+                 if  issingletontype (ft1)
821+                     ft1 =  Const (ft1) #  ft unique via type cache
822+                 else 
823+                     ft1 =  Type{ft1}
824+                 end 
825+             else 
826+                 ft1 =  Type{ft} where  ft<: ft1 
827+             end 
828+             t =  tmerge (t, ft1)
787829            t ===  Any &&  break 
788830        end 
789831        return  t
@@ -805,10 +847,13 @@ function fieldtype_tfunc(@nospecialize(s0), @nospecialize(name))
805847        ft =  ftypes[fld]
806848    end 
807849
808-     exact  =  ( isa (s0, Const)  ||  isType (s0))  &&   ! has_free_typevars (s )
850+     exactft  =  exact  ||  ! has_free_typevars (ft )
809851    ft =  rewrap_unionall (ft, s)
810-     if  exact
811-         return  Const (ft)
852+     if  exactft
853+         if  issingletontype (ft)
854+             return  Const (ft) #  ft unique via type cache
855+         end 
856+         return  Type{ft}
812857    end 
813858    return  Type{<: ft }
814859end 
0 commit comments