@@ -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)
@@ -635,7 +650,7 @@ class Definitions {
635
650
636
651
object FunctionOf {
637
652
def apply (args : List [Type ], resultType : Type , isImplicit : Boolean = false )(implicit ctx : Context ) =
638
- FunctionType (args.length , isImplicit).appliedTo(args ::: resultType :: Nil )
653
+ FunctionType (Phantomicity ( args :+ resultType) , isImplicit).appliedTo(args ::: resultType :: Nil )
639
654
def unapply (ft : Type )(implicit ctx : Context ) = {
640
655
val tsym = ft.typeSymbol
641
656
if (isFunctionClass(tsym)) {
@@ -693,18 +708,30 @@ class Definitions {
693
708
lazy val TupleType = mkArityArray(" scala.Tuple" , MaxTupleArity , 2 )
694
709
lazy val ProductNType = mkArityArray(" scala.Product" , MaxTupleArity , 0 )
695
710
696
- def FunctionClass (n : Int , isImplicit : Boolean = false )(implicit ctx : Context ) =
711
+ def FunctionClass (n : Int , isImplicit : Boolean = false )(implicit ctx : Context ): Symbol =
697
712
if (isImplicit) ctx.requiredClass(" scala.ImplicitFunction" + n.toString)
698
713
else if (n <= MaxImplementedFunctionArity ) FunctionClassPerRun ()(ctx)(n)
699
714
else ctx.requiredClass(" scala.Function" + n.toString)
700
715
716
+ def FunctionClass (phantomicity : Phantomicity , isImplicit : Boolean )(implicit ctx : Context ): Symbol = {
717
+ if (phantomicity.hasPhantoms) {
718
+ val prefix = if (isImplicit) " scala.ImplicitPhantomFunction" else " scala.PhantomFunction"
719
+ ctx.requiredClass(prefix + phantomicity.encodedString)
720
+ } else FunctionClass (phantomicity.arity, isImplicit)
721
+ }
722
+
701
723
lazy val Function0_applyR = ImplementedFunctionType (0 ).symbol.requiredMethodRef(nme.apply)
702
724
def Function0_apply (implicit ctx : Context ) = Function0_applyR .symbol
703
725
704
726
def FunctionType (n : Int , isImplicit : Boolean = false )(implicit ctx : Context ): TypeRef =
705
727
if (n <= MaxImplementedFunctionArity && (! isImplicit || ctx.erasedTypes)) ImplementedFunctionType (n)
706
728
else FunctionClass (n, isImplicit).typeRef
707
729
730
+ def FunctionType (phantomicity : Phantomicity , isImplicit : Boolean )(implicit ctx : Context ): TypeRef = {
731
+ if (phantomicity.hasPhantoms) FunctionClass (phantomicity, isImplicit).typeRef
732
+ else FunctionType (phantomicity.arity, isImplicit)
733
+ }
734
+
708
735
private lazy val TupleTypes : Set [TypeRef ] = TupleType .toSet
709
736
private lazy val ProductTypes : Set [TypeRef ] = ProductNType .toSet
710
737
@@ -730,23 +757,37 @@ class Definitions {
730
757
/** Is a function class.
731
758
* - FunctionN for N >= 0
732
759
* - ImplicitFunctionN for N >= 0
760
+ * - PhantomFunctionM for a valid M
761
+ * - ImplicitPhantomFunctionM for a valid M
733
762
*/
734
763
def isFunctionClass (cls : Symbol ) = scalaClassName(cls).isFunction
735
764
736
765
/** Is an implicit function class.
737
766
* - ImplicitFunctionN for N >= 0
767
+ * - ImplicitPhantomFunctionN for a valid M
738
768
*/
739
769
def isImplicitFunctionClass (cls : Symbol ) = scalaClassName(cls).isImplicitFunction
740
770
771
+ /** Is a phantom function class.
772
+ * - PhantomFunctionM for a valid M
773
+ * - ImplicitPhantomFunctionM for a valid M
774
+ */
775
+ def isPhantomFunctionClass (cls : Symbol ) = scalaClassName(cls).isPhantomFunction
776
+
741
777
/** Is a class that will be erased to FunctionXXL
742
778
* - FunctionN for N >= 22
743
779
* - ImplicitFunctionN for N >= 22
780
+ * - PhantomFunctionM for N >= 22, where N is the number of non phantoms in M
781
+ * - ImplicitPhantomFunctionM for N >= 22, where N is the number of non phantoms in M
744
782
*/
745
- def isXXLFunctionClass (cls : Symbol ) = scalaClassName(cls).functionArity > MaxImplementedFunctionArity
783
+ def isXXLFunctionClass (cls : Symbol ) =
784
+ scalaClassName(cls).phantomicity.erasedArity > MaxImplementedFunctionArity
746
785
747
786
/** Is a synthetic function class
748
787
* - FunctionN for N > 22
749
788
* - ImplicitFunctionN for N >= 0
789
+ * - PhantomFunctionM for a valid M
790
+ * - ImplicitPhantomFunctionM for a valid M
750
791
*/
751
792
def isSyntheticFunctionClass (cls : Symbol ) = scalaClassName(cls).isSyntheticFunction
752
793
@@ -755,31 +796,42 @@ class Definitions {
755
796
def isProductClass (cls : Symbol ) = isVarArityClass(cls, tpnme.Product )
756
797
757
798
/** Returns the erased class of the function class `cls`
758
- * - FunctionN for N > 22 becomes FunctionXXL
759
799
* - FunctionN for 22 > N >= 0 remains as FunctionN
760
- * - ImplicitFunctionN for N > 22 becomes FunctionXXL
800
+ * - FunctionN for N > 22 becomes FunctionXXL
761
801
* - ImplicitFunctionN for 22 > N >= 0 becomes FunctionN
802
+ * - ImplicitFunctionN for N > 22 becomes FunctionXXL
762
803
* - anything else becomes a NoSymbol
763
804
*/
764
805
def erasedFunctionClass (cls : Symbol ): Symbol = {
765
- val arity = scalaClassName(cls).functionArity
766
- if (arity > 22 ) defn.FunctionXXLClass
767
- else if (arity >= 0 ) defn.FunctionClass (arity)
768
- else NoSymbol
806
+ val phantomicity = scalaClassName(cls).phantomicity
807
+ if (! phantomicity.isValid) NoSymbol
808
+ else if (phantomicity.erasedArity > 22 ) defn.FunctionXXLClass
809
+ else defn.FunctionClass (phantomicity.erasedArity)
810
+ }
811
+
812
+ /** Returns the erased class of the function class `cls`
813
+ * - PhantomFunctionM becomes FunctionN where N is the number of non phantoms in M
814
+ * - ImplicitPhantomFunctionM becomes ImplicitFunctionN where N is the number of non phantoms in M
815
+ * - cls otherwise
816
+ */
817
+ def erasedPhantomsFunctionClass (cls : Symbol ): Symbol = {
818
+ val phantomicity = scalaClassName(cls).phantomicity
819
+ if (! phantomicity.isValid) cls
820
+ else defn.FunctionClass (phantomicity.erasedArity, cls.name.isImplicitFunction)
769
821
}
770
822
771
823
/** Returns the erased type of the function class `cls`
772
- * - FunctionN for N > 22 becomes FunctionXXL
773
824
* - FunctionN for 22 > N >= 0 remains as FunctionN
774
- * - ImplicitFunctionN for N > 22 becomes FunctionXXL
825
+ * - FunctionN for N > 22 becomes FunctionXXL
775
826
* - ImplicitFunctionN for 22 > N >= 0 becomes FunctionN
827
+ * - ImplicitFunctionN for N > 22 becomes FunctionXXL
776
828
* - anything else becomes a NoType
777
829
*/
778
830
def erasedFunctionType (cls : Symbol ): Type = {
779
- val arity = scalaClassName(cls).functionArity
780
- if (arity > 22 ) defn. FunctionXXLType
781
- else if (arity >= 0 ) defn.FunctionType (arity)
782
- else NoType
831
+ val phantomicity = scalaClassName(cls).phantomicity
832
+ if (! phantomicity.isValid) NoType
833
+ else if (phantomicity.erasedArity > 22 ) defn.FunctionXXLType
834
+ else defn. FunctionType (phantomicity.erasedArity)
783
835
}
784
836
785
837
val predefClassNames : Set [Name ] =
@@ -823,7 +875,10 @@ class Definitions {
823
875
* trait gets screwed up. Therefore, it is mandatory that FunctionXXL
824
876
* is treated as a NoInit trait.
825
877
*/
826
- lazy val NoInitClasses = NotRuntimeClasses + FunctionXXLClass
878
+ private lazy val NoInitClasses = NotRuntimeClasses + FunctionXXLClass
879
+
880
+ def isNoInitClass (cls : Symbol ): Boolean =
881
+ cls.is(NoInitsTrait ) || NoInitClasses .contains(cls) || isFunctionClass(cls)
827
882
828
883
def isPolymorphicAfterErasure (sym : Symbol ) =
829
884
(sym eq Any_isInstanceOf ) || (sym eq Any_asInstanceOf )
@@ -852,7 +907,7 @@ class Definitions {
852
907
def isFunctionType (tp : Type )(implicit ctx : Context ) = {
853
908
val arity = functionArity(tp)
854
909
val sym = tp.dealias.typeSymbol
855
- arity >= 0 && isFunctionClass(sym) && tp.isRef(FunctionType (arity , sym.name.isImplicitFunction).typeSymbol)
910
+ arity >= 0 && isFunctionClass(sym) && tp.isRef(FunctionType (sym.name.phantomicity , sym.name.isImplicitFunction).typeSymbol)
856
911
}
857
912
858
913
def functionArity (tp : Type )(implicit ctx : Context ) = tp.dealias.argInfos.length - 1
@@ -1008,14 +1063,16 @@ class Definitions {
1008
1063
def isPhantomAssume (sym : Symbol )(implicit ctx : Context ): Boolean =
1009
1064
sym.exists && (sym.owner eq PhantomClass ) && sym.name == nme.assume_
1010
1065
1011
- def topOf (tp : Type )(implicit ctx : Context ): Type = tp.phantomTopClass match {
1012
- case top : ClassInfo => top.prefix.select(tpnme.Any )
1013
- case _ => defn.AnyType
1066
+ def topOf (tp : Type )(implicit ctx : Context ): Type = {
1067
+ val lattice = tp.phantomLatticeClass
1068
+ if (lattice.exists) lattice.select(tpnme.Any )
1069
+ else defn.AnyType
1014
1070
}
1015
1071
1016
- def bottomOf (tp : Type )(implicit ctx : Context ): Type = tp.phantomTopClass match {
1017
- case top : ClassInfo => top.prefix.select(tpnme.Nothing )
1018
- case _ => defn.NothingType
1072
+ def bottomOf (tp : Type )(implicit ctx : Context ): Type = {
1073
+ val lattice = tp.phantomLatticeClass
1074
+ if (lattice.exists) lattice.select(tpnme.Nothing )
1075
+ else defn.NothingType
1019
1076
}
1020
1077
1021
1078
lazy val ErasedPhantomClass = ctx.requiredClass(" dotty.runtime.ErasedPhantom" )
0 commit comments