@@ -61,14 +61,14 @@ class Definitions {
61
61
private def enterCompleteClassSymbol (owner : Symbol , name : TypeName , flags : FlagSet , parents : List [TypeRef ], decls : Scope = newScope) =
62
62
ctx.newCompleteClassSymbol(owner, name, flags | Permanent , parents, decls).entered
63
63
64
- private def enterTypeField (cls : ClassSymbol , name : TypeName , flags : FlagSet , scope : MutableScope ) =
65
- scope.enter(newSymbol(cls, name, flags, TypeBounds .empty ))
64
+ private def enterTypeField (cls : ClassSymbol , name : TypeName , flags : FlagSet , scope : MutableScope , typeBounds : TypeBounds ) =
65
+ scope.enter(newSymbol(cls, name, flags, typeBounds ))
66
66
67
- private def enterTypeParam (cls : ClassSymbol , name : TypeName , flags : FlagSet , scope : MutableScope ) =
68
- enterTypeField(cls, name, flags | ClassTypeParamCreationFlags , scope)
67
+ private def enterTypeParam (cls : ClassSymbol , name : TypeName , flags : FlagSet , scope : MutableScope , typeBounds : TypeBounds ) =
68
+ enterTypeField(cls, name, flags | ClassTypeParamCreationFlags , scope, typeBounds )
69
69
70
70
private def enterSyntheticTypeParam (cls : ClassSymbol , paramFlags : FlagSet , scope : MutableScope , suffix : String = " T0" ) =
71
- enterTypeParam(cls, suffix.toTypeName.expandedName(cls), ExpandedName | paramFlags, scope)
71
+ enterTypeParam(cls, suffix.toTypeName.expandedName(cls), ExpandedName | paramFlags, scope, TypeBounds .empty )
72
72
73
73
// NOTE: Ideally we would write `parentConstrs: => Type*` but SIP-24 is only
74
74
// implemented in Dotty and not in Scala 2.
@@ -90,7 +90,7 @@ class Definitions {
90
90
newClassSymbol(ScalaPackageClass , name, EmptyFlags , completer).entered
91
91
}
92
92
93
- /** The trait FunctionN or ImplicitFunctionN, for some N
93
+ /** The trait FunctionN, ImplicitFunctionN, PhantomFunctionM, ImplicitPhantomFunctionM , for some N
94
94
* @param name The name of the trait to be created
95
95
*
96
96
* FunctionN traits follow this template:
@@ -108,30 +108,45 @@ class Definitions {
108
108
* trait ImplicitFunctionN[T0,...,T{N-1}, R] extends Object with FunctionN[T0,...,T{N-1}, R] {
109
109
* def apply(implicit $x0: T0, ..., $x{N_1}: T{N-1}): R
110
110
* }
111
+ *
112
+ * PhantomFunctionM traits follow this template:
113
+ *
114
+ * trait PhantomFunctionM[T0,...T{N-1}, R] extends Object {
115
+ * def apply($x0: T0, ..., $x{N_1}: T{N-1}): R
116
+ * }
117
+ *
118
+ * where M represents the phantomicity of all Ti.
119
+ *
120
+ * ImplicitPhantomFunctionM traits follow this template:
121
+ *
122
+ * trait ImplicitPhantomFunctionM[T0,...,T{N-1}, R] extends Object with PhantomFunctionM[T0,...,T{N-1}, R] {
123
+ * def apply(implicit $x0: T0, ..., $x{N_1}: T{N-1}): R
124
+ * }
125
+ *
126
+ * where M represents the phantomicity of all Ti.
127
+ *
111
128
*/
112
129
private def newFunctionNTrait (name : TypeName ) = {
113
130
val completer = new LazyType {
114
131
def complete (denot : SymDenotation )(implicit ctx : Context ): Unit = {
115
132
val cls = denot.asClass.classSymbol
116
133
val decls = newScope
117
- val arity = name.functionArity
134
+ val phantomicity = name.phantomicity
135
+ val arity = phantomicity.arity
118
136
val argParams =
119
137
for (i <- List .range(0 , arity)) yield
120
- enterTypeParam(cls, name ++ " $T" ++ i.toString, Contravariant , decls)
121
- val resParam = enterTypeParam(cls, name ++ " $R" , Covariant , decls)
138
+ enterTypeParam(cls, name ++ " $T" ++ i.toString, Contravariant , decls, phantomicity.tParamBounds(i)).typeRef
139
+ val resParam = enterTypeParam(cls, name ++ " $R" , Covariant , decls, phantomicity.tParamBounds(arity)).typeRef
122
140
val (methodType, parentTraits) =
123
- if (name.startsWith(tpnme. ImplicitFunction ) ) {
124
- val superTrait =
125
- FunctionType (arity) .appliedTo(argParams.map(_.typeRef) ::: resParam.typeRef :: Nil )
126
- (ImplicitMethodType , ctx.normalizeToClassRefs(superTrait :: Nil , cls, decls))
141
+ if (name.isImplicitFunction ) {
142
+ val superTrait = FunctionType (phantomicity, isImplicit = false )
143
+ val appliedSuperTrait = superTrait .appliedTo(argParams ::: resParam :: Nil )
144
+ (ImplicitMethodType , ctx.normalizeToClassRefs(appliedSuperTrait :: Nil , cls, decls))
127
145
}
128
146
else (MethodType , Nil )
129
- val applyMeth =
130
- decls.enter(
131
- newMethod(cls, nme.apply,
132
- methodType(argParams.map(_.typeRef), resParam.typeRef), Deferred ))
133
- denot.info =
134
- ClassInfo (ScalaPackageClass .thisType, cls, ObjectType :: parentTraits, decls)
147
+
148
+ decls.enter(newMethod(cls, nme.apply, methodType(argParams, resParam), Deferred ))
149
+ denot.info = ClassInfo (ScalaPackageClass .thisType, cls, ObjectType :: parentTraits, decls)
135
150
}
136
151
}
137
152
newClassSymbol(ScalaPackageClass , name, Trait | NoInits , completer)
@@ -636,7 +651,7 @@ class Definitions {
636
651
637
652
object FunctionOf {
638
653
def apply (args : List [Type ], resultType : Type , isImplicit : Boolean = false )(implicit ctx : Context ) =
639
- FunctionType (args.length , isImplicit).appliedTo(args ::: resultType :: Nil )
654
+ FunctionType (Phantomicity ( args :+ resultType) , isImplicit).appliedTo(args ::: resultType :: Nil )
640
655
def unapply (ft : Type )(implicit ctx : Context ) = {
641
656
val tsym = ft.typeSymbol
642
657
if (isFunctionClass(tsym)) {
@@ -694,18 +709,30 @@ class Definitions {
694
709
lazy val TupleType = mkArityArray(" scala.Tuple" , MaxTupleArity , 2 )
695
710
lazy val ProductNType = mkArityArray(" scala.Product" , MaxTupleArity , 0 )
696
711
697
- def FunctionClass (n : Int , isImplicit : Boolean = false )(implicit ctx : Context ) =
712
+ def FunctionClass (n : Int , isImplicit : Boolean = false )(implicit ctx : Context ): Symbol =
698
713
if (isImplicit) ctx.requiredClass(" scala.ImplicitFunction" + n.toString)
699
714
else if (n <= MaxImplementedFunctionArity ) FunctionClassPerRun ()(ctx)(n)
700
715
else ctx.requiredClass(" scala.Function" + n.toString)
701
716
717
+ def FunctionClass (phantomicity : Phantomicity , isImplicit : Boolean )(implicit ctx : Context ): Symbol = {
718
+ if (phantomicity.hasPhantoms) {
719
+ val prefix = if (isImplicit) " scala.ImplicitPhantomFunction" else " scala.PhantomFunction"
720
+ ctx.requiredClass(prefix + phantomicity.encodedString)
721
+ } else FunctionClass (phantomicity.arity, isImplicit)
722
+ }
723
+
702
724
lazy val Function0_applyR = ImplementedFunctionType (0 ).symbol.requiredMethodRef(nme.apply)
703
725
def Function0_apply (implicit ctx : Context ) = Function0_applyR .symbol
704
726
705
727
def FunctionType (n : Int , isImplicit : Boolean = false )(implicit ctx : Context ): TypeRef =
706
728
if (n <= MaxImplementedFunctionArity && (! isImplicit || ctx.erasedTypes)) ImplementedFunctionType (n)
707
729
else FunctionClass (n, isImplicit).typeRef
708
730
731
+ def FunctionType (phantomicity : Phantomicity , isImplicit : Boolean )(implicit ctx : Context ): TypeRef = {
732
+ if (phantomicity.hasPhantoms) FunctionClass (phantomicity, isImplicit).typeRef
733
+ else FunctionType (phantomicity.arity, isImplicit)
734
+ }
735
+
709
736
private lazy val TupleTypes : Set [TypeRef ] = TupleType .toSet
710
737
private lazy val ProductTypes : Set [TypeRef ] = ProductNType .toSet
711
738
@@ -731,23 +758,37 @@ class Definitions {
731
758
/** Is a function class.
732
759
* - FunctionN for N >= 0
733
760
* - ImplicitFunctionN for N >= 0
761
+ * - PhantomFunctionM for a valid M
762
+ * - ImplicitPhantomFunctionM for a valid M
734
763
*/
735
764
def isFunctionClass (cls : Symbol ) = scalaClassName(cls).isFunction
736
765
737
766
/** Is an implicit function class.
738
767
* - ImplicitFunctionN for N >= 0
768
+ * - ImplicitPhantomFunctionN for a valid M
739
769
*/
740
770
def isImplicitFunctionClass (cls : Symbol ) = scalaClassName(cls).isImplicitFunction
741
771
772
+ /** Is a phantom function class.
773
+ * - PhantomFunctionM for a valid M
774
+ * - ImplicitPhantomFunctionM for a valid M
775
+ */
776
+ def isPhantomFunctionClass (cls : Symbol ) = scalaClassName(cls).isPhantomFunction
777
+
742
778
/** Is a class that will be erased to FunctionXXL
743
779
* - FunctionN for N >= 22
744
780
* - ImplicitFunctionN for N >= 22
781
+ * - PhantomFunctionM for N >= 22, where N is the number of non phantoms in M
782
+ * - ImplicitPhantomFunctionM for N >= 22, where N is the number of non phantoms in M
745
783
*/
746
- def isXXLFunctionClass (cls : Symbol ) = scalaClassName(cls).functionArity > MaxImplementedFunctionArity
784
+ def isXXLFunctionClass (cls : Symbol ) =
785
+ scalaClassName(cls).phantomicity.erasedArity > MaxImplementedFunctionArity
747
786
748
787
/** Is a synthetic function class
749
788
* - FunctionN for N > 22
750
789
* - ImplicitFunctionN for N >= 0
790
+ * - PhantomFunctionM for a valid M
791
+ * - ImplicitPhantomFunctionM for a valid M
751
792
*/
752
793
def isSyntheticFunctionClass (cls : Symbol ) = scalaClassName(cls).isSyntheticFunction
753
794
@@ -756,31 +797,42 @@ class Definitions {
756
797
def isProductClass (cls : Symbol ) = isVarArityClass(cls, tpnme.Product )
757
798
758
799
/** Returns the erased class of the function class `cls`
759
- * - FunctionN for N > 22 becomes FunctionXXL
760
800
* - FunctionN for 22 > N >= 0 remains as FunctionN
761
- * - ImplicitFunctionN for N > 22 becomes FunctionXXL
801
+ * - FunctionN for N > 22 becomes FunctionXXL
762
802
* - ImplicitFunctionN for 22 > N >= 0 becomes FunctionN
803
+ * - ImplicitFunctionN for N > 22 becomes FunctionXXL
763
804
* - anything else becomes a NoSymbol
764
805
*/
765
806
def erasedFunctionClass (cls : Symbol ): Symbol = {
766
- val arity = scalaClassName(cls).functionArity
767
- if (arity > 22 ) defn.FunctionXXLClass
768
- else if (arity >= 0 ) defn.FunctionClass (arity)
769
- else NoSymbol
807
+ val phantomicity = scalaClassName(cls).phantomicity
808
+ if (! phantomicity.isValid) NoSymbol
809
+ else if (phantomicity.erasedArity > 22 ) defn.FunctionXXLClass
810
+ else defn.FunctionClass (phantomicity.erasedArity)
811
+ }
812
+
813
+ /** Returns the erased class of the function class `cls`
814
+ * - PhantomFunctionM becomes FunctionN where N is the number of non phantoms in M
815
+ * - ImplicitPhantomFunctionM becomes ImplicitFunctionN where N is the number of non phantoms in M
816
+ * - cls otherwise
817
+ */
818
+ def erasedPhantomsFunctionClass (cls : Symbol ): Symbol = {
819
+ val phantomicity = scalaClassName(cls).phantomicity
820
+ if (! phantomicity.isValid) cls
821
+ else defn.FunctionClass (phantomicity.erasedArity, cls.name.isImplicitFunction)
770
822
}
771
823
772
824
/** Returns the erased type of the function class `cls`
773
- * - FunctionN for N > 22 becomes FunctionXXL
774
825
* - FunctionN for 22 > N >= 0 remains as FunctionN
775
- * - ImplicitFunctionN for N > 22 becomes FunctionXXL
826
+ * - FunctionN for N > 22 becomes FunctionXXL
776
827
* - ImplicitFunctionN for 22 > N >= 0 becomes FunctionN
828
+ * - ImplicitFunctionN for N > 22 becomes FunctionXXL
777
829
* - anything else becomes a NoType
778
830
*/
779
831
def erasedFunctionType (cls : Symbol ): Type = {
780
- val arity = scalaClassName(cls).functionArity
781
- if (arity > 22 ) defn. FunctionXXLType
782
- else if (arity >= 0 ) defn.FunctionType (arity)
783
- else NoType
832
+ val phantomicity = scalaClassName(cls).phantomicity
833
+ if (! phantomicity.isValid) NoType
834
+ else if (phantomicity.erasedArity > 22 ) defn.FunctionXXLType
835
+ else defn. FunctionType (phantomicity.erasedArity)
784
836
}
785
837
786
838
val predefClassNames : Set [Name ] =
@@ -824,7 +876,10 @@ class Definitions {
824
876
* trait gets screwed up. Therefore, it is mandatory that FunctionXXL
825
877
* is treated as a NoInit trait.
826
878
*/
827
- lazy val NoInitClasses = NotRuntimeClasses + FunctionXXLClass
879
+ private lazy val NoInitClasses = NotRuntimeClasses + FunctionXXLClass
880
+
881
+ def isNoInitClass (cls : Symbol ): Boolean =
882
+ cls.is(NoInitsTrait ) || NoInitClasses .contains(cls) || isFunctionClass(cls)
828
883
829
884
def isPolymorphicAfterErasure (sym : Symbol ) =
830
885
(sym eq Any_isInstanceOf ) || (sym eq Any_asInstanceOf )
@@ -853,7 +908,7 @@ class Definitions {
853
908
def isFunctionType (tp : Type )(implicit ctx : Context ) = {
854
909
val arity = functionArity(tp)
855
910
val sym = tp.dealias.typeSymbol
856
- arity >= 0 && isFunctionClass(sym) && tp.isRef(FunctionType (arity , sym.name.isImplicitFunction).typeSymbol)
911
+ arity >= 0 && isFunctionClass(sym) && tp.isRef(FunctionType (sym.name.phantomicity , sym.name.isImplicitFunction).typeSymbol)
857
912
}
858
913
859
914
def functionArity (tp : Type )(implicit ctx : Context ) = tp.dealias.argInfos.length - 1
@@ -1009,14 +1064,16 @@ class Definitions {
1009
1064
def isPhantomAssume (sym : Symbol )(implicit ctx : Context ): Boolean =
1010
1065
sym.exists && (sym.owner eq PhantomClass ) && sym.name == nme.assume_
1011
1066
1012
- def topOf (tp : Type )(implicit ctx : Context ): Type = tp.phantomTopClass match {
1013
- case top : ClassInfo => top.prefix.select(tpnme.Any )
1014
- case _ => defn.AnyType
1067
+ def topOf (tp : Type )(implicit ctx : Context ): Type = {
1068
+ val lattice = tp.phantomLatticeClass
1069
+ if (lattice.exists) lattice.select(tpnme.Any )
1070
+ else defn.AnyType
1015
1071
}
1016
1072
1017
- def bottomOf (tp : Type )(implicit ctx : Context ): Type = tp.phantomTopClass match {
1018
- case top : ClassInfo => top.prefix.select(tpnme.Nothing )
1019
- case _ => defn.NothingType
1073
+ def bottomOf (tp : Type )(implicit ctx : Context ): Type = {
1074
+ val lattice = tp.phantomLatticeClass
1075
+ if (lattice.exists) lattice.select(tpnme.Nothing )
1076
+ else defn.NothingType
1020
1077
}
1021
1078
1022
1079
lazy val ErasedPhantomClass = ctx.requiredClass(" dotty.runtime.ErasedPhantom" )
0 commit comments