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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
/* NSC -- new Scala compiler
* Copyright 2005-2007 LAMP/EPFL
* @author Martin Odersky
*/
// $Id$
package scala.tools.nsc.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 _ =>
try {
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() + "]")
} catch {
case ex: Throwable =>
Console.println("exception while typing "+tree)
throw ex
}
}
tree
}
object precheck extends Traverser {
override def traverse(tree: Tree) {
try {
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))) {
var o = currentOwner
while (o != tree.symbol) {
o = o.owner
if (o == 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)
}
} catch {
case ex: Throwable =>
if (settings.debug.value)
Console.println("exception when traversing " + tree);
throw(ex)
}
}
}
object postcheck extends Traverser {
override def traverse(tree: Tree) {
try {
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 =>
}
}
} catch {
case ex: Throwable =>
if (settings.debug.value)
Console.println("exception when traversing " + tree);
throw(ex)
}
}
}
}
}
|