@@ -60,14 +60,14 @@ class Definitions {
6060 private def enterCompleteClassSymbol (owner : Symbol , name : TypeName , flags : FlagSet , parents : List [TypeRef ], decls : Scope = newScope) =
6161 ctx.newCompleteClassSymbol(owner, name, flags | Permanent , parents, decls).entered
6262
63- private def enterTypeField (cls : ClassSymbol , name : TypeName , flags : FlagSet , scope : MutableScope ) =
64- scope.enter(newSymbol(cls, name, flags, TypeBounds .empty ))
63+ private def enterTypeField (cls : ClassSymbol , name : TypeName , flags : FlagSet , scope : MutableScope , typeBounds : TypeBounds ) =
64+ scope.enter(newSymbol(cls, name, flags, typeBounds ))
6565
66- private def enterTypeParam (cls : ClassSymbol , name : TypeName , flags : FlagSet , scope : MutableScope ) =
67- enterTypeField(cls, name, flags | ClassTypeParamCreationFlags , scope)
66+ private def enterTypeParam (cls : ClassSymbol , name : TypeName , flags : FlagSet , scope : MutableScope , typeBounds : TypeBounds ) =
67+ enterTypeField(cls, name, flags | ClassTypeParamCreationFlags , scope, typeBounds )
6868
6969 private def enterSyntheticTypeParam (cls : ClassSymbol , paramFlags : FlagSet , scope : MutableScope , suffix : String = " T0" ) =
70- enterTypeParam(cls, suffix.toTypeName.expandedName(cls), ExpandedName | paramFlags, scope)
70+ enterTypeParam(cls, suffix.toTypeName.expandedName(cls), ExpandedName | paramFlags, scope, TypeBounds .empty )
7171
7272 // NOTE: Ideally we would write `parentConstrs: => Type*` but SIP-24 is only
7373 // implemented in Dotty and not in Scala 2.
@@ -89,7 +89,7 @@ class Definitions {
8989 newClassSymbol(ScalaPackageClass , name, EmptyFlags , completer).entered
9090 }
9191
92- /** The trait FunctionN or ImplicitFunctionN, for some N
92+ /** The trait FunctionN, ImplicitFunctionN, PhantomFunctionM, ImplicitPhantomFunctionM , for some N
9393 * @param name The name of the trait to be created
9494 *
9595 * FunctionN traits follow this template:
@@ -107,30 +107,45 @@ class Definitions {
107107 * trait ImplicitFunctionN[T0,...,T{N-1}, R] extends Object with FunctionN[T0,...,T{N-1}, R] {
108108 * def apply(implicit $x0: T0, ..., $x{N_1}: T{N-1}): R
109109 * }
110+ *
111+ * PhantomFunctionM traits follow this template:
112+ *
113+ * trait PhantomFunctionM[T0,...T{N-1}, R] extends Object {
114+ * def apply($x0: T0, ..., $x{N_1}: T{N-1}): R
115+ * }
116+ *
117+ * where M represents the phantomicity of all Ti.
118+ *
119+ * ImplicitPhantomFunctionM traits follow this template:
120+ *
121+ * trait ImplicitPhantomFunctionM[T0,...,T{N-1}, R] extends Object with PhantomFunctionM[T0,...,T{N-1}, R] {
122+ * def apply(implicit $x0: T0, ..., $x{N_1}: T{N-1}): R
123+ * }
124+ *
125+ * where M represents the phantomicity of all Ti.
126+ *
110127 */
111128 private def newFunctionNTrait (name : TypeName ) = {
112129 val completer = new LazyType {
113130 def complete (denot : SymDenotation )(implicit ctx : Context ): Unit = {
114131 val cls = denot.asClass.classSymbol
115132 val decls = newScope
116- val arity = name.functionArity
133+ val phantomicity = name.phantomicity
134+ val arity = phantomicity.arity
117135 val argParams =
118136 for (i <- List .range(0 , arity)) yield
119- enterTypeParam(cls, name ++ " $T" ++ i.toString, Contravariant , decls)
120- val resParam = enterTypeParam(cls, name ++ " $R" , Covariant , decls)
137+ enterTypeParam(cls, name ++ " $T" ++ i.toString, Contravariant , decls, phantomicity.tParamBounds(i)).typeRef
138+ val resParam = enterTypeParam(cls, name ++ " $R" , Covariant , decls, phantomicity.tParamBounds(arity)).typeRef
121139 val (methodType, parentTraits) =
122- if (name.startsWith(tpnme. ImplicitFunction ) ) {
123- val superTrait =
124- FunctionType (arity) .appliedTo(argParams.map(_.typeRef) ::: resParam.typeRef :: Nil )
125- (ImplicitMethodType , ctx.normalizeToClassRefs(superTrait :: Nil , cls, decls))
140+ if (name.isImplicitFunction ) {
141+ val superTrait = FunctionType (phantomicity, isImplicit = false )
142+ val appliedSuperTrait = superTrait .appliedTo(argParams ::: resParam :: Nil )
143+ (ImplicitMethodType , ctx.normalizeToClassRefs(appliedSuperTrait :: Nil , cls, decls))
126144 }
127145 else (MethodType , Nil )
128- val applyMeth =
129- decls.enter(
130- newMethod(cls, nme.apply,
131- methodType(argParams.map(_.typeRef), resParam.typeRef), Deferred ))
132- denot.info =
133- ClassInfo (ScalaPackageClass .thisType, cls, ObjectType :: parentTraits, decls)
146+
147+ decls.enter(newMethod(cls, nme.apply, methodType(argParams, resParam), Deferred ))
148+ denot.info = ClassInfo (ScalaPackageClass .thisType, cls, ObjectType :: parentTraits, decls)
134149 }
135150 }
136151 newClassSymbol(ScalaPackageClass , name, Trait | NoInits , completer)
@@ -640,7 +655,7 @@ class Definitions {
640655
641656 object FunctionOf {
642657 def apply (args : List [Type ], resultType : Type , isImplicit : Boolean = false )(implicit ctx : Context ) =
643- FunctionType (args.length , isImplicit).appliedTo(args ::: resultType :: Nil )
658+ FunctionType (Phantomicity ( args :+ resultType) , isImplicit).appliedTo(args ::: resultType :: Nil )
644659 def unapply (ft : Type )(implicit ctx : Context ) = {
645660 val tsym = ft.typeSymbol
646661 if (isFunctionClass(tsym)) {
@@ -698,18 +713,30 @@ class Definitions {
698713 lazy val TupleType = mkArityArray(" scala.Tuple" , MaxTupleArity , 2 )
699714 lazy val ProductNType = mkArityArray(" scala.Product" , MaxTupleArity , 0 )
700715
701- def FunctionClass (n : Int , isImplicit : Boolean = false )(implicit ctx : Context ) =
716+ def FunctionClass (n : Int , isImplicit : Boolean = false )(implicit ctx : Context ): Symbol =
702717 if (isImplicit) ctx.requiredClass(" scala.ImplicitFunction" + n.toString)
703718 else if (n <= MaxImplementedFunctionArity ) FunctionClassPerRun ()(ctx)(n)
704719 else ctx.requiredClass(" scala.Function" + n.toString)
705720
721+ def FunctionClass (phantomicity : Phantomicity , isImplicit : Boolean )(implicit ctx : Context ): Symbol = {
722+ if (phantomicity.hasPhantoms) {
723+ val prefix = if (isImplicit) " scala.ImplicitPhantomFunction" else " scala.PhantomFunction"
724+ ctx.requiredClass(prefix + phantomicity.encodedString)
725+ } else FunctionClass (phantomicity.arity, isImplicit)
726+ }
727+
706728 lazy val Function0_applyR = ImplementedFunctionType (0 ).symbol.requiredMethodRef(nme.apply)
707729 def Function0_apply (implicit ctx : Context ) = Function0_applyR .symbol
708730
709731 def FunctionType (n : Int , isImplicit : Boolean = false )(implicit ctx : Context ): TypeRef =
710732 if (n <= MaxImplementedFunctionArity && (! isImplicit || ctx.erasedTypes)) ImplementedFunctionType (n)
711733 else FunctionClass (n, isImplicit).typeRef
712734
735+ def FunctionType (phantomicity : Phantomicity , isImplicit : Boolean )(implicit ctx : Context ): TypeRef = {
736+ if (phantomicity.hasPhantoms) FunctionClass (phantomicity, isImplicit).typeRef
737+ else FunctionType (phantomicity.arity, isImplicit)
738+ }
739+
713740 private lazy val TupleTypes : Set [TypeRef ] = TupleType .toSet
714741 private lazy val ProductTypes : Set [TypeRef ] = ProductNType .toSet
715742
@@ -735,23 +762,37 @@ class Definitions {
735762 /** Is a function class.
736763 * - FunctionN for N >= 0
737764 * - ImplicitFunctionN for N >= 0
765+ * - PhantomFunctionM for a valid M
766+ * - ImplicitPhantomFunctionM for a valid M
738767 */
739768 def isFunctionClass (cls : Symbol ) = scalaClassName(cls).isFunction
740769
741770 /** Is an implicit function class.
742771 * - ImplicitFunctionN for N >= 0
772+ * - ImplicitPhantomFunctionN for a valid M
743773 */
744774 def isImplicitFunctionClass (cls : Symbol ) = scalaClassName(cls).isImplicitFunction
745775
776+ /** Is a phantom function class.
777+ * - PhantomFunctionM for a valid M
778+ * - ImplicitPhantomFunctionM for a valid M
779+ */
780+ def isPhantomFunctionClass (cls : Symbol ) = scalaClassName(cls).isPhantomFunction
781+
746782 /** Is a class that will be erased to FunctionXXL
747783 * - FunctionN for N >= 22
748784 * - ImplicitFunctionN for N >= 22
785+ * - PhantomFunctionM for N >= 22, where N is the number of non phantoms in M
786+ * - ImplicitPhantomFunctionM for N >= 22, where N is the number of non phantoms in M
749787 */
750- def isXXLFunctionClass (cls : Symbol ) = scalaClassName(cls).functionArity > MaxImplementedFunctionArity
788+ def isXXLFunctionClass (cls : Symbol ) =
789+ scalaClassName(cls).phantomicity.erasedArity > MaxImplementedFunctionArity
751790
752791 /** Is a synthetic function class
753792 * - FunctionN for N > 22
754793 * - ImplicitFunctionN for N >= 0
794+ * - PhantomFunctionM for a valid M
795+ * - ImplicitPhantomFunctionM for a valid M
755796 */
756797 def isSyntheticFunctionClass (cls : Symbol ) = scalaClassName(cls).isSyntheticFunction
757798
@@ -760,31 +801,42 @@ class Definitions {
760801 def isProductClass (cls : Symbol ) = isVarArityClass(cls, tpnme.Product )
761802
762803 /** Returns the erased class of the function class `cls`
763- * - FunctionN for N > 22 becomes FunctionXXL
764804 * - FunctionN for 22 > N >= 0 remains as FunctionN
765- * - ImplicitFunctionN for N > 22 becomes FunctionXXL
805+ * - FunctionN for N > 22 becomes FunctionXXL
766806 * - ImplicitFunctionN for 22 > N >= 0 becomes FunctionN
807+ * - ImplicitFunctionN for N > 22 becomes FunctionXXL
767808 * - anything else becomes a NoSymbol
768809 */
769810 def erasedFunctionClass (cls : Symbol ): Symbol = {
770- val arity = scalaClassName(cls).functionArity
771- if (arity > 22 ) defn.FunctionXXLClass
772- else if (arity >= 0 ) defn.FunctionClass (arity)
773- else NoSymbol
811+ val phantomicity = scalaClassName(cls).phantomicity
812+ if (! phantomicity.isValid) NoSymbol
813+ else if (phantomicity.erasedArity > 22 ) defn.FunctionXXLClass
814+ else defn.FunctionClass (phantomicity.erasedArity)
815+ }
816+
817+ /** Returns the erased class of the function class `cls`
818+ * - PhantomFunctionM becomes FunctionN where N is the number of non phantoms in M
819+ * - ImplicitPhantomFunctionM becomes ImplicitFunctionN where N is the number of non phantoms in M
820+ * - cls otherwise
821+ */
822+ def erasedPhantomsFunctionClass (cls : Symbol ): Symbol = {
823+ val phantomicity = scalaClassName(cls).phantomicity
824+ if (! phantomicity.isValid) cls
825+ else defn.FunctionClass (phantomicity.erasedArity, cls.name.isImplicitFunction)
774826 }
775827
776828 /** Returns the erased type of the function class `cls`
777- * - FunctionN for N > 22 becomes FunctionXXL
778829 * - FunctionN for 22 > N >= 0 remains as FunctionN
779- * - ImplicitFunctionN for N > 22 becomes FunctionXXL
830+ * - FunctionN for N > 22 becomes FunctionXXL
780831 * - ImplicitFunctionN for 22 > N >= 0 becomes FunctionN
832+ * - ImplicitFunctionN for N > 22 becomes FunctionXXL
781833 * - anything else becomes a NoType
782834 */
783835 def erasedFunctionType (cls : Symbol ): Type = {
784- val arity = scalaClassName(cls).functionArity
785- if (arity > 22 ) defn. FunctionXXLType
786- else if (arity >= 0 ) defn.FunctionType (arity)
787- else NoType
836+ val phantomicity = scalaClassName(cls).phantomicity
837+ if (! phantomicity.isValid) NoType
838+ else if (phantomicity.erasedArity > 22 ) defn.FunctionXXLType
839+ else defn. FunctionType (phantomicity.erasedArity)
788840 }
789841
790842 val predefClassNames : Set [Name ] =
@@ -828,7 +880,10 @@ class Definitions {
828880 * trait gets screwed up. Therefore, it is mandatory that FunctionXXL
829881 * is treated as a NoInit trait.
830882 */
831- lazy val NoInitClasses = NotRuntimeClasses + FunctionXXLClass
883+ private lazy val NoInitClasses = NotRuntimeClasses + FunctionXXLClass
884+
885+ def isNoInitClass (cls : Symbol ): Boolean =
886+ cls.is(NoInitsTrait ) || NoInitClasses .contains(cls) || isFunctionClass(cls)
832887
833888 def isPolymorphicAfterErasure (sym : Symbol ) =
834889 (sym eq Any_isInstanceOf ) || (sym eq Any_asInstanceOf )
@@ -857,7 +912,7 @@ class Definitions {
857912 def isFunctionType (tp : Type )(implicit ctx : Context ) = {
858913 val arity = functionArity(tp)
859914 val sym = tp.dealias.typeSymbol
860- arity >= 0 && isFunctionClass(sym) && tp.isRef(FunctionType (arity , sym.name.isImplicitFunction).typeSymbol)
915+ arity >= 0 && isFunctionClass(sym) && tp.isRef(FunctionType (sym.name.phantomicity , sym.name.isImplicitFunction).typeSymbol)
861916 }
862917
863918 def functionArity (tp : Type )(implicit ctx : Context ) = tp.dealias.argInfos.length - 1
@@ -1013,14 +1068,16 @@ class Definitions {
10131068 def isPhantomAssume (sym : Symbol )(implicit ctx : Context ): Boolean =
10141069 sym.exists && (sym.owner eq PhantomClass ) && sym.name == nme.assume_
10151070
1016- def topOf (tp : Type )(implicit ctx : Context ): Type = tp.phantomTopClass match {
1017- case top : ClassInfo => top.prefix.select(tpnme.Any )
1018- case _ => defn.AnyType
1071+ def topOf (tp : Type )(implicit ctx : Context ): Type = {
1072+ val lattice = tp.phantomLatticeClass
1073+ if (lattice.exists) lattice.select(tpnme.Any )
1074+ else defn.AnyType
10191075 }
10201076
1021- def bottomOf (tp : Type )(implicit ctx : Context ): Type = tp.phantomTopClass match {
1022- case top : ClassInfo => top.prefix.select(tpnme.Nothing )
1023- case _ => defn.NothingType
1077+ def bottomOf (tp : Type )(implicit ctx : Context ): Type = {
1078+ val lattice = tp.phantomLatticeClass
1079+ if (lattice.exists) lattice.select(tpnme.Nothing )
1080+ else defn.NothingType
10241081 }
10251082
10261083 lazy val ErasedPhantomClass = ctx.requiredClass(" dotty.runtime.ErasedPhantom" )
0 commit comments