Skip to content

Commit 07e24e8

Browse files
committed
Merge pull request #735 from dotty-staging/ycheck-methods
Ycheck that methods defined in ClassInfo exist in tree.
2 parents 056e124 + d528035 commit 07e24e8

File tree

117 files changed

+137
-48
lines changed

Some content is hidden

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

117 files changed

+137
-48
lines changed

project/Build.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ object DottyBuild extends Build {
4242
resolvers += Resolver.sonatypeRepo("releases"),
4343

4444
// get libraries onboard
45-
partestDeps := Seq("me.d-d" % "scala-compiler" % "2.11.5-20150619-173733-3bcd390afa",
45+
partestDeps := Seq("me.d-d" % "scala-compiler" % "2.11.5-20150714-145300-2ad68448c5",
4646
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
4747
"org.scala-lang" % "scala-library" % scalaVersion.value % "test"),
4848
libraryDependencies ++= partestDeps.value,

src/dotty/tools/backend/jvm/DottyBackendInterface.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,7 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{
784784
def decls: List[Symbol] = tp.decls.map(_.symbol).toList
785785

786786
def members: List[Symbol] =
787-
tp.memberDenots(takeAllFilter, (name, buf) => buf ++= member(name).alternatives).map(_.symbol).toList
787+
tp.memberDenots(takeAllFilter, (name, buf) => buf ++= tp.member(name).alternatives).map(_.symbol).toList
788788

789789
def typeSymbol: Symbol = tp.widenDealias.typeSymbol
790790

src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ object Trees {
223223

224224
override def toText(printer: Printer) = printer.toText(this)
225225

226-
override def hashCode(): Int = System.identityHashCode(this)
226+
override def hashCode(): Int = uniqueId // for debugging; was: System.identityHashCode(this)
227227
override def equals(that: Any) = this eq that.asInstanceOf[AnyRef]
228228
}
229229

src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -177,25 +177,26 @@ object Contexts {
177177
/** The new implicit references that are introduced by this scope */
178178
private var implicitsCache: ContextualImplicits = null
179179
def implicits: ContextualImplicits = {
180-
if (implicitsCache == null )
181-
implicitsCache = {
182-
val implicitRefs: List[TermRef] =
183-
if (isClassDefContext)
184-
try owner.thisType.implicitMembers
185-
catch {
186-
case ex: CyclicReference => Nil
187-
}
188-
else if (isImportContext) importInfo.importedImplicits
189-
else if (isNonEmptyScopeContext) scope.implicitDecls
190-
else Nil
191-
val outerImplicits =
192-
if (isImportContext && importInfo.hiddenRoot.exists)
193-
outer.implicits exclude importInfo.hiddenRoot
194-
else
195-
outer.implicits
196-
if (implicitRefs.isEmpty) outerImplicits
197-
else new ContextualImplicits(implicitRefs, outerImplicits)(this)
180+
if (implicitsCache == null ) {
181+
val outerImplicits =
182+
if (isImportContext && importInfo.hiddenRoot.exists)
183+
outer.implicits exclude importInfo.hiddenRoot
184+
else
185+
outer.implicits
186+
try
187+
implicitsCache = {
188+
val implicitRefs: List[TermRef] =
189+
if (isClassDefContext) owner.thisType.implicitMembers
190+
else if (isImportContext) importInfo.importedImplicits
191+
else if (isNonEmptyScopeContext) scope.implicitDecls
192+
else Nil
193+
if (implicitRefs.isEmpty) outerImplicits
194+
else new ContextualImplicits(implicitRefs, outerImplicits)(this)
195+
}
196+
catch {
197+
case ex: CyclicReference => implicitsCache = outerImplicits
198198
}
199+
}
199200
implicitsCache
200201
}
201202

src/dotty/tools/dotc/core/NameOps.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ object NameOps {
241241
case nme.clone_ => nme.clone_
242242
}
243243

244-
def specializedFor(returnType: Types.Type, args: List[Types.Type])(implicit ctx: Context): name.ThisName = {
244+
def specializedFor(classTargs: List[Types.Type], classTargsNames: List[Name], methodTargs: List[Types.Type], methodTarsNames: List[Name])(implicit ctx: Context): name.ThisName = {
245245

246246
def typeToTag(tp: Types.Type): Name = {
247247
tp.classSymbol match {
@@ -258,9 +258,12 @@ object NameOps {
258258
}
259259
}
260260

261+
val methodTags: Seq[Name] = (methodTargs zip methodTarsNames).sortBy(_._2).map(x => typeToTag(x._1))
262+
val classTags: Seq[Name] = (classTargs zip classTargsNames).sortBy(_._2).map(x => typeToTag(x._1))
263+
261264
name.fromName(name ++ nme.specializedTypeNames.prefix ++
262-
args.map(typeToTag).foldRight(typeToTag(returnType))(_ ++ _) ++
263-
nme.specializedTypeNames.suffix)
265+
methodTags.fold(nme.EMPTY)(_ ++ _) ++ nme.specializedTypeNames.separator ++
266+
classTags.fold(nme.EMPTY)(_ ++ _) ++ nme.specializedTypeNames.suffix)
264267
}
265268

266269
/** If name length exceeds allowable limit, replace part of it by hash */

src/dotty/tools/dotc/core/Names.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,4 +348,25 @@ object Names {
348348
StringBuilder.newBuilder.mapResult(s => from.fromChars(s.toCharArray, 0, s.length))
349349
def apply(): Builder[Char, Name] = termNameBuilder
350350
}
351+
352+
implicit val NameOrdering: Ordering[Name] = new Ordering[Name] {
353+
def compare(x: Name, y: Name): Int = {
354+
if (x.isTermName && y.isTypeName) 1
355+
else if (x.isTypeName && y.isTermName) -1
356+
else if (x eq y) 0
357+
else {
358+
val until = x.length min y.length
359+
var i = 0
360+
361+
while (i < until && x(i) == y(i)) i = i + 1
362+
363+
if (i < until) {
364+
if (x(i) < y(i)) -1
365+
else /*(x(i) > y(i))*/ 1
366+
} else {
367+
x.length - y.length
368+
}
369+
}
370+
}
371+
}
351372
}

src/dotty/tools/dotc/core/StdNames.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,8 @@ object StdNames {
559559
final val Void: N = "V"
560560
final val Object: N = "L"
561561

562-
final val prefix: N = "$mc"
562+
final val prefix: N = "$m"
563+
final val separator: N = "c"
563564
final val suffix: N = "$sp"
564565
}
565566

src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,14 @@ object SymDenotations {
404404
name.toTermName == nme.COMPANION_CLASS_METHOD ||
405405
name.toTermName == nme.COMPANION_MODULE_METHOD
406406

407+
/** Is this a syntetic method that represents conversions between representations of a value class
408+
* These methods are generated in ExtensionMethods
409+
* and used in ElimErasedValueType.
410+
*/
411+
final def isValueClassConvertMethod(implicit ctx: Context) =
412+
name.toTermName == nme.U2EVT ||
413+
name.toTermName == nme.EVT2U
414+
407415
/** Is symbol a primitive value class? */
408416
def isPrimitiveValueClass(implicit ctx: Context) = defn.ScalaValueClasses contains symbol
409417

src/dotty/tools/dotc/core/Symbols.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,8 @@ object Symbols {
503503
def showKind(implicit ctx: Context): String = ctx.kindString(this)
504504
def showName(implicit ctx: Context): String = ctx.nameString(this)
505505
def showFullName(implicit ctx: Context): String = ctx.fullNameString(this)
506+
507+
override def hashCode() = id // for debugging.
506508
}
507509

508510
type TermSymbol = Symbol { type ThisName = TermName }

src/dotty/tools/dotc/core/Types.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1296,7 +1296,7 @@ object Types {
12961296
case d: SymDenotation =>
12971297
if (this.isInstanceOf[WithFixedSym]) d.current
12981298
else if (d.validFor.runId == ctx.runId || ctx.stillValid(d))
1299-
if (prefix.isTightPrefix(d.owner) || d.isConstructor) d.current
1299+
if (d.exists && prefix.isTightPrefix(d.owner) || d.isConstructor) d.current
13001300
else recomputeMember(d) // symbol could have been overridden, recompute membership
13011301
else {
13021302
val newd = loadDenot

src/dotty/tools/dotc/transform/ElimErasedValueType.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,11 @@ class ElimErasedValueType extends MiniPhaseTransform with InfoTransformer {
5656

5757
override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = {
5858
val Apply(fun, args) = tree
59-
val name = fun.symbol.name
6059

6160
// The casts to and from ErasedValueType are no longer needed once ErasedValueType
6261
// has been eliminated.
6362
val t =
64-
if ((name eq nme.U2EVT) || (name eq nme.EVT2U))
63+
if (fun.symbol.isValueClassConvertMethod)
6564
args.head
6665
else
6766
tree

src/dotty/tools/dotc/transform/FunctionalInterfaces.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,12 @@ class FunctionalInterfaces extends MiniPhaseTransform {
6363
val m = tree.meth.tpe.widen.asInstanceOf[MethodType]
6464

6565
if (shouldSpecialize(m)) {
66-
val interfaceName = (functionName ++ m.paramTypes.length.toString).specializedFor(m.resultType, m.paramTypes)
66+
val functionSymbol = tree.tpe.widenDealias.classSymbol
67+
val names = ctx.atPhase(ctx.erasurePhase) {
68+
implicit ctx => functionSymbol.typeParams.map(_.name)
69+
}
70+
val interfaceName = (functionName ++ m.paramTypes.length.toString).specializedFor(m.paramTypes ::: m.resultType :: Nil, names, Nil, Nil)
71+
6772
// symbols loaded from classpath aren't defined in periods earlier than when they where loaded
6873
val interface = ctx.withPhase(ctx.typerPhase).getClassIfDefined(functionPackage ++ interfaceName)
6974
if (interface.exists) {

src/dotty/tools/dotc/transform/Memoize.scala

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,20 @@ import Decorators._
4545
override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
4646
val sym = tree.symbol
4747

48-
def newField = ctx.newSymbol(
49-
owner = ctx.owner,
50-
name = sym.name.asTermName.fieldName,
51-
flags = Private | (if (sym is Stable) EmptyFlags else Mutable),
52-
info = sym.info.resultType,
53-
coord = tree.pos)
54-
.withAnnotationsCarrying(sym, defn.FieldMetaAnnot)
55-
.enteredAfter(thisTransform)
48+
def newField = {
49+
val fieldType =
50+
if (sym.isGetter) sym.info.resultType
51+
else /*sym.isSetter*/ sym.info.firstParamTypes.head
52+
53+
ctx.newSymbol(
54+
owner = ctx.owner,
55+
name = sym.name.asTermName.fieldName,
56+
flags = Private | (if (sym is Stable) EmptyFlags else Mutable),
57+
info = fieldType,
58+
coord = tree.pos)
59+
.withAnnotationsCarrying(sym, defn.FieldMetaAnnot)
60+
.enteredAfter(thisTransform)
61+
}
5662

5763
/** Can be used to filter annotations on getters and setters; not used yet */
5864
def keepAnnotations(denot: SymDenotation, meta: ClassSymbol) = {

src/dotty/tools/dotc/transform/Mixin.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
9898
override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Erasure])
9999

100100
override def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation =
101-
if (sym.is(Accessor, butNot = Deferred) && sym.owner.is(Trait))
101+
if (sym.is(Accessor, butNot = Deferred | Lazy) && sym.owner.is(Trait))
102102
sym.copySymDenotation(initFlags = sym.flags &~ ParamAccessor | Deferred).ensureNotPrivate
103103
else if (sym.isConstructor && sym.owner.is(Trait))
104104
sym.copySymDenotation(
@@ -108,8 +108,8 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
108108
sym
109109

110110
private def initializer(sym: Symbol)(implicit ctx: Context): TermSymbol = {
111-
val initName = InitializerName(sym.name.asTermName)
112-
sym.owner.info.decl(initName).symbol
111+
val initName = if(!sym.is(Lazy)) InitializerName(sym.name.asTermName) else sym.name.asTermName
112+
sym.owner.info.decl(initName).suchThat(_.is(Lazy) == sym.is(Lazy)).symbol
113113
.orElse(
114114
ctx.newSymbol(
115115
sym.owner,
@@ -229,7 +229,7 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
229229

230230
def setters(mixin: ClassSymbol): List[Tree] =
231231
for (setter <- mixin.info.decls.filter(setr => setr.isSetter && !wasDeferred(setr)).toList)
232-
yield DefDef(implementation(setter.asTerm), unitLiteral.withPos(cls.pos))
232+
yield transformFollowing(DefDef(implementation(setter.asTerm), unitLiteral.withPos(cls.pos)))
233233

234234
cpy.Template(impl)(
235235
constr =

src/dotty/tools/dotc/transform/PatternMatcher.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,11 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
440440

441441
def emitVars = storedBinders.nonEmpty
442442

443-
private lazy val (stored, substed) = (subPatBinders, subPatRefs).zipped.partition{ case (sym, _) => storedBinders(sym) }
443+
lazy val storedSubsted = (subPatBinders, subPatRefs).zipped.partition{ case (sym, _) => storedBinders(sym) }
444+
445+
def stored = storedSubsted._1
446+
447+
def substed = storedSubsted._2
444448

445449
// dd: this didn't yet trigger error. But I believe it would. if this causes double denition of symbol error this can be replaced with NoRebindings
446450
protected lazy val introducedRebindings: Rebindings = if (!emitVars) Rebindings(subPatBinders, subPatRefs)
@@ -1443,7 +1447,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
14431447
// require (nbSubPats > 0 && (!lastIsStar || isSeq))
14441448
protected def subPatRefs(binder: Symbol): List[Tree] = {
14451449
val refs = if (totalArity > 0 && isSeq) subPatRefsSeq(binder)
1446-
else if (totalArity > 1 && !isSeq) productElemsToN(binder, totalArity)
1450+
else if (binder.info.member(nme._1).exists && !isSeq) productElemsToN(binder, totalArity)
14471451
else ref(binder):: Nil
14481452
refs
14491453
}

src/dotty/tools/dotc/transform/TreeChecker.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dotty.tools.dotc
22
package transform
33

44
import TreeTransforms._
5+
import core.Names.Name
56
import core.DenotTransformers._
67
import core.Denotations._
78
import core.SymDenotations._
@@ -42,6 +43,12 @@ class TreeChecker extends Phase with SymTransformer {
4243
private val seenClasses = collection.mutable.HashMap[String, Symbol]()
4344
private val seenModuleVals = collection.mutable.HashMap[String, Symbol]()
4445

46+
def isValidJVMName(name: Name) =
47+
!name.exists(c => c == '.' || c == ';' || c =='[' || c == '/')
48+
49+
def isValidJVMMethodName(name: Name) =
50+
!name.exists(c => c == '.' || c == ';' || c =='[' || c == '/' || c == '<' || c == '>')
51+
4552
def printError(str: String)(implicit ctx: Context) = {
4653
ctx.println(Console.RED + "[error] " + Console.WHITE + str)
4754
}
@@ -130,6 +137,7 @@ class TreeChecker extends Phase with SymTransformer {
130137
def withDefinedSym[T](tree: untpd.Tree)(op: => T)(implicit ctx: Context): T = tree match {
131138
case tree: DefTree =>
132139
val sym = tree.symbol
140+
assert(isValidJVMName(sym.name), s"${sym.fullName} name is invalid on jvm")
133141
everDefinedSyms.get(sym) match {
134142
case Some(t) =>
135143
if (t ne tree)
@@ -257,12 +265,24 @@ class TreeChecker extends Phase with SymTransformer {
257265
assert(cls.primaryConstructor == constr.symbol, i"mismatch, primary constructor ${cls.primaryConstructor}, in tree = ${constr.symbol}")
258266
checkOwner(impl)
259267
checkOwner(impl.constr)
268+
269+
def isNonMagicalMethod(x: Symbol) =
270+
x.is(Method) &&
271+
!x.isCompanionMethod &&
272+
!x.isValueClassConvertMethod &&
273+
x != defn.newRefArrayMethod
274+
275+
val symbolsNotDefined = cls.classInfo.decls.toSet.filter(isNonMagicalMethod) -- impl.body.map(_.symbol) - constr.symbol
276+
277+
assert(symbolsNotDefined.isEmpty, i" $cls tree does not define methods: $symbolsNotDefined")
278+
260279
super.typedClassDef(cdef, cls)
261280
}
262281

263282
override def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context) =
264283
withDefinedSyms(ddef.tparams) {
265284
withDefinedSymss(ddef.vparamss) {
285+
if (!sym.isClassConstructor) assert(isValidJVMMethodName(sym.name), s"${sym.fullName} name is invalid on jvm")
266286
super.typedDefDef(ddef, sym)
267287
}
268288
}

test/dotc/tests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ class tests extends CompilerTest {
154154

155155
@Test def run_all = runFiles(runDir)
156156

157-
@Test def dotty = compileDir(dottyDir, "tools", "-deep" :: "-Ycheck-reentrant" :: allowDeepSubtypes ++ twice) // note the -deep argument
157+
@Test def dotty = compileDir(dottyDir, ".", "-deep" :: "-Ycheck-reentrant" :: allowDeepSubtypes) // note the -deep argument
158158

159159
@Test def dotc_ast = compileDir(dotcDir, "ast")
160160
@Test def dotc_config = compileDir(dotcDir, "config")

tests/pending/pos/i743.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
object NonLocalReturn {
2+
def foo(a: List[Int]): Int = {
3+
a.foreach(x => return x)
4+
0
5+
}
6+
}

tests/pending/run/StackMap.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
object Test {
2+
var implicitsCache = null
3+
4+
def main(args: Array[String]): Unit = {
5+
implicitsCache = try{null} catch { case ex: Exception => null }
6+
}
7+
}
File renamed without changes.
File renamed without changes.
File renamed without changes.

tests/pending/run/exceptions-2.check renamed to tests/run/exceptions-2.check

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
exceptions-2.scala:267: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
2-
try { 1 } catch { case e: java.io.IOException => () }
3-
^
41
nested1:
52
Innermost finally
63
Outermost finally
File renamed without changes.
File renamed without changes.
File renamed without changes.

tests/run/i744.check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1

tests/run/i744.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
trait A{
2+
private var s = 1
3+
def getS = s
4+
}
5+
6+
object Test extends A {
7+
def main(args: Array[String]): Unit = println(getS)
8+
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

tests/run/value-class-extractor.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ object NonNullChar {
66
@inline final val None = new NonNullChar(0.toChar)
77
}
88

9-
final class SomeProduct /*extends Product3[String, Int, List[String]]*/ {
9+
final class SomeProduct extends Product3[String, Int, List[String]] {
1010
def canEqual(x: Any) = x.isInstanceOf[SomeProduct]
1111
def _1 = "abc"
1212
def _2 = 5
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)