summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2008-04-04 18:00:26 +0000
committerMartin Odersky <odersky@gmail.com>2008-04-04 18:00:26 +0000
commitf9a68fb01de1edd3fa620912bbe75897133cc81b (patch)
treeb75321225503a24060ce665cdbeb3e1c95d7eb09 /src/compiler/scala/tools/nsc
parent768d107385af8f700be33b22444e537091d7f0ef (diff)
downloadscala-f9a68fb01de1edd3fa620912bbe75897133cc81b.tar.gz
scala-f9a68fb01de1edd3fa620912bbe75897133cc81b.tar.bz2
scala-f9a68fb01de1edd3fa620912bbe75897133cc81b.zip
(1) more changes for dynamic cycle detection of...
(1) more changes for dynamic cycle detection of implicits 2) change (to wildcard scoping in types 3) suppress $tag generation for purely (abstract traits 4) increase stacksize for sabbus to 32m (otherwise (problems on Windows)
Diffstat (limited to 'src/compiler/scala/tools/nsc')
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala68
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala28
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala47
4 files changed, 84 insertions, 61 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 04334951ec..fd1db30e74 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -191,8 +191,11 @@ trait Parsers extends NewScanners with MarkupParsers {
val savedPlaceholderTypes = placeholderTypes
placeholderTypes = List()
var t = op
- if (!placeholderTypes.isEmpty) t = ExistentialTypeTree(t, placeholderTypes.reverse)
- placeholderTypes = savedPlaceholderTypes
+ if (!placeholderTypes.isEmpty && t.isInstanceOf[AppliedTypeTree]) {
+ t = ExistentialTypeTree(t, placeholderTypes.reverse)
+ placeholderTypes = List()
+ }
+ placeholderTypes = placeholderTypes ::: savedPlaceholderTypes
t
}
@@ -646,7 +649,7 @@ trait Parsers extends NewScanners with MarkupParsers {
/** TypedOpt ::= [`:' Type]
*/
def typedOpt(): Tree =
- if (inToken == COLON) { inNextToken; placeholderTypeBoundary(typ()) }
+ if (inToken == COLON) { inNextToken; typ() }
else TypeTree()
/** RequiresTypedOpt ::= [requires AnnotType]
@@ -654,7 +657,7 @@ trait Parsers extends NewScanners with MarkupParsers {
def requiresTypeOpt(): Tree =
if (inToken == REQUIRES) {
deprecationWarning(in.currentPos, "`requires T' has been deprecated; use `{ self: T => ...' instead")
- inNextToken; placeholderTypeBoundary(annotType(false))
+ inNextToken; annotType(false)
} else TypeTree()
/** Types ::= Type {`,' Type}
@@ -686,24 +689,26 @@ trait Parsers extends NewScanners with MarkupParsers {
* ExistentialClause ::= forSome `{' ExistentialDcl {semi ExistentialDcl}} `}'
* ExistentialDcl ::= type TypeDcl | val ValDcl
*/
- def typ(): Tree = {
+ def typ(): Tree = typ(false)
+
+ def typ(isPattern: Boolean): Tree = placeholderTypeBoundary {
val t =
if (inToken == LPAREN) {
val pos = inSkipToken
if (inToken == RPAREN) {
inNextToken
- atPos(accept(ARROW)) { makeFunctionTypeTree(List(), typ()) }
+ atPos(accept(ARROW)) { makeFunctionTypeTree(List(), typ(isPattern)) }
/* Not more used
} else if (inToken == ARROW) {
inNextToken
- val t0 = typ()
+ val t0 = typ(isPattern)
accept(RPAREN)
- atPos(accept(ARROW)) { makeByNameFunctionTypeTree(t0, typ()) }
+ atPos(accept(ARROW)) { makeByNameFunctionTypeTree(t0, typ(isPattern)) }
*/
} else {
- val ts = types(false, false, true)
+ val ts = types(isPattern, false, true)
accept(RPAREN)
- if (inToken == ARROW) atPos(inSkipToken) { makeFunctionTypeTree(ts, typ()) }
+ if (inToken == ARROW) atPos(inSkipToken) { makeFunctionTypeTree(ts, typ(isPattern)) }
else {
for (t <- ts) t match {
case AppliedTypeTree(Select(_, n), _)
@@ -711,15 +716,15 @@ trait Parsers extends NewScanners with MarkupParsers {
syntaxError(t.pos, "no by-name parameter type allowed here", false)
case _ =>
}
- infixTypeRest(pos, annotTypeRest(pos, false, makeTupleType(ts, true)), false, InfixMode.FirstOp)
+ infixTypeRest(pos, annotTypeRest(pos, isPattern, makeTupleType(ts, true)), false, InfixMode.FirstOp)
}
}
} else {
- infixType(false, InfixMode.FirstOp)
+ infixType(isPattern, InfixMode.FirstOp)
}
if (inToken == ARROW)
atPos(inSkipToken) {
- makeFunctionTypeTree(List(t), typ())
+ makeFunctionTypeTree(List(t), typ(isPattern))
}
else if (inToken == FORSOME)
atPos(inSkipToken) {
@@ -739,8 +744,9 @@ trait Parsers extends NewScanners with MarkupParsers {
/** InfixType ::= CompoundType {id [nl] CompoundType}
*/
- def infixType(isPattern: Boolean, mode: InfixMode.Value): Tree =
+ def infixType(isPattern: Boolean, mode: InfixMode.Value): Tree = placeholderTypeBoundary {
infixTypeRest(inCurrentPos, infixTypeFirst(isPattern), isPattern, mode)
+ }
def infixTypeFirst(isPattern: Boolean) =
if (inToken == LBRACE) scalaAnyRefConstr else annotType(isPattern)
@@ -790,7 +796,7 @@ trait Parsers extends NewScanners with MarkupParsers {
* | `(' Types [`,'] `)'
* | WildcardType
*/
- def annotType(isPattern: Boolean): Tree = {
+ def annotType(isPattern: Boolean): Tree = placeholderTypeBoundary {
val annots1 = annotations()
if (!annots1.isEmpty)
deprecationWarning(
@@ -864,7 +870,7 @@ trait Parsers extends NewScanners with MarkupParsers {
Bind(ident().toTypeName, EmptyTree)
}
else {
- typ()
+ typ(true)
}
} else if (isFuncArg) {
// copy-paste (with change) from def paramType
@@ -884,7 +890,7 @@ trait Parsers extends NewScanners with MarkupParsers {
} else t
}
} else if (isTypeApply) {
- placeholderTypeBoundary(typ())
+ typ()
} else {
typ()
}
@@ -1045,8 +1051,7 @@ trait Parsers extends NewScanners with MarkupParsers {
}
} else if (annots.isEmpty || isTypeIntro) {
t = atPos(pos) {
- val tpt = placeholderTypeBoundary(
- if (location != Local) compoundType(false) else typ())
+ val tpt = if (location != Local) compoundType(false) else typ()
if (isWildcard(t))
(placeholderParams: @unchecked) match {
case (vd @ ValDef(mods, name, _, _)) :: rest =>
@@ -1072,10 +1077,11 @@ trait Parsers extends NewScanners with MarkupParsers {
}
stripParens(t)
}
- if (!placeholderParams.isEmpty)
- if (isWildcard(res)) savedPlaceholderParams = placeholderParams ::: savedPlaceholderParams
- else res = atPos(res.pos){Function(placeholderParams.reverse, res)}
- placeholderParams = savedPlaceholderParams
+ if (!placeholderParams.isEmpty && !isWildcard(res)) {
+ res = atPos(res.pos){ Function(placeholderParams.reverse, res) }
+ placeholderParams = List()
+ }
+ placeholderParams = placeholderParams ::: savedPlaceholderParams
res
}
@@ -1356,7 +1362,7 @@ trait Parsers extends NewScanners with MarkupParsers {
val p = pattern2(seqOK)
p match {
case Ident(name) if (treeInfo.isVarPattern(p) && inToken == COLON) =>
- atPos(inSkipToken) { Typed(p, placeholderTypeBoundary(compoundType(true))) }
+ atPos(inSkipToken) { Typed(p, compoundType(true)) }
case _ =>
p
}
@@ -1746,10 +1752,10 @@ trait Parsers extends NewScanners with MarkupParsers {
if (inToken == ARROW)
atPos(inSkipToken) {
AppliedTypeTree(
- scalaDot(nme.BYNAME_PARAM_CLASS_NAME.toTypeName), List(placeholderTypeBoundary(typ())))
+ scalaDot(nme.BYNAME_PARAM_CLASS_NAME.toTypeName), List(typ()))
}
else {
- val t = placeholderTypeBoundary(typ())
+ val t = typ()
if (isIdent && inName == STAR) {
inNextToken
atPos(t.pos) {
@@ -1789,7 +1795,7 @@ trait Parsers extends NewScanners with MarkupParsers {
val param = atPos(pos) { TypeDef(mods, pname, tparams, typeBounds()) }
if (inToken == VIEWBOUND && (implicitViewBuf ne null))
implicitViewBuf += atPos(inSkipToken) {
- makeFunctionTypeTree(List(Ident(pname)), placeholderTypeBoundary(typ()))
+ makeFunctionTypeTree(List(Ident(pname)), typ())
}
param
}
@@ -1815,7 +1821,7 @@ trait Parsers extends NewScanners with MarkupParsers {
bound(SUBTYPE, nme.Any))
def bound(tok: Int, default: Name): Tree =
- if (inToken == tok) { inNextToken; placeholderTypeBoundary(typ()) }
+ if (inToken == tok) { inNextToken; typ() }
else scalaDot(default.toTypeName)
//////// DEFS ////////////////////////////////////////////////////////////////
@@ -2125,7 +2131,7 @@ trait Parsers extends NewScanners with MarkupParsers {
inToken match {
case EQUALS =>
inNextToken
- TypeDef(mods, name, tparams, placeholderTypeBoundary(typ()))
+ TypeDef(mods, name, tparams, typ())
case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | NEWLINES | COMMA | RBRACE =>
TypeDef(mods | Flags.DEFERRED, name, tparams, typeBounds())
case _ =>
@@ -2222,14 +2228,14 @@ trait Parsers extends NewScanners with MarkupParsers {
* TraitParents ::= AnnotType {with AnnotType}
*/
def templateParents(isTrait: Boolean): (List[Tree], List[List[Tree]]) = {
- val parents = new ListBuffer[Tree] + placeholderTypeBoundary(annotType(false))
+ val parents = new ListBuffer[Tree] + annotType(false)
val argss = new ListBuffer[List[Tree]]
if (inToken == LPAREN && !isTrait)
do { argss += argumentExprs() } while (inToken == LPAREN)
else argss += List()
while (inToken == WITH) {
inNextToken
- parents += placeholderTypeBoundary(annotType(false))
+ parents += annotType(false)
}
(parents.toList, argss.toList)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 1f0750d580..758a006e0e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -97,8 +97,9 @@ trait Contexts { self: Analyzer =>
private var _undetparams: List[Symbol] = List() // Undetermined type parameters,
// not inherited to child contexts
var depth: Int = 0
- var imports: List[ImportInfo] = List()
-
+ var imports: List[ImportInfo] = List() // currently visible imports
+ var openImplicits: List[Type] = List() // types for which implicit arguments
+ // are currently searched
var prefix: Type = NoPrefix
var inConstructorSuffix = false // are we in a secondary constructor
// after the this constructor call?
@@ -130,6 +131,7 @@ trait Contexts { self: Analyzer =>
txt._undetparams = _undetparams
txt.depth = depth
txt.imports = imports
+ txt.openImplicits = openImplicits
txt.prefix = prefix
txt.inConstructorSuffix = inConstructorSuffix
txt.returnsSeen = returnsSeen
@@ -169,15 +171,16 @@ trait Contexts { self: Analyzer =>
val a8 = eq(depth, that.depth)
val a9 = eq(imports, that.imports)
- val a10 = eq(prefix, that.prefix)
- val a11 = eq(inConstructorSuffix, that.inConstructorSuffix)
- val a12 = eq(implicitsEnabled, that.implicitsEnabled)
- val a13 = eq(checking, that.checking)
- val a14 = eq(retyping, that.retyping)
- val a15 = eq(savedTypeBounds, that.savedTypeBounds)
- val a16 = eq(unit, that.unit)
- val ret = a0 && a1 && a2 && a3 && a4 && a5 && a6 && a7 && a8 && a9 && a10 && a11 && a12 && a13 && a14 && a15 && a16
- val a17 = {
+ val a10 = eq(openImplicits, that.openImplicits)
+ val a11 = eq(prefix, that.prefix)
+ val a12 = eq(inConstructorSuffix, that.inConstructorSuffix)
+ val a13 = eq(implicitsEnabled, that.implicitsEnabled)
+ val a14 = eq(checking, that.checking)
+ val a15 = eq(retyping, that.retyping)
+ val a16 = eq(savedTypeBounds, that.savedTypeBounds)
+ val a17 = eq(unit, that.unit)
+ val ret = a0 && a1 && a2 && a3 && a4 && a5 && a6 && a7 && a8 && a9 && a10 && a11 && a12 && a13 && a14 && a15 && a16 && a17
+ val a18 = {
if (implicitsRunId > that.implicitsRunId) {
that.implicitsRunId = NoRunId
that.implicitsCache = null
@@ -189,7 +192,7 @@ trait Contexts { self: Analyzer =>
implicitsCache == that.implicitsCache
}
if (ret) {
- if (!a17) {
+ if (!a18) {
//assert(this.implicitsCache == null || that.implicitsCache == null)
}
}
@@ -252,6 +255,7 @@ trait Contexts { self: Analyzer =>
c.implicitsEnabled = this.implicitsEnabled
c.checking = this.checking
c.retyping = this.retyping
+ c.openImplicits = this.openImplicits
c
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index e3a4ae897d..89b4b85cb0 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -265,7 +265,7 @@ trait SyntheticMethods { self: Analyzer =>
stat.symbol.resetFlag(CASEACCESSOR)
}
}
- if (!inIDE && clazz.info.nonPrivateDecl(nme.tag) == NoSymbol) ts += tagMethod
+ if (!inIDE && !clazz.hasFlag(INTERFACE) && clazz.info.nonPrivateDecl(nme.tag) == NoSymbol) ts += tagMethod
}
if (clazz.isModuleClass) {
if (!hasOverridingImplementation(Object_toString)) ts += moduleToStringMethod
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index c34212cd8d..12e0e63960 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -134,7 +134,7 @@ trait Typers { self: Analyzer =>
private def argMode(fun: Tree, mode: Int) =
if (treeInfo.isSelfOrSuperConstrCall(fun)) mode | SCCmode else mode
- private var pendingImplicits: List[Type] = List()
+ private val DivergentImplicit = new Exception()
abstract class Typer(context0: Context) {
import context0.unit
@@ -3297,26 +3297,28 @@ trait Typers { self: Analyzer =>
}
private def dominates(dtor: Type, dted: Type): Boolean = {
- def simplify(tp: Type): Type = tp match {
- case RefinedType(parents, defs) => intersectionType(parents, tp.typeSymbol.owner)
- case AnnotatedType(attribs, tp, selfsym) => tp
+ def core(tp: Type): Type = tp.normalize match {
+ case RefinedType(parents, defs) => intersectionType(parents map core, tp.typeSymbol.owner)
+ case AnnotatedType(attribs, tp, selfsym) => core(tp)
+ case ExistentialType(tparams, result) => core(result).subst(tparams, tparams map (t => core(t.info.bounds.hi)))
+ case PolyType(tparams, result) => core(result).subst(tparams, tparams map (t => core(t.info.bounds.hi)))
case _ => tp
}
def sum(xs: List[Int]) = (0 /: xs)(_ + _)
def complexity(tp: Type): Int = tp match {
case SingleType(pre, sym) => complexity(pre) + 1
case TypeRef(pre, sym, args) => complexity(pre) + sum(args map complexity) + 1
- case TypeBounds(lo, hi) => complexity(lo) + complexity(hi)
- case ClassInfoType(parents, defs, clazz) => sum(parents map complexity) + 1
- case MethodType(paramtypes, result) => sum(paramtypes map complexity) + complexity(result) + 1
- case PolyType(tparams, result) => sum(tparams map (_.info) map complexity) + complexity(result) + 1
- case ExistentialType(tparams, result) => sum(tparams map (_.info) map complexity) + complexity(result) + 1
+ case RefinedType(parents, _) => sum(parents map complexity) + 1
case _ => 1
}
- val dtor1 = simplify(dtor)
- val dted1 = simplify(dted)
- (dtor1.typeSymbol == dted1.typeSymbol) &&
- (dtor1 =:= dted1 || complexity(dtor1) > complexity(dted1))
+ def overlaps(tp1: Type, tp2: Type): Boolean = (tp1, tp2) match {
+ case (RefinedType(parents, _), _) => parents exists (overlaps(_, tp2))
+ case (_, RefinedType(parents, _)) => parents exists (overlaps(tp1, _))
+ case _ => tp1.typeSymbol == tp2.typeSymbol
+ }
+ val dtor1 = core(dtor)
+ val dted1 = core(dted)
+ overlaps(dtor1, dted1) && (dtor1 =:= dted1 || complexity(dtor1) > complexity(dted1))
}
/** Try to construct a typed tree from given implicit info with given
@@ -3332,16 +3334,27 @@ trait Typers { self: Analyzer =>
* @pre <code>info.tpe</code> does not contain an error
*/
private def typedImplicit(pos: Position, info: ImplicitInfo, pt0: Type, pt: Type, isLocal: Boolean): Tree =
- pendingImplicits find (dominates(pt, _)) match {
+ context.openImplicits find (dominates(pt, _)) match {
case Some(pending) =>
- context.error(pos, "diverging implicit expansion for type "+pending)
+ throw DivergentImplicit
EmptyTree
case None =>
try {
- pendingImplicits = pt :: pendingImplicits
+ context.openImplicits = pt :: context.openImplicits
typedImplicit0(pos, info, pt0, pt, isLocal)
+ } catch {
+ case DivergentImplicit =>
+ if (context.openImplicits.tail.isEmpty) {
+ if (!(pt.isErroneous))
+ context.unit.error(
+ pos, "diverging implicit expansion for type "+pt+"\nstarting with "+
+ info.sym+info.sym.locationString)
+ EmptyTree
+ } else {
+ throw DivergentImplicit
+ }
} finally {
- pendingImplicits = pendingImplicits.tail
+ context.openImplicits = context.openImplicits.tail
}
}