From 0f97e0f90df27d39a75b3142c72ad21d20fbdd2c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 7 Nov 2005 17:37:54 +0000 Subject: *** empty log message *** --- sources/scala/tools/nsc/symtab/Types.scala | 7 +-- sources/scala/tools/nsc/transform/Erasure.scala | 2 +- sources/scala/tools/nsc/typechecker/Contexts.scala | 21 +++++-- sources/scala/tools/nsc/typechecker/Infer.scala | 73 +++++++++++++++++----- sources/scala/tools/nsc/typechecker/Typers.scala | 3 +- 5 files changed, 79 insertions(+), 27 deletions(-) diff --git a/sources/scala/tools/nsc/symtab/Types.scala b/sources/scala/tools/nsc/symtab/Types.scala index a13b809660..d4df21fd0a 100755 --- a/sources/scala/tools/nsc/symtab/Types.scala +++ b/sources/scala/tools/nsc/symtab/Types.scala @@ -1472,10 +1472,9 @@ import Flags._; tps1.isEmpty && tps2.isEmpty || !tps1.isEmpty && !tps2.isEmpty && - (if (tparams.head.hasFlag(COVARIANT)) tps1.head <:< tps2.head - else if (tparams.head.hasFlag(CONTRAVARIANT)) tps2.head <:< tps1.head - else tps1.head =:= tps2.head) && - isSubArgs(tps1.tail, tps2.tail, tparams.tail) + (tparams.head.hasFlag(COVARIANT) || (tps2.head <:< tps1.head)) && + (tparams.head.hasFlag(CONTRAVARIANT) || tps1.head <:< tps2.head) && + isSubArgs(tps1.tail, tps2.tail, tparams.tail) } sym1 == sym2 && (pre1 <:< pre2) && isSubArgs(args1, args2, sym1.typeParams) diff --git a/sources/scala/tools/nsc/transform/Erasure.scala b/sources/scala/tools/nsc/transform/Erasure.scala index aa3f874d30..5d02e12e04 100755 --- a/sources/scala/tools/nsc/transform/Erasure.scala +++ b/sources/scala/tools/nsc/transform/Erasure.scala @@ -407,7 +407,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { val member = opc.overriding; val other = opc.overridden; //System.out.println("bridge? " + member + ":" + member.tpe + member.locationString + " to " + other + ":" + other.tpe + other.locationString);//DEBUG - if (!(member hasFlag DEFERRED)) { + if (!atPhase(phase.prev)(member hasFlag DEFERRED)) { val otpe = erasure(other.tpe); val bridgeNeeded = atPhase(phase.next) { !(other.tpe =:= member.tpe) && diff --git a/sources/scala/tools/nsc/typechecker/Contexts.scala b/sources/scala/tools/nsc/typechecker/Contexts.scala index 718b7655b8..7490fc00c6 100755 --- a/sources/scala/tools/nsc/typechecker/Contexts.scala +++ b/sources/scala/tools/nsc/typechecker/Contexts.scala @@ -62,13 +62,13 @@ import scala.tools.util.Position; private var _undetparams: List[Symbol] = List(); // Undetermined type parameters var depth: int = 0; var imports: List[ImportInfo] = List(); - var typeSubstFrom: List[Symbol] = List(); // The set of type parameters in scope. - var typeSubstTo: List[Type] = List(); // Types to which parameters are mapped. var reportAmbiguousErrors = false; var reportGeneralErrors = false; var checking = false; + var savedTypeBounds: List[Pair[Symbol, Type]] = List(); + def undetparams = _undetparams; def undetparams_=(ps: List[Symbol]) = { //System.out.println("undetparams = " + ps);//debug @@ -88,8 +88,6 @@ import scala.tools.util.Position; c.variance = this.variance; c.depth = if (scope == this.scope) this.depth else this.depth + 1; c.imports = imports; - c.typeSubstFrom = this.typeSubstFrom; - c.typeSubstTo = this.typeSubstTo; c.reportAmbiguousErrors = this.reportAmbiguousErrors; c.reportGeneralErrors = this.reportGeneralErrors; c.checking = this.checking; @@ -155,6 +153,9 @@ import scala.tools.util.Position; case _ => outer.isLocal() } + def nextEnclosing(p: Context => boolean): Context = + if (this == NoContext || p(this)) this else outer.nextEnclosing(p); + override def toString(): String = { if (this == NoContext) "NoContext"; else owner.toString() + " @ " + tree.getClass() + " " + tree.toString() + ", scope = " + scope.hashCode() + " " + scope.toList + "\n:: " + outer.toString() @@ -193,6 +194,18 @@ import scala.tools.util.Position; (pre.widen.symbol.isSubClass(sym.owner) && isSubClassOfEnclosing(pre.widen.symbol)))) } + def pushTypeBounds(sym: Symbol): unit = { + savedTypeBounds = Pair(sym, sym.info) :: savedTypeBounds + } + + def restoreTypeBounds: unit = { + for (val Pair(sym, info) <- savedTypeBounds) { + System.out.println("resetting " + sym + " to " + info); + sym.setInfo(info); + } + savedTypeBounds = List() + } + private var implicitsCache: List[List[ImplicitInfo]] = null; private var implicitsRun: CompilerRun = NoRun; diff --git a/sources/scala/tools/nsc/typechecker/Infer.scala b/sources/scala/tools/nsc/typechecker/Infer.scala index 173e43cb36..e010c600b5 100755 --- a/sources/scala/tools/nsc/typechecker/Infer.scala +++ b/sources/scala/tools/nsc/typechecker/Infer.scala @@ -77,6 +77,29 @@ package scala.tools.nsc.typechecker; List.map2(bounds, targs)((bound, targ) => bound containsType targ) forall (x => x) } + object freeTypeParams extends TypeTraverser { + private var result: List[Symbol] = _; + private def includeIfAbstract(sym: Symbol): unit = { + if (sym.isAbstractType && !result.contains(sym)) result = sym :: result; + } + override def traverse(tp: Type): TypeTraverser = { + tp match { + case TypeRef(NoPrefix, sym, _) => + includeIfAbstract(sym) + case TypeRef(ThisType(_), sym, _) => + includeIfAbstract(sym) + case _ => + } + mapOver(tp); + this + } + def collect(tp: Type): List[Symbol] = { + result = List(); + traverse(tp); + result + } + } + /** Solve constraint collected in types `tvars' * @param tvars All type variables to be instantiated. * @param tparams The type parameters corresponding to `tvars' @@ -486,27 +509,43 @@ package scala.tools.nsc.typechecker; " can be instantiated in more than one way to expected type " + pt + "\n --- because ---\n" + ex.getMessage()); } -/* - if (!restpe.subst(undetparams, tvars) <:< pt) { - map all unbound type params to AnyVal; - tvars = undetparams map freshVar; - if (restpe.subst(undetparams, tvars) <:< pt) { - computeArgs; - restpe = skipImplicit(tree.tpe.resultType); - map all unbound type params tparams1 to freshVars tvars1 - val targs1 = solve(tvars1, tparams1, ??, ??); - checkBounds(tparams1, targs1, "inferred"); - return Pair(tparams, targs) where different - } - } -*/ - if (restpe.subst(undetparams, tvars) <:< pt) { - computeArgs - } else { + def instError = { System.out.println("ici " + tree + " " + undetparams + " " + pt);//debug errorTree(tree, "constructor cannot be instantiated to expected type" + foundReqMsg(restpe, pt)) } + if (restpe.subst(undetparams, tvars) <:< pt) { + computeArgs + } else if (isFullyDefined(pt)) { + System.out.println("infer constr " + tree + ":" + restpe + ", pt = " + pt);//debug + val ptparams = freeTypeParams.collect(pt); + System.out.println("free type params = " + ptparams);//debug + val ptWithWildcards = pt.subst(ptparams, ptparams map (ptparam => WildcardType)); + tvars = undetparams map freshVar; + if (restpe.subst(undetparams, tvars) <:< ptWithWildcards) { + computeArgs; + restpe = skipImplicit(tree.tpe.resultType); + System.out.println("new tree = " + tree + ":" + restpe);//debug + val ptvars = ptparams map freshVar; + if (restpe <:< pt.subst(ptparams, ptvars)) { + for (val tvar <- ptvars) { + val tparam = tvar.origin.symbol; + val Pair(loBounds, hiBounds) = + if (tvar.constr.inst != NoType && isFullyDefined(tvar.constr.inst)) + Pair(List(tvar.constr.inst), List(tvar.constr.inst)) + else + Pair(tvar.constr.lobounds, tvar.constr.hibounds); + if (!loBounds.isEmpty || !hiBounds.isEmpty) { + context.nextEnclosing(.tree.isInstanceOf[CaseDef]).pushTypeBounds(tparam); + tparam setInfo TypeBounds( + lub(tparam.info.bounds.lo :: loBounds), + glb(tparam.info.bounds.hi :: hiBounds)); + System.out.println("new bounds of " + tparam + " = " + tparam.info);//debug + } + } + } else { System.out.println("no instance: "); instError } + } else { System.out.println("not a subtype " + restpe.subst(undetparams, tvars) + " of " + ptWithWildcards); instError } + } else { System.out.println("not fuly defined: " + pt); instError } } /* -- Overload Resolution ----------------------------------------------------------- */ diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala index 6a29c53241..8cddbef7fb 100755 --- a/sources/scala/tools/nsc/typechecker/Typers.scala +++ b/sources/scala/tools/nsc/typechecker/Typers.scala @@ -722,12 +722,13 @@ import collection.mutable.HashMap; val guard1: Tree = if (cdef.guard == EmptyTree) EmptyTree else typed(cdef.guard, BooleanClass.tpe); val body1: Tree = typed(cdef.body, pt); + context.restoreTypeBounds; copy.CaseDef(cdef, pat1, guard1, body1) setType body1.tpe } def typedCases(tree: Tree, cases: List[CaseDef], pattp: Type, pt: Type): List[CaseDef] = { List.mapConserve(cases)(cdef => - newTyper(context.makeNewScope(tree, context.owner)).typedCase(cdef, pattp, pt)) + newTyper(context.makeNewScope(cdef, context.owner)).typedCase(cdef, pattp, pt)) } def typedFunction(fun: Function, mode: int, pt: Type): Tree = { -- cgit v1.2.3