@@ -60,14 +60,14 @@ class Definitions {
60
60
private def enterCompleteClassSymbol (owner : Symbol , name : TypeName , flags : FlagSet , parents : List [TypeRef ], decls : Scope = newScope) =
61
61
ctx.newCompleteClassSymbol(owner, name, flags | Permanent , parents, decls).entered
62
62
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 ))
65
65
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 )
68
68
69
69
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 )
71
71
72
72
// NOTE: Ideally we would write `parentConstrs: => Type*` but SIP-24 is only
73
73
// implemented in Dotty and not in Scala 2.
@@ -89,7 +89,7 @@ class Definitions {
89
89
newClassSymbol(ScalaPackageClass , name, EmptyFlags , completer).entered
90
90
}
91
91
92
- /** The trait FunctionN or ImplicitFunctionN, for some N
92
+ /** The trait FunctionN, ImplicitFunctionN, PhantomFunctionM, ImplicitPhantomFunctionM , for some N
93
93
* @param name The name of the trait to be created
94
94
*
95
95
* FunctionN traits follow this template:
@@ -107,30 +107,45 @@ class Definitions {
107
107
* trait ImplicitFunctionN[T0,...,T{N-1}, R] extends Object with FunctionN[T0,...,T{N-1}, R] {
108
108
* def apply(implicit $x0: T0, ..., $x{N_1}: T{N-1}): R
109
109
* }
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
+ *
110
127
*/
111
128
private def newFunctionNTrait (name : TypeName ) = {
112
129
val completer = new LazyType {
113
130
def complete (denot : SymDenotation )(implicit ctx : Context ): Unit = {
114
131
val cls = denot.asClass.classSymbol
115
132
val decls = newScope
116
- val arity = name.functionArity
133
+ val phantomicity = name.phantomicity
134
+ val arity = phantomicity.arity
117
135
val argParams =
118
136
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
121
139
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))
126
144
}
127
145
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)
134
149
}
135
150
}
136
151
newClassSymbol(ScalaPackageClass , name, Trait | NoInits , completer)
@@ -640,7 +655,7 @@ class Definitions {
640
655
641
656
object FunctionOf {
642
657
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 )
644
659
def unapply (ft : Type )(implicit ctx : Context ) = {
645
660
val tsym = ft.typeSymbol
646
661
if (isFunctionClass(tsym)) {
@@ -698,18 +713,30 @@ class Definitions {
698
713
lazy val TupleType = mkArityArray(" scala.Tuple" , MaxTupleArity , 2 )
699
714
lazy val ProductNType = mkArityArray(" scala.Product" , MaxTupleArity , 0 )
700
715
701
- def FunctionClass (n : Int , isImplicit : Boolean = false )(implicit ctx : Context ) =
716
+ def FunctionClass (n : Int , isImplicit : Boolean = false )(implicit ctx : Context ): Symbol =
702
717
if (isImplicit) ctx.requiredClass(" scala.ImplicitFunction" + n.toString)
703
718
else if (n <= MaxImplementedFunctionArity ) FunctionClassPerRun ()(ctx)(n)
704
719
else ctx.requiredClass(" scala.Function" + n.toString)
705
720
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
+
706
728
lazy val Function0_applyR = ImplementedFunctionType (0 ).symbol.requiredMethodRef(nme.apply)
707
729
def Function0_apply (implicit ctx : Context ) = Function0_applyR .symbol
708
730
709
731
def FunctionType (n : Int , isImplicit : Boolean = false )(implicit ctx : Context ): TypeRef =
710
732
if (n <= MaxImplementedFunctionArity && (! isImplicit || ctx.erasedTypes)) ImplementedFunctionType (n)
711
733
else FunctionClass (n, isImplicit).typeRef
712
734
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
+
713
740
private lazy val TupleTypes : Set [TypeRef ] = TupleType .toSet
714
741
private lazy val ProductTypes : Set [TypeRef ] = ProductNType .toSet
715
742
@@ -735,23 +762,37 @@ class Definitions {
735
762
/** Is a function class.
736
763
* - FunctionN for N >= 0
737
764
* - ImplicitFunctionN for N >= 0
765
+ * - PhantomFunctionM for a valid M
766
+ * - ImplicitPhantomFunctionM for a valid M
738
767
*/
739
768
def isFunctionClass (cls : Symbol ) = scalaClassName(cls).isFunction
740
769
741
770
/** Is an implicit function class.
742
771
* - ImplicitFunctionN for N >= 0
772
+ * - ImplicitPhantomFunctionN for a valid M
743
773
*/
744
774
def isImplicitFunctionClass (cls : Symbol ) = scalaClassName(cls).isImplicitFunction
745
775
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
+
746
782
/** Is a class that will be erased to FunctionXXL
747
783
* - FunctionN for N >= 22
748
784
* - 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
749
787
*/
750
- def isXXLFunctionClass (cls : Symbol ) = scalaClassName(cls).functionArity > MaxImplementedFunctionArity
788
+ def isXXLFunctionClass (cls : Symbol ) =
789
+ scalaClassName(cls).phantomicity.erasedArity > MaxImplementedFunctionArity
751
790
752
791
/** Is a synthetic function class
753
792
* - FunctionN for N > 22
754
793
* - ImplicitFunctionN for N >= 0
794
+ * - PhantomFunctionM for a valid M
795
+ * - ImplicitPhantomFunctionM for a valid M
755
796
*/
756
797
def isSyntheticFunctionClass (cls : Symbol ) = scalaClassName(cls).isSyntheticFunction
757
798
@@ -760,31 +801,42 @@ class Definitions {
760
801
def isProductClass (cls : Symbol ) = isVarArityClass(cls, tpnme.Product )
761
802
762
803
/** Returns the erased class of the function class `cls`
763
- * - FunctionN for N > 22 becomes FunctionXXL
764
804
* - FunctionN for 22 > N >= 0 remains as FunctionN
765
- * - ImplicitFunctionN for N > 22 becomes FunctionXXL
805
+ * - FunctionN for N > 22 becomes FunctionXXL
766
806
* - ImplicitFunctionN for 22 > N >= 0 becomes FunctionN
807
+ * - ImplicitFunctionN for N > 22 becomes FunctionXXL
767
808
* - anything else becomes a NoSymbol
768
809
*/
769
810
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)
774
826
}
775
827
776
828
/** Returns the erased type of the function class `cls`
777
- * - FunctionN for N > 22 becomes FunctionXXL
778
829
* - FunctionN for 22 > N >= 0 remains as FunctionN
779
- * - ImplicitFunctionN for N > 22 becomes FunctionXXL
830
+ * - FunctionN for N > 22 becomes FunctionXXL
780
831
* - ImplicitFunctionN for 22 > N >= 0 becomes FunctionN
832
+ * - ImplicitFunctionN for N > 22 becomes FunctionXXL
781
833
* - anything else becomes a NoType
782
834
*/
783
835
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)
788
840
}
789
841
790
842
val predefClassNames : Set [Name ] =
@@ -828,7 +880,10 @@ class Definitions {
828
880
* trait gets screwed up. Therefore, it is mandatory that FunctionXXL
829
881
* is treated as a NoInit trait.
830
882
*/
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)
832
887
833
888
def isPolymorphicAfterErasure (sym : Symbol ) =
834
889
(sym eq Any_isInstanceOf ) || (sym eq Any_asInstanceOf )
@@ -857,7 +912,7 @@ class Definitions {
857
912
def isFunctionType (tp : Type )(implicit ctx : Context ) = {
858
913
val arity = functionArity(tp)
859
914
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)
861
916
}
862
917
863
918
def functionArity (tp : Type )(implicit ctx : Context ) = tp.dealias.argInfos.length - 1
@@ -1013,14 +1068,16 @@ class Definitions {
1013
1068
def isPhantomAssume (sym : Symbol )(implicit ctx : Context ): Boolean =
1014
1069
sym.exists && (sym.owner eq PhantomClass ) && sym.name == nme.assume_
1015
1070
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
1019
1075
}
1020
1076
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
1024
1081
}
1025
1082
1026
1083
lazy val ErasedPhantomClass = ctx.requiredClass(" dotty.runtime.ErasedPhantom" )
0 commit comments