Skip to content
This repository was archived by the owner on Sep 1, 2020. It is now read-only.

Commit 83d0b6a

Browse files
committed
Basic implementation of 42.type:
- Implements mandatory `.type` for identifiers - Implements optional `.type` for literals - Fixes a few problems with it, updates .check files
1 parent d76ccf3 commit 83d0b6a

File tree

74 files changed

+290
-200
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+290
-200
lines changed

bincompat-backward.whitelist.conf

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,22 +134,17 @@ filter {
134134
problemName=MissingMethodProblem
135135
},
136136
{
137-
matchName="scala.reflect.api.Mirror.symbolOf"
137+
matchName="scala.reflect.api.Trees#SingletonTypeTreeApi.isLiteral"
138138
problemName=MissingMethodProblem
139139
},
140140
{
141-
matchName="scala.reflect.api.Mirror.typeOf"
141+
matchName="scala.reflect.api.Trees#SingletonTypeTreeApi.scala$reflect$api$Trees$SingletonTypeTreeApi$$$outer"
142142
problemName=MissingMethodProblem
143143
},
144144
{
145-
matchName="scala.reflect.api.Mirror.weakTypeOf"
145+
matchName="scala.reflect.api.Mirror.symbolOf"
146146
problemName=MissingMethodProblem
147147
},
148-
// see SI-8388
149-
{
150-
matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticIdentExtractor"
151-
problemName=MissingClassProblem
152-
},
153148
{
154149
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticIdent"
155150
problemName=MissingMethodProblem

bincompat-forward.whitelist.conf

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,11 @@ filter {
228228
problemName=MissingClassProblem
229229
},
230230
{
231-
matchName="scala.reflect.runtime.JavaMirrors#JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$followStatic"
231+
matchName="scala.reflect.api.Trees#SingletonTypeTreeApi.scala$reflect$api$Trees$SingletonTypeTreeApi$$$outer"
232+
problemName=MissingMethodProblem
233+
},
234+
{
235+
matchName="scala.reflect.api.Trees#SingletonTypeTreeApi.isLiteral"
232236
problemName=MissingMethodProblem
233237
},
234238
{
@@ -393,6 +397,10 @@ filter {
393397
{
394398
matchName="scala.reflect.runtime.Settings.ZirrefutableGeneratorPatterns"
395399
problemName=MissingMethodProblem
396-
}
400+
},
401+
{
402+
matchName="scala.reflect.runtime.JavaMirrors#JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$followStatic"
403+
problemName=MissingMethodProblem
404+
}
397405
]
398406
}

src/compiler/scala/reflect/reify/codegen/GenTypes.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ trait GenTypes {
5252
reifyBuildCall(nme.SuperType, thistpe, supertpe)
5353
case tpe @ SingleType(pre, sym) =>
5454
reifyBuildCall(nme.SingleType, pre, sym)
55-
case tpe @ ConstantType(value) =>
55+
// TODO (folone): ConstantType folding?
56+
case tpe @ ConstantType(value) if !tpe.isDeclaredSingleton =>
5657
mirrorBuildCall(nme.ConstantType, reifyProduct(value))
5758
case tpe @ TypeRef(pre, sym, args) =>
5859
reifyBuildCall(nme.TypeRef, pre, sym, args)

src/compiler/scala/tools/nsc/ast/parser/Parsers.scala

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -674,11 +674,11 @@ self =>
674674

675675
def isExprIntro: Boolean = isExprIntroToken(in.token)
676676

677-
def isTypeIntroToken(token: Token): Boolean = token match {
677+
def isTypeIntroToken(token: Token): Boolean = isLiteralToken(token) || (token match {
678678
case IDENTIFIER | BACKQUOTED_IDENT | THIS |
679-
SUPER | USCORE | LPAREN | AT => true
679+
SUPER | USCORE | LPAREN | AT | NULL => true
680680
case _ => false
681-
}
681+
})
682682

683683
def isStatSeqEnd = in.token == RBRACE || in.token == EOF
684684

@@ -861,7 +861,13 @@ self =>
861861
in.nextToken()
862862
if (in.token == RPAREN) {
863863
in.nextToken()
864-
atPos(start, accept(ARROW)) { makeFunctionTypeTree(Nil, typ()) }
864+
if (in.token == DOT && lookingAhead { in.token == TYPE }) {
865+
accept(DOT)
866+
accept(TYPE)
867+
atPos(start)(new SingletonTypeTree(Literal(Constant(()))) { override val isLiteral = true })
868+
} else {
869+
atPos(start, accept(ARROW)) { makeFunctionTypeTree(Nil, typ()) }
870+
}
865871
}
866872
else {
867873
val ts = functionTypes()
@@ -1090,6 +1096,14 @@ self =>
10901096
if (in.token == DOT) t = selectors(t, typeOK, in.skipToken())
10911097
} else {
10921098
val tok = in.token
1099+
if (tok != BACKQUOTED_IDENT && tok != IDENTIFIER) {
1100+
val lit = literal(false)
1101+
if (in.token == DOT && lookingAhead { in.token == TYPE }) {
1102+
accept(DOT)
1103+
accept(TYPE)
1104+
}
1105+
return atPos(start)(new SingletonTypeTree(lit) { override val isLiteral = true })
1106+
}
10931107
val name = ident()
10941108
t = atPos(start) {
10951109
if (tok == BACKQUOTED_IDENT) Ident(name) updateAttachment BackquotedIdentifierAttachment

src/compiler/scala/tools/nsc/transform/Constructors.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL {
640640
// methods with constant result type get literals as their body
641641
// all methods except the primary constructor go into template
642642
stat.symbol.tpe match {
643+
// TODO (folone): inlining of defs with literal-based singleton type results?
643644
case MethodType(List(), tp @ ConstantType(c)) =>
644645
defBuf += deriveDefDef(stat)(Literal(c) setPos _.pos setType tp)
645646
case _ =>

src/compiler/scala/tools/nsc/transform/Erasure.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,8 @@ abstract class Erasure extends AddInterfaces
535535
} else bridgingCall
536536
}
537537
val rhs = member.tpe match {
538-
case MethodType(Nil, ConstantType(c)) => Literal(c)
538+
// TODO (folone): inlining of defs with literal-based singleton type results?
539+
case MethodType(Nil, tp @ ConstantType(c)) if !tp.isDeclaredSingleton => Literal(c)
539540
case _ =>
540541
val sel: Tree = Select(This(root), member)
541542
val bridgingCall = (sel /: bridge.paramss)((fun, vparams) => Apply(fun, vparams map Ident))

src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,7 @@ trait MatchOptimization extends MatchTreeMaking with MatchAnalysis {
496496
val alternativesSupported = true
497497
val canJump = true
498498

499+
// TODO (folone): ConstantType folding?
499500
// Constant folding sets the type of a constant tree to `ConstantType(Constant(folded))`
500501
// The tree itself can be a literal, an ident, a selection, ...
501502
object SwitchablePattern { def unapply(pat: Tree): Option[Tree] = pat.tpe match {

src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import java.lang.ArithmeticException
1414
* @author Martin Odersky
1515
* @version 1.0
1616
*/
17+
// TODO (folone): ConstantType folding?
1718
abstract class ConstantFolder {
1819

1920
val global: Global
@@ -30,7 +31,7 @@ abstract class ConstantFolder {
3031
* the conversion.
3132
*/
3233
def apply(tree: Tree, pt: Type): Tree = fold(apply(tree), tree.tpe match {
33-
case ConstantType(x) => x convertTo pt
34+
case t @ ConstantType(x) if !t.isDeclaredSingleton => x convertTo pt
3435
case _ => null
3536
})
3637

src/compiler/scala/tools/nsc/typechecker/Infer.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,7 @@ trait Infer extends Checkable {
477477
else Some(
478478
if (targ.typeSymbol == RepeatedParamClass) targ.baseType(SeqClass)
479479
else if (targ.typeSymbol == JavaRepeatedParamClass) targ.baseType(ArrayClass)
480+
else if (targ.isDeclaredSingleton) targ
480481
// this infers Foo.type instead of "object Foo" (see also widenIfNecessary)
481482
else if (targ.typeSymbol.isModuleClass || tvar.constr.avoidWiden) targ
482483
else targ.widen

src/compiler/scala/tools/nsc/typechecker/Namers.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ trait Namers extends MethodSynthesis {
2525
var _lockedCount = 0
2626
def lockedCount = this._lockedCount
2727

28+
private var inferDependentTypes = false
29+
2830
/** Replaces any Idents for which cond is true with fresh TypeTrees().
2931
* Does the same for any trees containing EmptyTrees.
3032
*/
@@ -838,7 +840,7 @@ trait Namers extends MethodSynthesis {
838840
* value should not be widened, so it has a use even in situations
839841
* whether it is otherwise redundant (such as in a singleton.)
840842
*/
841-
private def widenIfNecessary(sym: Symbol, tpe: Type, pt: Type): Type = {
843+
private def widenIfNecessary(sym: Symbol, tpe: Type, pt: Type, isLiteral: Boolean): Type = {
842844
val getter =
843845
if (sym.isValue && sym.owner.isClass && sym.isPrivate)
844846
sym.getter(sym.owner)
@@ -863,7 +865,7 @@ trait Namers extends MethodSynthesis {
863865
)
864866
dropIllegalStarTypes(
865867
if (shouldWiden) tpe.widen
866-
else if (sym.isFinal) tpe // "final val" allowed to retain constant type
868+
else if (sym.isFinal || (isLiteral && inferDependentTypes)) tpe // "final val" allowed to retain constant type
867869
else tpe.deconst
868870
)
869871
}
@@ -876,7 +878,7 @@ trait Namers extends MethodSynthesis {
876878
case _ => defnTyper.computeType(tree.rhs, pt)
877879
}
878880

879-
val defnTpe = widenIfNecessary(tree.symbol, rhsTpe, pt)
881+
val defnTpe = widenIfNecessary(tree.symbol, rhsTpe, pt, tree.rhs.isInstanceOf[Literal])
880882
tree.tpt defineType defnTpe setPos tree.pos.focus
881883
tree.tpt.tpe
882884
}

0 commit comments

Comments
 (0)