diff options
author | Martin Odersky <odersky@gmail.com> | 2005-11-24 14:22:54 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2005-11-24 14:22:54 +0000 |
commit | d8e21c31629b27b6ec5f764d2d06da63fa7602be (patch) | |
tree | 938c8da2a2364c0bdac4a3ba78f0cc1d111cf491 /sources/scala/tools/nsc/typechecker | |
parent | a47b13bd5f8687b6a415dc55257d01a5f1882f6a (diff) | |
download | scala-d8e21c31629b27b6ec5f764d2d06da63fa7602be.tar.gz scala-d8e21c31629b27b6ec5f764d2d06da63fa7602be.tar.bz2 scala-d8e21c31629b27b6ec5f764d2d06da63fa7602be.zip |
*** empty log message ***
Diffstat (limited to 'sources/scala/tools/nsc/typechecker')
-rwxr-xr-x | sources/scala/tools/nsc/typechecker/Contexts.scala | 30 | ||||
-rwxr-xr-x | sources/scala/tools/nsc/typechecker/Infer.scala | 4 | ||||
-rwxr-xr-x | sources/scala/tools/nsc/typechecker/Namers.scala | 82 | ||||
-rwxr-xr-x | sources/scala/tools/nsc/typechecker/Typers.scala | 55 |
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 |