1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
/* NSC -- new Scala compiler
* Copyright 2005-2010 LAMP/EPFL
* @author Martin Odersky
*/
// $Id$
package scala.tools.nsc
package typechecker
import scala.tools.nsc.symtab.Flags._
import scala.tools.nsc.util.{Position, NoPosition}
abstract class TreeCheckers extends Analyzer {
import global._
val tpeOfTree = new scala.collection.mutable.HashMap[Tree, Type]
def checkTrees {
if (settings.verbose.value)
Console.println("[consistency check at the beginning of phase " + phase + "]")
for (unit <- currentRun.units) check(unit)
}
def check(unit: CompilationUnit) {
informProgress("checking "+unit)
val context = rootContext(unit)
context.checking = true
tpeOfTree.clear
val checker = new TreeChecker(context)
val unit0 = currentRun.currentUnit
currentRun.currentUnit = unit
checker.precheck.traverse(unit.body)
checker.typed(unit.body)
checker.postcheck.traverse(unit.body)
currentRun.advanceUnit
assert(currentRun.currentUnit == unit)
currentRun.currentUnit = unit0
}
override def newTyper(context: Context): Typer = new TreeChecker(context)
class TreeChecker(context0: Context) extends Typer(context0) {
import infer._
override def typed(tree: Tree, mode: Int, pt: Type): Tree = {
tree match {
case EmptyTree | TypeTree() =>
;
case _ =>
if (!tpeOfTree.contains(tree)) {
tpeOfTree.update(tree, tree.tpe)
tree.tpe = null
}
val newtree = super.typed(tree, mode, pt);
if ((newtree ne tree) && !newtree.isInstanceOf[Literal])
error(tree.pos, "trees differ\n old: " + tree + " [" + tree.getClass() +
"]\n new: " + newtree + " [" + newtree.getClass() + "]")
}
tree
}
object precheck extends Traverser {
override def traverse(tree: Tree) {
tree match {
case DefDef(_, _, _, _, _, _) =>
if (tree.symbol.hasFlag(ACCESSOR) &&
!tree.symbol.isDeferred &&
!tree.symbol.tpe.resultType.isInstanceOf[ConstantType]) {
assert(tree.symbol.accessed != NoSymbol, tree.symbol)
assert(tree.symbol.accessed.getter(tree.symbol.owner) == tree.symbol ||
tree.symbol.accessed.setter(tree.symbol.owner) == tree.symbol)
}
case ValDef(_, _, _, _) =>
if (tree.symbol.hasGetter) {
assert(tree.symbol.getter(tree.symbol.owner) != NoSymbol, tree.symbol)
}
case Apply(_, args) =>
assert(args forall (EmptyTree !=))
case Select(_, _) =>
assert(tree.symbol != NoSymbol, tree)
case This(_) =>
if (!(tree.symbol.isStatic && (tree.symbol hasFlag MODULE))) {
if (currentOwner.ownerChain takeWhile (_ != tree.symbol) exists (_ == NoSymbol)) {
error(tree.pos, "tree symbol "+tree.symbol+" does not point to enclosing class; tree = "+tree)
return
}
}
case _ =>
}
if (tree.pos == NoPosition && tree != EmptyTree) {
error(tree.pos, "tree without position: " + tree)
} else if ((tree.tpe eq null) && phase.id >= currentRun.typerPhase.id) {
error(tree.pos, "tree without type: " + tree)
} else if (tree.isDef && tree.symbol.owner != currentOwner) {
var owner = currentOwner
while (owner.isTerm && !owner.isMethod && tree.symbol.owner != owner)
owner = owner.owner;
if (tree.symbol.owner != owner) {
error(tree.pos, "" + tree.symbol + " has wrong owner: " + tree.symbol.owner +
tree.symbol.owner.locationString + ", should be: " +
currentOwner + currentOwner.locationString)
}
} else {
super.traverse(tree)
}
}
}
object postcheck extends Traverser {
override def traverse(tree: Tree) {
tree match {
case EmptyTree | TypeTree() =>
;
case _ =>
tpeOfTree.get(tree) match {
case Some(oldtpe) =>
if (!(oldtpe =:= tree.tpe))
error(tree.pos, "types differ\n old: " + oldtpe +
"\n new: " + tree.tpe + "\n tree: " + tree)
tree.tpe = oldtpe
super.traverse(tree)
case None =>
}
}
}
}
}
}
|