@@ -61,14 +61,14 @@ class Definitions {
6161 private def enterCompleteClassSymbol (owner : Symbol , name : TypeName , flags : FlagSet , parents : List [TypeRef ], decls : Scope = newScope) =
6262 ctx.newCompleteClassSymbol(owner, name, flags | Permanent , parents, decls).entered
6363
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 ))
6666
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 )
6969
7070 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 )
7272
7373 // NOTE: Ideally we would write `parentConstrs: => Type*` but SIP-24 is only
7474 // implemented in Dotty and not in Scala 2.
@@ -90,7 +90,7 @@ class Definitions {
9090 newClassSymbol(ScalaPackageClass , name, EmptyFlags , completer).entered
9191 }
9292
93- /** The trait FunctionN or ImplicitFunctionN, for some N
93+ /** The trait FunctionN, ImplicitFunctionN, PhantomFunctionM, ImplicitPhantomFunctionM , for some N
9494 * @param name The name of the trait to be created
9595 *
9696 * FunctionN traits follow this template:
@@ -108,30 +108,45 @@ class Definitions {
108108 * trait ImplicitFunctionN[T0,...,T{N-1}, R] extends Object with FunctionN[T0,...,T{N-1}, R] {
109109 * def apply(implicit $x0: T0, ..., $x{N_1}: T{N-1}): R
110110 * }
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+ *
111128 */
112129 private def newFunctionNTrait (name : TypeName ) = {
113130 val completer = new LazyType {
114131 def complete (denot : SymDenotation )(implicit ctx : Context ): Unit = {
115132 val cls = denot.asClass.classSymbol
116133 val decls = newScope
117- val arity = name.functionArity
134+ val phantomicity = name.phantomicity
135+ val arity = phantomicity.arity
118136 val argParams =
119137 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
122140 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))
127145 }
128146 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)
135150 }
136151 }
137152 newClassSymbol(ScalaPackageClass , name, Trait | NoInits , completer)
@@ -636,7 +651,7 @@ class Definitions {
636651
637652 object FunctionOf {
638653 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 )
640655 def unapply (ft : Type )(implicit ctx : Context ) = {
641656 val tsym = ft.typeSymbol
642657 if (isFunctionClass(tsym)) {
@@ -694,18 +709,30 @@ class Definitions {
694709 lazy val TupleType = mkArityArray(" scala.Tuple" , MaxTupleArity , 2 )
695710 lazy val ProductNType = mkArityArray(" scala.Product" , MaxTupleArity , 0 )
696711
697- def FunctionClass (n : Int , isImplicit : Boolean = false )(implicit ctx : Context ) =
712+ def FunctionClass (n : Int , isImplicit : Boolean = false )(implicit ctx : Context ): Symbol =
698713 if (isImplicit) ctx.requiredClass(" scala.ImplicitFunction" + n.toString)
699714 else if (n <= MaxImplementedFunctionArity ) FunctionClassPerRun ()(ctx)(n)
700715 else ctx.requiredClass(" scala.Function" + n.toString)
701716
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+
702724 lazy val Function0_applyR = ImplementedFunctionType (0 ).symbol.requiredMethodRef(nme.apply)
703725 def Function0_apply (implicit ctx : Context ) = Function0_applyR .symbol
704726
705727 def FunctionType (n : Int , isImplicit : Boolean = false )(implicit ctx : Context ): TypeRef =
706728 if (n <= MaxImplementedFunctionArity && (! isImplicit || ctx.erasedTypes)) ImplementedFunctionType (n)
707729 else FunctionClass (n, isImplicit).typeRef
708730
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+
709736 private lazy val TupleTypes : Set [TypeRef ] = TupleType .toSet
710737 private lazy val ProductTypes : Set [TypeRef ] = ProductNType .toSet
711738
@@ -731,23 +758,37 @@ class Definitions {
731758 /** Is a function class.
732759 * - FunctionN for N >= 0
733760 * - ImplicitFunctionN for N >= 0
761+ * - PhantomFunctionM for a valid M
762+ * - ImplicitPhantomFunctionM for a valid M
734763 */
735764 def isFunctionClass (cls : Symbol ) = scalaClassName(cls).isFunction
736765
737766 /** Is an implicit function class.
738767 * - ImplicitFunctionN for N >= 0
768+ * - ImplicitPhantomFunctionN for a valid M
739769 */
740770 def isImplicitFunctionClass (cls : Symbol ) = scalaClassName(cls).isImplicitFunction
741771
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+
742778 /** Is a class that will be erased to FunctionXXL
743779 * - FunctionN for N >= 22
744780 * - 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
745783 */
746- def isXXLFunctionClass (cls : Symbol ) = scalaClassName(cls).functionArity > MaxImplementedFunctionArity
784+ def isXXLFunctionClass (cls : Symbol ) =
785+ scalaClassName(cls).phantomicity.erasedArity > MaxImplementedFunctionArity
747786
748787 /** Is a synthetic function class
749788 * - FunctionN for N > 22
750789 * - ImplicitFunctionN for N >= 0
790+ * - PhantomFunctionM for a valid M
791+ * - ImplicitPhantomFunctionM for a valid M
751792 */
752793 def isSyntheticFunctionClass (cls : Symbol ) = scalaClassName(cls).isSyntheticFunction
753794
@@ -756,31 +797,42 @@ class Definitions {
756797 def isProductClass (cls : Symbol ) = isVarArityClass(cls, tpnme.Product )
757798
758799 /** Returns the erased class of the function class `cls`
759- * - FunctionN for N > 22 becomes FunctionXXL
760800 * - FunctionN for 22 > N >= 0 remains as FunctionN
761- * - ImplicitFunctionN for N > 22 becomes FunctionXXL
801+ * - FunctionN for N > 22 becomes FunctionXXL
762802 * - ImplicitFunctionN for 22 > N >= 0 becomes FunctionN
803+ * - ImplicitFunctionN for N > 22 becomes FunctionXXL
763804 * - anything else becomes a NoSymbol
764805 */
765806 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)
770822 }
771823
772824 /** Returns the erased type of the function class `cls`
773- * - FunctionN for N > 22 becomes FunctionXXL
774825 * - FunctionN for 22 > N >= 0 remains as FunctionN
775- * - ImplicitFunctionN for N > 22 becomes FunctionXXL
826+ * - FunctionN for N > 22 becomes FunctionXXL
776827 * - ImplicitFunctionN for 22 > N >= 0 becomes FunctionN
828+ * - ImplicitFunctionN for N > 22 becomes FunctionXXL
777829 * - anything else becomes a NoType
778830 */
779831 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)
784836 }
785837
786838 val predefClassNames : Set [Name ] =
@@ -824,7 +876,10 @@ class Definitions {
824876 * trait gets screwed up. Therefore, it is mandatory that FunctionXXL
825877 * is treated as a NoInit trait.
826878 */
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)
828883
829884 def isPolymorphicAfterErasure (sym : Symbol ) =
830885 (sym eq Any_isInstanceOf ) || (sym eq Any_asInstanceOf )
@@ -853,7 +908,7 @@ class Definitions {
853908 def isFunctionType (tp : Type )(implicit ctx : Context ) = {
854909 val arity = functionArity(tp)
855910 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)
857912 }
858913
859914 def functionArity (tp : Type )(implicit ctx : Context ) = tp.dealias.argInfos.length - 1
@@ -1009,14 +1064,16 @@ class Definitions {
10091064 def isPhantomAssume (sym : Symbol )(implicit ctx : Context ): Boolean =
10101065 sym.exists && (sym.owner eq PhantomClass ) && sym.name == nme.assume_
10111066
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
10151071 }
10161072
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
10201077 }
10211078
10221079 lazy val ErasedPhantomClass = ctx.requiredClass(" dotty.runtime.ErasedPhantom" )
0 commit comments