summaryrefslogtreecommitdiff
path: root/sources/scala/tools/nsc/typechecker
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-11-24 14:22:54 +0000
committerMartin Odersky <odersky@gmail.com>2005-11-24 14:22:54 +0000
commitd8e21c31629b27b6ec5f764d2d06da63fa7602be (patch)
tree938c8da2a2364c0bdac4a3ba78f0cc1d111cf491 /sources/scala/tools/nsc/typechecker
parenta47b13bd5f8687b6a415dc55257d01a5f1882f6a (diff)
downloadscala-d8e21c31629b27b6ec5f764d2d06da63fa7602be.tar.gz
scala-d8e21c31629b27b6ec5f764d2d06da63fa7602be.tar.bz2
scala-d8e21c31629b27b6ec5f764d2d06da63fa7602be.zip
*** empty log message ***
Diffstat (limited to 'sources/scala/tools/nsc/typechecker')
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Contexts.scala30
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Infer.scala4
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Namers.scala82
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Typers.scala55
4 files changed, 121 insertions, 50 deletions
diff --git a/sources/scala/tools/nsc/typechecker/Contexts.scala b/sources/scala/tools/nsc/typechecker/Contexts.scala
index d6608f3521..8035c227a0 100755
--- a/sources/scala/tools/nsc/typechecker/Contexts.scala
+++ b/sources/scala/tools/nsc/typechecker/Contexts.scala
@@ -85,7 +85,7 @@ import scala.tools.nsc.util.Position;
tree match {
case Template(_, _) | PackageDef(_, _) =>
c.enclClass = c;
- c.prefix = skolemizedThisType(this.prefix, c.owner)
+ c.prefix = skolemizedThisType(this.tree, this.prefix, c.owner)
case _ =>
c.enclClass = this.enclClass;
c.prefix = if (c.owner != this.owner && c.owner.isTerm) NoPrefix else this.prefix
@@ -129,13 +129,27 @@ import scala.tools.nsc.util.Position;
c
}
- def skolemizedThisType(pre: Type, clazz: Symbol): Type = if (settings.Xgadt.value) {
- val tparams = clazz.unsafeTypeParams;
- if (pre.isInstanceOf[SingleType] || !tparams.isEmpty) {
- val self = clazz.newThisSkolem
- setInfo clazz.typeOfThis.substSym(tparams, newTypeSkolems(tparams));
- singleType(pre, self)
- } else clazz.thisType
+ def constructorContext = {
+ val baseContext = enclClass.outer;
+ val argContext = baseContext.makeNewScope(tree, owner);
+ for (val sym <- scope.toList) argContext.scope enter sym;
+ argContext
+ }
+
+ def skolemizedThisType(encl: Tree, pre: Type, clazz: Symbol): Type = if (settings.Xgadt.value) {
+ encl match {
+ case ClassDef(_, _, tparamdefs, _, _) =>
+ System.out.println("sktt " + clazz);
+ if (!tparamdefs.isEmpty || pre.isInstanceOf[SingleType]) {
+ val tparams = clazz.unsafeTypeParams;
+ val tskolems = tparamdefs map (.symbol);
+ System.out.println("sktt2 " + tparams + " " + tskolems);
+ val self = clazz.newThisSkolem setInfo clazz.typeOfThis.substSym(tparams, tskolems);
+ singleType(pre, self)
+ } else clazz.thisType
+ case _ =>
+ clazz.thisType
+ }
} else clazz.thisType;
def error(pos: int, msg: String): unit =
diff --git a/sources/scala/tools/nsc/typechecker/Infer.scala b/sources/scala/tools/nsc/typechecker/Infer.scala
index e6568b20b5..e6c35e42d8 100755
--- a/sources/scala/tools/nsc/typechecker/Infer.scala
+++ b/sources/scala/tools/nsc/typechecker/Infer.scala
@@ -216,10 +216,6 @@ package scala.tools.nsc.typechecker;
def checkAccessible(tree: Tree, sym: Symbol, pre: Type, site: Tree): Tree =
if (sym.isError) {
tree setSymbol sym setType ErrorType
- } else if (sym.owner.hasFlag(INCONSTRUCTOR) &&
- !sym.isTypeParameterOrSkolem && !sym.isConstructor &&
- (site.isInstanceOf[This] || site.isInstanceOf[Super]) && !phase.erasedTypes) {
- errorTree(tree, "" + sym + " cannot be accessed from constructor");
} else {
val sym1 = sym filter (alt => context.isAccessible(alt, pre, site.isInstanceOf[Super]));
if (sym1 == NoSymbol) {
diff --git a/sources/scala/tools/nsc/typechecker/Namers.scala b/sources/scala/tools/nsc/typechecker/Namers.scala
index a836e0b0f6..ae41a3067b 100755
--- a/sources/scala/tools/nsc/typechecker/Namers.scala
+++ b/sources/scala/tools/nsc/typechecker/Namers.scala
@@ -28,6 +28,30 @@ trait Namers: Analyzer {
sym
}
+ /** Convert to corresponding type parameters all skolems which satisfy one of the
+ * following two conditions:
+ * 1. The skolem is a parameter of a class or alias type
+ * 2. The skolem is a method parameter which appears in parameter `tparams'
+ */
+ class DeSkolemizeMap(tparams: List[Symbol]) extends TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case TypeRef(pre, sym, args) =>
+ val tparam = sym.deSkolemize;
+ mapOver(
+ if (tparam == sym || !(tparams contains tparam)) tp
+ else rawTypeRef(NoPrefix, tparam, args))
+ case SingleType(pre, sym) if (sym.isThisSkolem) =>
+ ThisType(sym.deSkolemize)
+ case PolyType(tparams1, restpe) =>
+ new DeSkolemizeMap(tparams1 ::: tparams).mapOver(tp)
+ case ClassInfoType(parents, decls, clazz) =>
+ val parents1 = List.mapConserve(parents)(this);
+ if (parents1 eq parents) tp else ClassInfoType(parents1, decls, clazz);
+ case _ =>
+ mapOver(tp)
+ }
+ }
+
class Namer(val context: Context) {
private def isTemplateContext(context: Context): boolean = context.tree match {
@@ -112,6 +136,27 @@ trait Namers: Analyzer {
def enterSyms(trees: List[Tree]): Namer =
(this /: trees) ((namer, tree) => namer.enterSym(tree));
+ def newTypeSkolems(tparams: List[Symbol]): List[Symbol] = {
+ val tskolems = tparams map (.newTypeSkolem);
+ val ltp = new LazyType {
+ override def complete(sym: Symbol): unit =
+ sym setInfo sym.deSkolemize.info.substSym(tparams, tskolems);
+ }
+ tskolems foreach (.setInfo(ltp));
+ tskolems
+ }
+
+ def skolemize(tparams: List[AbsTypeDef]): unit = if (settings.Xgadt.value) {
+ val tskolems = newTypeSkolems(tparams map (.symbol));
+ for (val Pair(tparam, tskolem) <- tparams zip tskolems) tparam.symbol = tskolem
+ }
+
+ def applicableTypeParams(owner: Symbol): List[Symbol] =
+ if (owner.isTerm || owner.isPackageClass) List()
+ else applicableTypeParams(owner.owner) ::: owner.unsafeTypeParams;
+
+ def deSkolemize: TypeMap = new DeSkolemizeMap(applicableTypeParams(context.owner));
+
def enterSym(tree: Tree): Namer = {
def finishWith(tparams: List[AbsTypeDef]): unit = {
@@ -120,16 +165,12 @@ trait Namers: Analyzer {
if (!tparams.isEmpty) {
new Namer(context.makeNewScope(tree, tree.symbol)).enterSyms(tparams);
ltype = new LazyPolyType(tparams map (.symbol), ltype);
+ skolemize(tparams);
}
tree.symbol.setInfo(ltype);
}
def finish = finishWith(List());
- def skolemize(tparams: List[AbsTypeDef]): unit = {
- val tskolems = newTypeSkolems(tparams map (.symbol));
- for (val Pair(tparam, tskolem) <- tparams zip tskolems) tparam.symbol = tskolem
- }
-
if (tree.symbol == NoSymbol) {
val owner = context.owner;
tree match {
@@ -180,11 +221,9 @@ trait Namers: Analyzer {
tree.symbol = enterInScope(owner.newConstructor(tree.pos))
.setFlag(mods | owner.getFlag(ConstrFlags));
finishWith(tparams);
- skolemize(tparams);
case DefDef(mods, name, tparams, _, _, _) =>
tree.symbol = enterInScope(owner.newMethod(tree.pos, name)).setFlag(mods);
finishWith(tparams);
- skolemize(tparams);
case AbsTypeDef(mods, name, _, _) =>
tree.symbol = enterInScope(owner.newAbstractType(tree.pos, name)).setFlag(mods);
finish
@@ -211,7 +250,9 @@ trait Namers: Analyzer {
def typeCompleter(tree: Tree) = new TypeCompleter(tree) {
override def complete(sym: Symbol): unit = {
if (settings.debug.value) log("defining " + sym);
- sym.setInfo(typeSig(tree));
+ val tp = typeSig(tree);
+ sym.setInfo(tp);
+ if (settings.Xgadt.value) System.out.println("" + sym + ":" + tp);
if (settings.debug.value) log("defined " + sym);
validate(sym);
}
@@ -308,11 +349,10 @@ trait Namers: Analyzer {
if (!vparams.isEmpty && vparams.head.hasFlag(IMPLICIT)) ImplicitMethodType(formals, restpe)
else MethodType(formals, restpe);
}
- deSkolemize(
- makePolyType(
- tparamSyms,
- if (vparamSymss.isEmpty) PolyType(List(), restype)
- else (vparamSymss :\ restype)(mkMethodType)))
+ makePolyType(
+ tparamSyms,
+ if (vparamSymss.isEmpty) PolyType(List(), restype)
+ else (vparamSymss :\ restype)(mkMethodType))
}
/** If `sym' is an implicit value, check that its type signature `tp' is contractive.
@@ -354,7 +394,7 @@ trait Namers: Analyzer {
private def aliasTypeSig(tpsym: Symbol, tparams: List[AbsTypeDef], rhs: Tree): Type =
makePolyType(typer.reenterTypeParams(tparams), typer.typedType(rhs).tpe);
- private def typeSig(tree: Tree): Type =
+ private def typeSig(tree: Tree): Type = deSkolemize {
try {
val sym: Symbol = tree.symbol;
tree match {
@@ -368,10 +408,8 @@ trait Namers: Analyzer {
clazz.tpe;
case DefDef(_, _, tparams, vparamss, tpt, rhs) =>
- if (sym.isConstructor) sym.owner.setFlag(INCONSTRUCTOR);
val result =
new Namer(context.makeNewScope(tree, sym)).methodSig(tparams, vparamss, tpt, rhs);
- if (sym.isConstructor) sym.owner.resetFlag(INCONSTRUCTOR);
checkContractive(sym, result)
case ValDef(_, _, tpt, rhs) =>
@@ -383,7 +421,16 @@ trait Namers: Analyzer {
tpt.tpe = deconstIfNotFinal(sym, newTyper(context.make(tree, sym)).computeType(rhs));
tpt.tpe
}
- else typer.typedType(tpt).tpe
+ else {
+ val typer1 =
+ if (false && sym.hasFlag(PARAM) && sym.owner.isConstructor && !phase.erasedTypes) {
+ //todo: find out instead why Template contexts can be nested in Template contexts?
+ var c = context.enclClass;
+ while (c.tree.isInstanceOf[Template]) c = c.outer;
+ newTyper(c)
+ } else typer;
+ typer1.typedType(tpt).tpe
+ }
case AliasTypeDef(_, _, tparams, rhs) =>
new Namer(context.makeNewScope(tree, sym)).aliasTypeSig(sym, tparams, rhs)
@@ -416,6 +463,7 @@ trait Namers: Analyzer {
typer.reportTypeError(tree.pos, ex);
ErrorType
}
+ }
/** Check that symbol's definition is well-formed. This means:
* - no conflicting modifiers
diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala
index 267a9ca838..829ff3a0d9 100755
--- a/sources/scala/tools/nsc/typechecker/Typers.scala
+++ b/sources/scala/tools/nsc/typechecker/Typers.scala
@@ -488,7 +488,8 @@ import collection.mutable.HashMap;
}
if (!(selfType <:< parent.tpe.typeOfThis) && !phase.erasedTypes) {
System.out.println(context.owner);//debug
- System.out.println(context.owner.thisSym);//debug
+ System.out.println(context.owner.unsafeTypeParams);//debug
+ System.out.println(List.fromArray(context.owner.info.closure));//debug
error(parent.pos, "illegal inheritance;\n self-type " +
selfType + " does not conform to " + parent +
"'s selftype " + parent.tpe.typeOfThis);
@@ -564,6 +565,7 @@ import collection.mutable.HashMap;
val selfType =
if (clazz.isAnonymousClass && !phase.erasedTypes)
intersectionType(clazz.info.parents, clazz.owner)
+ else if (settings.Xgadt.value) clazz.typeOfThis.asSeenFrom(context.prefix, clazz)
else clazz.typeOfThis;
// the following is necessary for templates generated later
new Namer(context.outer.make(templ, clazz, clazz.info.decls)).enterSyms(templ.body);
@@ -574,7 +576,10 @@ import collection.mutable.HashMap;
def typedValDef(vdef: ValDef): ValDef = {
val sym = vdef.symbol;
- var tpt1 = checkNoEscaping.privates(sym, typedType(vdef.tpt));
+ val typer1 = if (sym.hasFlag(PARAM) && sym.owner.isConstructor)
+ newTyper(context.constructorContext)
+ else this;
+ var tpt1 = checkNoEscaping.privates(sym, typer1.typedType(vdef.tpt));
checkNonCyclic(vdef.pos, tpt1.tpe, sym);
val rhs1 =
if (vdef.rhs.isEmpty) {
@@ -638,6 +643,9 @@ import collection.mutable.HashMap;
}
}
+ def typedSuperCall(tree: Tree): Tree =
+ typed(tree, EXPRmode | INCONSTRmode, UnitClass.tpe);
+
def typedDefDef(ddef: DefDef): DefDef = {
val meth = ddef.symbol;
reenterTypeParams(ddef.tparams);
@@ -661,9 +669,16 @@ import collection.mutable.HashMap;
meth.owner.isAnonymousClass ||
meth.owner.isRefinementClass))
error(ddef.pos, "constructor definition not allowed here " + meth.owner);//debug
- context.enclClass.owner.setFlag(INCONSTRUCTOR);
- val result = typed(ddef.rhs, EXPRmode | INCONSTRmode, UnitClass.tpe);
- context.enclClass.owner.resetFlag(INCONSTRUCTOR);
+ val result = ddef.rhs match {
+ case Block(stat :: stats, expr) =>
+ val stat1 = typedSuperCall(stat);
+ typed(copy.Block(ddef.rhs, stats, expr), UnitClass.tpe) match {
+ case block1 @ Block(stats1, expr1) =>
+ copy.Block(block1, stat1 :: stats1, expr1)
+ }
+ case _ =>
+ typedSuperCall(ddef.rhs)
+ }
if (meth.isPrimaryConstructor && !phase.erasedTypes && reporter.errors() == 0)
computeParamAliases(meth.owner, vparamss1, result);
result
@@ -704,14 +719,7 @@ import collection.mutable.HashMap;
def typedBlock(block: Block, mode: int, pt: Type): Block = {
namer.enterSyms(block.stats);
block.stats foreach enterLabelDef;
- val stats1 =
- if ((mode & INCONSTRmode) != 0) {
- val constrCall = typed(block.stats.head, mode, WildcardType);
- context.enclClass.owner.resetFlag(INCONSTRUCTOR);
- constrCall :: typedStats(block.stats.tail, context.owner);
- } else {
- typedStats(block.stats, context.owner)
- }
+ val stats1 = typedStats(block.stats, context.owner);
val expr1 = typed(block.expr, mode & ~(FUNmode | QUALmode), pt);
val block1 = copy.Block(block, stats1, expr1)
setType (if (treeInfo.isPureExpr(block)) expr1.tpe else expr1.tpe.deconst);
@@ -827,10 +835,16 @@ import collection.mutable.HashMap;
errorTree(tree, treeSymTypeMsg(fun) + " does not take type parameters.");
}
+ def typedArg(arg: Tree, pt: Type): Tree = {
+ val argTyper = if ((mode & INCONSTRmode) != 0) newTyper(context.constructorContext)
+ else this;
+ argTyper.typed(arg, mode & stickyModes, pt)
+ }
+
def typedApply(fun: Tree, args: List[Tree]): Tree = fun.tpe match {
case OverloadedType(pre, alts) =>
val args1 = List.mapConserve(args)(arg =>
- typed(arg, mode & stickyModes, WildcardType));
+ typedArg(arg, WildcardType));
inferMethodAlternative(fun, context.undetparams, args1 map (.tpe.deconst), pt);
typedApply(adapt(fun, funmode, WildcardType), args1);
case MethodType(formals0, restpe) =>
@@ -842,8 +856,7 @@ import collection.mutable.HashMap;
val tparams = context.undetparams;
context.undetparams = List();
if (tparams.isEmpty) {
- val args1 = List.map2(args, formals) ((arg, formal) =>
- typed(arg, mode & stickyModes, formal));
+ val args1 = List.map2(args, formals)(typedArg);
def ifPatternSkipFormals(tp: Type) = tp match {
case MethodType(_, rtp) if ((mode & PATTERNmode) != 0) => rtp
case _ => tp
@@ -854,18 +867,18 @@ import collection.mutable.HashMap;
val lenientTargs = protoTypeArgs(tparams, formals, restpe, pt);
val strictTargs = List.map2(lenientTargs, tparams)((targ, tparam) =>
if (targ == WildcardType) tparam.tpe else targ);
- def typedArg(tree: Tree, formal: Type): Tree = {
+ def typedArgToPoly(arg: Tree, formal: Type): Tree = {
val lenientPt = formal.subst(tparams, lenientTargs);
- val tree1 = typed(tree, mode & stickyModes | POLYmode, lenientPt);
+ val arg1 = typedArg(arg, lenientPt);
val argtparams = context.undetparams;
context.undetparams = List();
if (!argtparams.isEmpty) {
val strictPt = formal.subst(tparams, strictTargs);
- inferArgumentInstance(tree1, argtparams, strictPt, lenientPt);
+ inferArgumentInstance(arg1, argtparams, strictPt, lenientPt);
}
- tree1
+ arg1
}
- val args1 = List.map2(args, formals)(typedArg);
+ val args1 = List.map2(args, formals)(typedArgToPoly);
if (args1 exists (.tpe.isError)) setError(tree)
else {
if (settings.debug.value) log("infer method inst " + fun + ", tparams = " + tparams + ", args = " + args1.map(.tpe) + ", pt = " + pt + ", lobounds = " + tparams.map(.tpe.bounds.lo));//debug