@@ -709,20 +709,19 @@ object Contexts {
709709  }
710710
711711  sealed  abstract  class  GADTMap  {
712-     def  setBounds (sym : Symbol , b : TypeBounds )(implicit  ctx : Context ):  Unit 
712+     def  addEmptyBounds (sym : Symbol )(implicit  ctx : Context ):  Unit 
713+     def  addBound (sym : Symbol , bound : Type , isUpper : Boolean )(implicit  ctx : Context ):  Boolean 
713714    def  bounds (sym : Symbol )(implicit  ctx : Context ):  TypeBounds 
714715    def  contains (sym : Symbol )(implicit  ctx : Context ):  Boolean 
715716    def  derived :  GADTMap 
716717  }
717718
718-   class  SmartGADTMap (
719+   final   class  SmartGADTMap (
719720    private [this ] var  myConstraint :  Constraint  =  new  OrderingConstraint (SimpleIdentityMap .Empty , SimpleIdentityMap .Empty , SimpleIdentityMap .Empty ),
720-     private [this ] var  mapping :  SimpleIdentityMap [Symbol , TypeVar ] =  SimpleIdentityMap .Empty 
721+     private [this ] var  mapping :  SimpleIdentityMap [Symbol , TypeVar ] =  SimpleIdentityMap .Empty ,
722+     private [this ] var  reverseMapping :  SimpleIdentityMap [TypeVar , Symbol ] =  SimpleIdentityMap .Empty 
721723  ) extends  GADTMap  with  ConstraintHandling  {
722-     def  log (str : String ):  Unit  =  {
723-       import  dotty .tools .dotc .config .Printers .gadts 
724-       gadts.println(s " GADTMap:  $str" )
725-     }
724+     import  dotty .tools .dotc .config .Printers .gadts 
726725
727726    //  TODO: dirty kludge - should this class be an inner class of TyperState instead?
728727    private [this ] var  myCtx :  Context  =  null 
@@ -739,56 +738,120 @@ object Contexts {
739738    override  def  isSubType (tp1 : Type , tp2 : Type ):  Boolean  =  ctx.typeComparer.isSubType(tp1, tp2)
740739    override  def  isSameType (tp1 : Type , tp2 : Type ):  Boolean  =  ctx.typeComparer.isSameType(tp1, tp2)
741740
742-     private [this ] def  tvar (sym : Symbol )(implicit  ctx : Context ) =  inCtx(ctx) {
741+     private [this ] def  tvar (sym : Symbol )(implicit  ctx : Context ):   TypeVar  =  inCtx(ctx) {
743742      val  res  =  mapping(sym) match  {
744743        case  tv : TypeVar  =>  tv
745744        case  null  => 
746-           log(i " creating tvar for:  $sym" )
747745          val  res  =  {
748746            import  NameKinds .DepParamName 
749-             //  do not use newTypeVar:
750-             //  it registers the TypeVar with TyperState, we don't want that since it instantiates them (TODO: when?)
751-             //  (see pos/i3500.scala)
752-             //  it registers the TypeVar with TyperState Constraint, which we don't care for but it's needless
753-             val  poly  =  PolyType (DepParamName .fresh().toTypeName ::  Nil )(
747+             //  avoid registering the TypeVar with TyperState / TyperState#constraint
748+             //  TyperState TypeVars get instantiated when we don't want them to (see pos/i3500.scala)
749+             //  TyperState#constraint TypeVars can be narrowed in subtype checks - don't want that either
750+             val  poly  =  PolyType (DepParamName .fresh(sym.name.toTypeName) ::  Nil )(
754751              pt =>  TypeBounds .empty ::  Nil ,
755752              pt =>  defn.AnyType )
756-             //  null out creatorState, we don't need it anyway (and TypeVar can null it too) 
753+             //  null out creatorState as a precaution 
757754            new  TypeVar (poly.paramRefs.head, creatorState =  null )
758755          }
756+           gadts.println(i " GADTMap: created tvar  $sym ->  $res" )
759757          constraint =  constraint.add(res.origin.binder, res ::  Nil )
760758          mapping =  mapping.updated(sym, res)
759+           reverseMapping =  reverseMapping.updated(res, sym)
761760          res
762761      }
763-       log(i " tvar:  $sym ->  $res" )
764762      res
765763    }
766764
767-     override  def  setBounds (sym : Symbol , b : TypeBounds )(implicit  ctx : Context ):  Unit  =  inCtx(ctx) {
768-       val  tv  =  tvar(sym)
769-       log(i " setBounds ` $sym` ` $tv`: ` $b` " )
770-       addUpperBound(tv.origin, b.hi)
771-       addLowerBound(tv.origin, b.lo)
765+     override  def  addEmptyBounds (sym : Symbol )(implicit  ctx : Context ):  Unit  =  tvar(sym)
766+ 
767+     override  def  addBound (sym : Symbol , bound : Type , isUpper : Boolean )(implicit  ctx : Context ):  Boolean  =  inCtx(ctx) {
768+       def  isEmptyBounds (tp : Type ) =  tp match  {
769+         case  TypeBounds (lo, hi) =>  (lo eq defn.NothingType ) &&  (hi eq defn.AnyType )
770+         case  _ =>  false 
771+       }
772+ 
773+       val  symTvar  =  tvar(sym)
774+ 
775+       def  doAddOrdering (bound : TypeParamRef ) = 
776+         if  (isUpper) addLess(symTvar.origin, bound) else  addLess(bound, symTvar.origin)
777+ 
778+       def  doAddBound (bound : Type ) = 
779+         if  (isUpper) addUpperBound(symTvar.origin, bound) else  addLowerBound(symTvar.origin, bound)
780+ 
781+       val  tvarBound  =  (new  TypeVarInsertingMap )(bound)
782+       val  res  =  tvarBound match  {
783+         case  boundTvar : TypeVar  => 
784+           if  (boundTvar eq symTvar) true  else  doAddOrdering(boundTvar.origin)
785+         //  hack to normalize T and T[_]
786+         case  AppliedType (boundTvar : TypeVar , args) if  args forall isEmptyBounds => 
787+           doAddOrdering(boundTvar.origin)
788+         case  tp =>  doAddBound(tp)
789+       }
790+ 
791+       gadts.println {
792+         val  descr  =  if  (isUpper) " upper"   else  " lower" 
793+         val  op  =  if  (isUpper) " <:"   else  " >:" 
794+         i " adding  $descr bound  $sym  $op  $bound =  $res\t (  $symTvar  $op  $tvarBound ) " 
795+       }
796+       res
772797    }
773798
774799    override  def  bounds (sym : Symbol )(implicit  ctx : Context ):  TypeBounds  =  inCtx(ctx) {
775800      mapping(sym) match  {
776801        case  null  =>  null 
777-         case  tv =>  constraint.fullBounds(tv.origin)
802+         case  tv => 
803+           val  tb  =  constraint.fullBounds(tv.origin)
804+           val  res  =  {
805+             val  tm  =  new  TypeVarRemovingMap 
806+             tb.derivedTypeBounds(tm(tb.lo), tm(tb.hi))
807+           }
808+           gadts.println(i " gadt bounds  $sym:  $res\t (  $tv:  $tb ) " )
809+           res
778810      }
779811    }
780812
781-     override  def  contains (sym : Symbol )(implicit  ctx : Context ) =  mapping(sym) ne null 
813+     override  def  contains (sym : Symbol )(implicit  ctx : Context ):   Boolean  =  mapping(sym) ne null 
782814
783815    override  def  derived :  GADTMap  =  new  SmartGADTMap (
784816      this .myConstraint,
785-       this .mapping
817+       this .mapping,
818+       this .reverseMapping
786819    )
820+ 
821+     private  final  class  TypeVarInsertingMap  extends  TypeMap  {
822+       override  def  apply (tp : Type ):  Type  =  tp match  {
823+         case  tp : TypeRef  => 
824+           val  sym  =  tp.typeSymbol
825+           if  (contains(sym)) tvar(sym) else  tp
826+         case  _ => 
827+           mapOver(tp)
828+       }
829+     }
830+ 
831+     private  final  class  TypeVarRemovingMap  extends  TypeMap  {
832+       override  def  apply (tp : Type ):  Type  =  tp match  {
833+         case  tpr : TypeParamRef  => 
834+           constraint.typeVarOfParam(tpr) match  {
835+             case  tv : TypeVar  => 
836+               reverseMapping(tv).typeRef
837+             case  unexpected => 
838+               //  if we didn't get a TypeVar, it's likely to cause problems
839+               gadts.println(i " GADTMap: unexpected typeVarOfParam( $tpr) = ` $unexpected`  ${unexpected.getClass}" )
840+               tpr
841+           }
842+         case  tv : TypeVar  => 
843+           if  (reverseMapping.contains(tv)) reverseMapping(tv).typeRef
844+           else  tv
845+         case  _ => 
846+           mapOver(tp)
847+       }
848+     }
787849  }
788850
789851  @ sharable object  EmptyGADTMap  extends  GADTMap  {
790-     override  def  setBounds (sym : Symbol , b : TypeBounds )(implicit  ctx : Context ) =  unsupported(" EmptyGADTMap.setBounds"  )
791-     override  def  bounds (sym : Symbol )(implicit  ctx : Context ) =  null 
852+     override  def  addEmptyBounds (sym : Symbol )(implicit  ctx : Context ):  Unit  =  unsupported(" EmptyGADTMap.addEmptyBounds"  )
853+     override  def  addBound (sym : Symbol , bound : Type , isUpper : Boolean )(implicit  ctx : Context ):  Boolean  =  unsupported(" EmptyGADTMap.addBound"  )
854+     override  def  bounds (sym : Symbol )(implicit  ctx : Context ):  TypeBounds  =  null 
792855    override  def  contains (sym : Symbol )(implicit  ctx : Context ) =  false 
793856    override  def  derived  =  new  SmartGADTMap 
794857  }
0 commit comments