summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2012-08-20 01:45:43 +0100
committerGrzegorz Kossakowski <grzegorz.kossakowski@gmail.com>2012-08-20 08:10:56 +0100
commit27606f83c4fe394a9b9547c70574e8c6935bc1a3 (patch)
treee16fbe1bea3d9170ba6c2788e42cc62cf82bfdc3 /src/compiler
parent1a6a9b4c75c5a8835ab1ed42a9e0269cf4bc2fe7 (diff)
downloadscala-27606f83c4fe394a9b9547c70574e8c6935bc1a3.tar.gz
scala-27606f83c4fe394a9b9547c70574e8c6935bc1a3.tar.bz2
scala-27606f83c4fe394a9b9547c70574e8c6935bc1a3.zip
Splitting large methods into smaller ones.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala914
1 files changed, 482 insertions, 432 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 47e129206a..1b93992675 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -104,7 +104,8 @@ trait Typers extends Modes with Adaptations with Tags {
tp.isError || pt.isError ||
context0.implicitsEnabled && // this condition prevents chains of views
inferView(EmptyTree, tp, pt, false) != EmptyTree
- }}
+ }
+ }
/** Find implicit arguments and pass them to given tree.
*/
@@ -606,21 +607,23 @@ trait Typers extends Modes with Adaptations with Tags {
/** Is `sym` defined in package object of package `pkg`?
*/
- private def isInPackageObject(sym: Symbol, pkg: Symbol) =
- pkg.isPackageClass && {
- sym.alternatives forall { sym =>
- !sym.owner.isPackage && {
- sym.owner.isPackageObjectClass &&
+ private def isInPackageObject(sym: Symbol, pkg: Symbol) = {
+ def isInPkgObj(sym: Symbol) =
+ !sym.owner.isPackage && {
+ sym.owner.isPackageObjectClass &&
sym.owner.owner == pkg ||
pkg.isInitialized && {
// need to be careful here to not get a cyclic reference during bootstrap
val pkgobj = pkg.info.member(nme.PACKAGEkw)
pkgobj.isInitialized &&
- (pkgobj.info.member(sym.name).alternatives contains sym)
+ (pkgobj.info.member(sym.name).alternatives contains sym)
}
- }
}
+ pkg.isPackageClass && {
+ if (sym.isOverloaded) sym.alternatives forall isInPkgObj
+ else isInPkgObj(sym)
}
+ }
/** Post-process an identifier or selection node, performing the following:
* 1. Check that non-function pattern expressions are stable
@@ -1131,109 +1134,112 @@ trait Typers extends Modes with Adaptations with Tags {
} else if (tree.tpe <:< pt) {
tree
} else {
- if (inPatternMode(mode)) {
- if ((tree.symbol ne null) && tree.symbol.isModule)
- inferModulePattern(tree, pt)
- if (isPopulated(tree.tpe, approximateAbstracts(pt)))
- return tree
- }
- val tree1 = constfold(tree, pt) // (10) (11)
- if (tree1.tpe <:< pt) adapt(tree1, mode, pt, original)
- else {
- if (inExprModeButNot(mode, FUNmode)) {
- pt.normalize match {
- case TypeRef(_, sym, _) =>
- // note: was if (pt.typeSymbol == UnitClass) but this leads to a potentially
- // infinite expansion if pt is constant type ()
- if (sym == UnitClass && tree.tpe <:< AnyClass.tpe) { // (12)
- if (settings.warnValueDiscard.value)
- context.unit.warning(tree.pos, "discarded non-Unit value")
- return typed(atPos(tree.pos)(Block(List(tree), Literal(Constant()))), mode, pt)
- } else if (isNumericValueClass(sym) && isNumericSubType(tree.tpe, pt)) {
- if (settings.warnNumericWiden.value)
- context.unit.warning(tree.pos, "implicit numeric widening")
- return typed(atPos(tree.pos)(Select(tree, "to" + sym.name)), mode, pt)
- }
- case AnnotatedType(_, _, _) if canAdaptAnnotations(tree, mode, pt) => // (13)
- return typed(adaptAnnotations(tree, mode, pt), mode, pt)
- case _ =>
- }
- if (!context.undetparams.isEmpty) {
- return instantiate(tree, mode, pt)
- }
- if (context.implicitsEnabled && !pt.isError && !tree.isErrorTyped) {
- // (14); the condition prevents chains of views
- debuglog("inferring view from " + tree.tpe + " to " + pt)
- val coercion = inferView(tree, tree.tpe, pt, true)
- // convert forward views of delegate types into closures wrapped around
- // the delegate's apply method (the "Invoke" method, which was translated into apply)
- if (forMSIL && coercion != null && isCorrespondingDelegate(tree.tpe, pt)) {
- val meth: Symbol = tree.tpe.member(nme.apply)
- debuglog("replacing forward delegate view with: " + meth + ":" + meth.tpe)
- return typed(Select(tree, meth), mode, pt)
+ def fallBack: Tree = {
+ if (inPatternMode(mode)) {
+ if ((tree.symbol ne null) && tree.symbol.isModule)
+ inferModulePattern(tree, pt)
+ if (isPopulated(tree.tpe, approximateAbstracts(pt)))
+ return tree
+ }
+ val tree1 = constfold(tree, pt) // (10) (11)
+ if (tree1.tpe <:< pt) adapt(tree1, mode, pt, original)
+ else {
+ if (inExprModeButNot(mode, FUNmode)) {
+ pt.normalize match {
+ case TypeRef(_, sym, _) =>
+ // note: was if (pt.typeSymbol == UnitClass) but this leads to a potentially
+ // infinite expansion if pt is constant type ()
+ if (sym == UnitClass && tree.tpe <:< AnyClass.tpe) { // (12)
+ if (settings.warnValueDiscard.value)
+ context.unit.warning(tree.pos, "discarded non-Unit value")
+ return typed(atPos(tree.pos)(Block(List(tree), Literal(Constant()))), mode, pt)
+ } else if (isNumericValueClass(sym) && isNumericSubType(tree.tpe, pt)) {
+ if (settings.warnNumericWiden.value)
+ context.unit.warning(tree.pos, "implicit numeric widening")
+ return typed(atPos(tree.pos)(Select(tree, "to" + sym.name)), mode, pt)
+ }
+ case AnnotatedType(_, _, _) if canAdaptAnnotations(tree, mode, pt) => // (13)
+ return typed(adaptAnnotations(tree, mode, pt), mode, pt)
+ case _ =>
}
- if (coercion != EmptyTree) {
- def msg = "inferred view from " + tree.tpe + " to " + pt + " = " + coercion + ":" + coercion.tpe
- if (settings.logImplicitConv.value)
- unit.echo(tree.pos, msg)
-
- debuglog(msg)
- val silentContext = context.makeImplicit(context.ambiguousErrors)
- val res = newTyper(silentContext).typed(
- new ApplyImplicitView(coercion, List(tree)) setPos tree.pos, mode, pt)
- if (silentContext.hasErrors) context.issue(silentContext.errBuffer.head) else return res
+ if (!context.undetparams.isEmpty) {
+ return instantiate(tree, mode, pt)
+ }
+ if (context.implicitsEnabled && !pt.isError && !tree.isErrorTyped) {
+ // (14); the condition prevents chains of views
+ debuglog("inferring view from " + tree.tpe + " to " + pt)
+ val coercion = inferView(tree, tree.tpe, pt, true)
+ // convert forward views of delegate types into closures wrapped around
+ // the delegate's apply method (the "Invoke" method, which was translated into apply)
+ if (forMSIL && coercion != null && isCorrespondingDelegate(tree.tpe, pt)) {
+ val meth: Symbol = tree.tpe.member(nme.apply)
+ debuglog("replacing forward delegate view with: " + meth + ":" + meth.tpe)
+ return typed(Select(tree, meth), mode, pt)
+ }
+ if (coercion != EmptyTree) {
+ def msg = "inferred view from " + tree.tpe + " to " + pt + " = " + coercion + ":" + coercion.tpe
+ if (settings.logImplicitConv.value)
+ unit.echo(tree.pos, msg)
+
+ debuglog(msg)
+ val silentContext = context.makeImplicit(context.ambiguousErrors)
+ val res = newTyper(silentContext).typed(
+ new ApplyImplicitView(coercion, List(tree)) setPos tree.pos, mode, pt)
+ if (silentContext.hasErrors) context.issue(silentContext.errBuffer.head) else return res
+ }
}
}
- }
- if (settings.debug.value) {
- log("error tree = " + tree)
- if (settings.explaintypes.value) explainTypes(tree.tpe, pt)
- }
+ if (settings.debug.value) {
+ log("error tree = " + tree)
+ if (settings.explaintypes.value) explainTypes(tree.tpe, pt)
+ }
- val found = tree.tpe
- if (!found.isErroneous && !pt.isErroneous) {
- if (!context.reportErrors && isPastTyper) {
- val (bound, req) = pt match {
- case ExistentialType(qs, tpe) => (qs, tpe)
- case _ => (Nil, pt)
- }
- val boundOrSkolems = bound ++ pt.skolemsExceptMethodTypeParams
- if (boundOrSkolems.nonEmpty) {
- // Ignore type errors raised in later phases that are due to mismatching types with existential skolems
- // We have lift crashing in 2.9 with an adapt failure in the pattern matcher.
- // Here's my hypothsis why this happens. The pattern matcher defines a variable of type
- //
- // val x: T = expr
- //
- // where T is the type of expr, but T contains existential skolems ts.
- // In that case, this value definition does not typecheck.
- // The value definition
- //
- // val x: T forSome { ts } = expr
- //
- // would typecheck. Or one can simply leave out the type of the `val`:
- //
- // val x = expr
- //
- // SI-6029 shows another case where we also fail (in uncurry), but this time the expected
- // type is an existential type.
- //
- // The reason for both failures have to do with the way we (don't) transform
- // skolem types along with the trees that contain them. We'd need a
- // radically different approach to do it. But before investing a lot of time to
- // to do this (I have already sunk 3 full days with in the end futile attempts
- // to consistently transform skolems and fix 6029), I'd like to
- // investigate ways to avoid skolems completely.
- //
- log("recovering from existential or skolem type error in tree \n" + tree + "\nwith type " + tree.tpe + "\n expected type = " + pt + "\n context = " + context.tree)
- return adapt(tree, mode, deriveTypeWithWildcards(boundOrSkolems)(pt))
+ val found = tree.tpe
+ if (!found.isErroneous && !pt.isErroneous) {
+ if (!context.reportErrors && isPastTyper) {
+ val (bound, req) = pt match {
+ case ExistentialType(qs, tpe) => (qs, tpe)
+ case _ => (Nil, pt)
+ }
+ val boundOrSkolems = bound ++ pt.skolemsExceptMethodTypeParams
+ if (boundOrSkolems.nonEmpty) {
+ // Ignore type errors raised in later phases that are due to mismatching types with existential skolems
+ // We have lift crashing in 2.9 with an adapt failure in the pattern matcher.
+ // Here's my hypothsis why this happens. The pattern matcher defines a variable of type
+ //
+ // val x: T = expr
+ //
+ // where T is the type of expr, but T contains existential skolems ts.
+ // In that case, this value definition does not typecheck.
+ // The value definition
+ //
+ // val x: T forSome { ts } = expr
+ //
+ // would typecheck. Or one can simply leave out the type of the `val`:
+ //
+ // val x = expr
+ //
+ // SI-6029 shows another case where we also fail (in uncurry), but this time the expected
+ // type is an existential type.
+ //
+ // The reason for both failures have to do with the way we (don't) transform
+ // skolem types along with the trees that contain them. We'd need a
+ // radically different approach to do it. But before investing a lot of time to
+ // to do this (I have already sunk 3 full days with in the end futile attempts
+ // to consistently transform skolems and fix 6029), I'd like to
+ // investigate ways to avoid skolems completely.
+ //
+ log("recovering from existential or skolem type error in tree \n" + tree + "\nwith type " + tree.tpe + "\n expected type = " + pt + "\n context = " + context.tree)
+ return adapt(tree, mode, deriveTypeWithWildcards(boundOrSkolems)(pt))
+ }
}
+ // create an actual error
+ AdaptTypeError(tree, found, pt)
}
- // create an actual error
- AdaptTypeError(tree, found, pt)
+ setError(tree)
}
- setError(tree)
}
+ fallBack
}
}
}
@@ -2848,73 +2854,79 @@ trait Typers extends Modes with Adaptations with Tags {
def duplErrTree = setError(treeCopy.Apply(tree, fun0, args))
def duplErrorTree(err: AbsTypeError) = { issue(err); duplErrTree }
- var fun = fun0
- if (fun.hasSymbol && fun.symbol.isOverloaded) {
- // remove alternatives with wrong number of parameters without looking at types.
- // less expensive than including them in inferMethodAlternatvie (see below).
- def shapeType(arg: Tree): Type = arg match {
- case Function(vparams, body) =>
- functionType(vparams map (vparam => AnyClass.tpe), shapeType(body))
- case AssignOrNamedArg(Ident(name), rhs) =>
- NamedType(name, shapeType(rhs))
- case _ =>
- NothingClass.tpe
- }
- val argtypes = args map shapeType
- val pre = fun.symbol.tpe.prefix
-
- var sym = fun.symbol filter { alt =>
- // must use pt as expected type, not WildcardType (a tempting quick fix to #2665)
- // now fixed by using isWeaklyCompatible in exprTypeArgs
- // TODO: understand why exactly -- some types were not inferred anymore (`ant clean quick.bin` failed)
- // (I had expected inferMethodAlternative to pick up the slack introduced by using WildcardType here)
- //
- // @PP responds: I changed it to pass WildcardType instead of pt and only one line in
- // trunk (excluding scalacheck, which had another) failed to compile. It was this line in
- // Types: "refs = Array(Map(), Map())". I determined that inference fails if there are at
- // least two invariant type parameters. See the test case I checked in to help backstop:
- // pos/isApplicableSafe.scala.
- isApplicableSafe(context.undetparams, followApply(pre.memberType(alt)), argtypes, pt)
- }
- if (sym.isOverloaded) {
- val sym1 = sym filter (alt => {
- // eliminate functions that would result from tupling transforms
- // keeps alternatives with repeated params
- hasExactlyNumParams(followApply(alt.tpe), argtypes.length) ||
- // also keep alts which define at least one default
- alt.tpe.paramss.exists(_.exists(_.hasDefault))
- })
- if (sym1 != NoSymbol) sym = sym1
- }
- if (sym != NoSymbol)
- fun = adapt(fun setSymbol sym setType pre.memberType(sym), forFunMode(mode), WildcardType)
+ def preSelectOverloaded(fun: Tree): Tree = {
+ if (fun.hasSymbol && fun.symbol.isOverloaded) {
+ // remove alternatives with wrong number of parameters without looking at types.
+ // less expensive than including them in inferMethodAlternatvie (see below).
+ def shapeType(arg: Tree): Type = arg match {
+ case Function(vparams, body) =>
+ functionType(vparams map (vparam => AnyClass.tpe), shapeType(body))
+ case AssignOrNamedArg(Ident(name), rhs) =>
+ NamedType(name, shapeType(rhs))
+ case _ =>
+ NothingClass.tpe
+ }
+ val argtypes = args map shapeType
+ val pre = fun.symbol.tpe.prefix
+
+ var sym = fun.symbol filter { alt =>
+ // must use pt as expected type, not WildcardType (a tempting quick fix to #2665)
+ // now fixed by using isWeaklyCompatible in exprTypeArgs
+ // TODO: understand why exactly -- some types were not inferred anymore (`ant clean quick.bin` failed)
+ // (I had expected inferMethodAlternative to pick up the slack introduced by using WildcardType here)
+ //
+ // @PP responds: I changed it to pass WildcardType instead of pt and only one line in
+ // trunk (excluding scalacheck, which had another) failed to compile. It was this line in
+ // Types: "refs = Array(Map(), Map())". I determined that inference fails if there are at
+ // least two invariant type parameters. See the test case I checked in to help backstop:
+ // pos/isApplicableSafe.scala.
+ isApplicableSafe(context.undetparams, followApply(pre.memberType(alt)), argtypes, pt)
+ }
+ if (sym.isOverloaded) {
+ val sym1 = sym filter (alt => {
+ // eliminate functions that would result from tupling transforms
+ // keeps alternatives with repeated params
+ hasExactlyNumParams(followApply(alt.tpe), argtypes.length) ||
+ // also keep alts which define at least one default
+ alt.tpe.paramss.exists(_.exists(_.hasDefault))
+ })
+ if (sym1 != NoSymbol) sym = sym1
+ }
+ if (sym == NoSymbol) fun
+ else adapt(fun setSymbol sym setType pre.memberType(sym), forFunMode(mode), WildcardType)
+ } else fun
}
+ val fun = preSelectOverloaded(fun0)
+
fun.tpe match {
case OverloadedType(pre, alts) =>
- val undetparams = context.extractUndetparams()
-
- val argtpes = new ListBuffer[Type]
- val amode = forArgMode(fun, mode)
- val args1 = args map {
- case arg @ AssignOrNamedArg(Ident(name), rhs) =>
- // named args: only type the righthand sides ("unknown identifier" errors otherwise)
- val rhs1 = typedArg(rhs, amode, BYVALmode, WildcardType)
- argtpes += NamedType(name, rhs1.tpe.deconst)
- // the assign is untyped; that's ok because we call doTypedApply
- atPos(arg.pos) { new AssignOrNamedArg(arg.lhs , rhs1) }
- case arg =>
- val arg1 = typedArg(arg, amode, BYVALmode, WildcardType)
- argtpes += arg1.tpe.deconst
- arg1
- }
- context.undetparams = undetparams
- if (context.hasErrors)
- setError(tree)
- else {
- inferMethodAlternative(fun, undetparams, argtpes.toList, pt, varArgsOnly = treeInfo.isWildcardStarArgList(args))
- doTypedApply(tree, adapt(fun, forFunMode(mode), WildcardType), args1, mode, pt)
+ def handleOverloaded = {
+ val undetparams = context.extractUndetparams()
+
+ val argtpes = new ListBuffer[Type]
+ val amode = forArgMode(fun, mode)
+ val args1 = args map {
+ case arg @ AssignOrNamedArg(Ident(name), rhs) =>
+ // named args: only type the righthand sides ("unknown identifier" errors otherwise)
+ val rhs1 = typedArg(rhs, amode, BYVALmode, WildcardType)
+ argtpes += NamedType(name, rhs1.tpe.deconst)
+ // the assign is untyped; that's ok because we call doTypedApply
+ atPos(arg.pos) { new AssignOrNamedArg(arg.lhs, rhs1) }
+ case arg =>
+ val arg1 = typedArg(arg, amode, BYVALmode, WildcardType)
+ argtpes += arg1.tpe.deconst
+ arg1
+ }
+ context.undetparams = undetparams
+ if (context.hasErrors)
+ setError(tree)
+ else {
+ inferMethodAlternative(fun, undetparams, argtpes.toList, pt, varArgsOnly = treeInfo.isWildcardStarArgList(args))
+ doTypedApply(tree, adapt(fun, forFunMode(mode), WildcardType), args1, mode, pt)
+ }
}
+ handleOverloaded
case mt @ MethodType(params, _) =>
val paramTypes = mt.paramTypes
@@ -3035,101 +3047,107 @@ trait Typers extends Modes with Adaptations with Tags {
} else {
val tparams = context.extractUndetparams()
if (tparams.isEmpty) { // all type params are defined
- // In order for checkDead not to be misled by the unfortunate special
- // case of AnyRef#synchronized (which is implemented with signature T => T
- // but behaves as if it were (=> T) => T) we need to know what is the actual
- // target of a call. Since this information is no longer available from
- // typedArg, it is recorded here.
- checkDead.updateExpr(fun)
-
- val args1 =
- // no expected type when jumping to a match label -- anything goes (this is ok since we're typing the translation of well-typed code)
- // ... except during erasure: we must take the expected type into account as it drives the insertion of casts!
- // I've exhausted all other semi-clean approaches I could think of in balancing GADT magic, SI-6145, CPS type-driven transforms and other existential trickiness
- // (the right thing to do -- packing existential types -- runs into limitations in subtyping existential types,
- // casting breaks SI-6145,
- // not casting breaks GADT typing as it requires sneaking ill-typed trees past typer)
- if (!phase.erasedTypes && fun.symbol.isLabel && treeInfo.isSynthCaseSymbol(fun.symbol))
- typedArgs(args, forArgMode(fun, mode))
- else
- typedArgs(args, forArgMode(fun, mode), paramTypes, formals)
-
- // instantiate dependent method types, must preserve singleton types where possible (stableTypeFor) -- example use case:
- // val foo = "foo"; def precise(x: String)(y: x.type): x.type = {...}; val bar : foo.type = precise(foo)(foo)
- // precise(foo) : foo.type => foo.type
- val restpe = mt.resultType(args1 map (arg => gen.stableTypeFor(arg) getOrElse arg.tpe))
- def ifPatternSkipFormals(tp: Type) = tp match {
- case MethodType(_, rtp) if (inPatternMode(mode)) => rtp
- case _ => tp
- }
+ def handleMonomorphicCall: Tree = {
+ // In order for checkDead not to be misled by the unfortunate special
+ // case of AnyRef#synchronized (which is implemented with signature T => T
+ // but behaves as if it were (=> T) => T) we need to know what is the actual
+ // target of a call. Since this information is no longer available from
+ // typedArg, it is recorded here.
+ checkDead.updateExpr(fun)
+
+ val args1 =
+ // no expected type when jumping to a match label -- anything goes (this is ok since we're typing the translation of well-typed code)
+ // ... except during erasure: we must take the expected type into account as it drives the insertion of casts!
+ // I've exhausted all other semi-clean approaches I could think of in balancing GADT magic, SI-6145, CPS type-driven transforms and other existential trickiness
+ // (the right thing to do -- packing existential types -- runs into limitations in subtyping existential types,
+ // casting breaks SI-6145,
+ // not casting breaks GADT typing as it requires sneaking ill-typed trees past typer)
+ if (!phase.erasedTypes && fun.symbol.isLabel && treeInfo.isSynthCaseSymbol(fun.symbol))
+ typedArgs(args, forArgMode(fun, mode))
+ else
+ typedArgs(args, forArgMode(fun, mode), paramTypes, formals)
+
+ // instantiate dependent method types, must preserve singleton types where possible (stableTypeFor) -- example use case:
+ // val foo = "foo"; def precise(x: String)(y: x.type): x.type = {...}; val bar : foo.type = precise(foo)(foo)
+ // precise(foo) : foo.type => foo.type
+ val restpe = mt.resultType(args1 map (arg => gen.stableTypeFor(arg) getOrElse arg.tpe))
+ def ifPatternSkipFormals(tp: Type) = tp match {
+ case MethodType(_, rtp) if (inPatternMode(mode)) => rtp
+ case _ => tp
+ }
- // Replace the Delegate-Chainer methods += and -= with corresponding
- // + and - calls, which are translated in the code generator into
- // Combine and Remove
- if (forMSIL) {
- fun match {
- case Select(qual, name) =>
- if (isSubType(qual.tpe, DelegateClass.tpe)
- && (name == encode("+=") || name == encode("-=")))
- {
- val n = if (name == encode("+=")) nme.PLUS else nme.MINUS
- val f = Select(qual, n)
- // the compiler thinks, the PLUS method takes only one argument,
- // but he thinks it's an instance method -> still two ref's on the stack
- // -> translated by backend
- val rhs = treeCopy.Apply(tree, f, args)
- return typed(Assign(qual, rhs))
- }
- case _ => ()
+ // Replace the Delegate-Chainer methods += and -= with corresponding
+ // + and - calls, which are translated in the code generator into
+ // Combine and Remove
+ if (forMSIL) {
+ fun match {
+ case Select(qual, name) =>
+ if (isSubType(qual.tpe, DelegateClass.tpe)
+ && (name == encode("+=") || name == encode("-="))) {
+ val n = if (name == encode("+=")) nme.PLUS else nme.MINUS
+ val f = Select(qual, n)
+ // the compiler thinks, the PLUS method takes only one argument,
+ // but he thinks it's an instance method -> still two ref's on the stack
+ // -> translated by backend
+ val rhs = treeCopy.Apply(tree, f, args)
+ return typed(Assign(qual, rhs))
+ }
+ case _ => ()
+ }
}
- }
- /** This is translating uses of List() into Nil. This is less
- * than ideal from a consistency standpoint, but it shouldn't be
- * altered without due caution.
- * ... this also causes bootstrapping cycles if List_apply is
- * forced during kind-arity checking, so it is guarded by additional
- * tests to ensure we're sufficiently far along.
- */
- if (args.isEmpty && !forInteractive && fun.symbol.isInitialized && ListModule.hasCompleteInfo && (fun.symbol == List_apply))
- atPos(tree.pos)(gen.mkNil setType restpe)
- else
- constfold(treeCopy.Apply(tree, fun, args1) setType ifPatternSkipFormals(restpe))
+ /**
+ * This is translating uses of List() into Nil. This is less
+ * than ideal from a consistency standpoint, but it shouldn't be
+ * altered without due caution.
+ * ... this also causes bootstrapping cycles if List_apply is
+ * forced during kind-arity checking, so it is guarded by additional
+ * tests to ensure we're sufficiently far along.
+ */
+ if (args.isEmpty && !forInteractive && fun.symbol.isInitialized && ListModule.hasCompleteInfo && (fun.symbol == List_apply))
+ atPos(tree.pos)(gen.mkNil setType restpe)
+ else
+ constfold(treeCopy.Apply(tree, fun, args1) setType ifPatternSkipFormals(restpe))
+ }
+ handleMonomorphicCall
} else if (needsInstantiation(tparams, formals, args)) {
//println("needs inst "+fun+" "+tparams+"/"+(tparams map (_.info)))
inferExprInstance(fun, tparams)
doTypedApply(tree, fun, args, mode, pt)
} else {
- assert(!inPatternMode(mode), modeString(mode)) // this case cannot arise for patterns
- val lenientTargs = protoTypeArgs(tparams, formals, mt.resultApprox, pt)
- val strictTargs = map2(lenientTargs, tparams)((targ, tparam) =>
- if (targ == WildcardType) tparam.tpeHK else targ)
- var remainingParams = paramTypes
- def typedArgToPoly(arg: Tree, formal: Type): Tree = { //TR TODO: cleanup
- val lenientPt = formal.instantiateTypeParams(tparams, lenientTargs)
- val newmode =
- if (isByNameParamType(remainingParams.head)) POLYmode
- else POLYmode | BYVALmode
- if (remainingParams.tail.nonEmpty) remainingParams = remainingParams.tail
- val arg1 = typedArg(arg, forArgMode(fun, mode), newmode, lenientPt)
- val argtparams = context.extractUndetparams()
- if (!argtparams.isEmpty) {
- val strictPt = formal.instantiateTypeParams(tparams, strictTargs)
- inferArgumentInstance(arg1, argtparams, strictPt, lenientPt)
- arg1
- } else arg1
- }
- val args1 = map2(args, formals)(typedArgToPoly)
- if (args1 exists {_.isErrorTyped}) duplErrTree
- else {
- debuglog("infer method inst "+fun+", tparams = "+tparams+", args = "+args1.map(_.tpe)+", pt = "+pt+", lobounds = "+tparams.map(_.tpe.bounds.lo)+", parambounds = "+tparams.map(_.info)) //debug
- // define the undetparams which have been fixed by this param list, replace the corresponding symbols in "fun"
- // returns those undetparams which have not been instantiated.
- val undetparams = inferMethodInstance(fun, tparams, args1, pt)
- val result = doTypedApply(tree, fun, args1, mode, pt)
- context.undetparams = undetparams
- result
+ def handlePolymorphicCall = {
+ assert(!inPatternMode(mode), modeString(mode)) // this case cannot arise for patterns
+ val lenientTargs = protoTypeArgs(tparams, formals, mt.resultApprox, pt)
+ val strictTargs = map2(lenientTargs, tparams)((targ, tparam) =>
+ if (targ == WildcardType) tparam.tpeHK else targ)
+ var remainingParams = paramTypes
+ def typedArgToPoly(arg: Tree, formal: Type): Tree = { //TR TODO: cleanup
+ val lenientPt = formal.instantiateTypeParams(tparams, lenientTargs)
+ val newmode =
+ if (isByNameParamType(remainingParams.head)) POLYmode
+ else POLYmode | BYVALmode
+ if (remainingParams.tail.nonEmpty) remainingParams = remainingParams.tail
+ val arg1 = typedArg(arg, forArgMode(fun, mode), newmode, lenientPt)
+ val argtparams = context.extractUndetparams()
+ if (!argtparams.isEmpty) {
+ val strictPt = formal.instantiateTypeParams(tparams, strictTargs)
+ inferArgumentInstance(arg1, argtparams, strictPt, lenientPt)
+ arg1
+ } else arg1
+ }
+ val args1 = map2(args, formals)(typedArgToPoly)
+ if (args1 exists { _.isErrorTyped }) duplErrTree
+ else {
+ debuglog("infer method inst " + fun + ", tparams = " + tparams + ", args = " + args1.map(_.tpe) + ", pt = " + pt + ", lobounds = " + tparams.map(_.tpe.bounds.lo) + ", parambounds = " + tparams.map(_.info)) //debug
+ // define the undetparams which have been fixed by this param list, replace the corresponding symbols in "fun"
+ // returns those undetparams which have not been instantiated.
+ val undetparams = inferMethodInstance(fun, tparams, args1, pt)
+ val result = doTypedApply(tree, fun, args1, mode, pt)
+ context.undetparams = undetparams
+ result
+ }
}
+ handlePolymorphicCall
}
}
@@ -4461,41 +4479,43 @@ trait Typers extends Modes with Adaptations with Tags {
qual.tpe = tree.symbol.owner.tpe
if (!reallyExists(sym)) {
- if (context.owner.enclosingTopLevelClass.isJavaDefined && name.isTypeName) {
- val tree1 = atPos(tree.pos) { gen.convertToSelectFromType(qual, name) }
- if (tree1 != EmptyTree) return typed1(tree1, mode, pt)
- }
+ def handleMissing: Tree = {
+ if (context.owner.enclosingTopLevelClass.isJavaDefined && name.isTypeName) {
+ val tree1 = atPos(tree.pos) { gen.convertToSelectFromType(qual, name) }
+ if (tree1 != EmptyTree) return typed1(tree1, mode, pt)
+ }
- // try to expand according to Dynamic rules.
- asDynamicCall foreach (x => return x)
+ // try to expand according to Dynamic rules.
+ asDynamicCall foreach (x => return x)
- debuglog(
- "qual = "+qual+":"+qual.tpe+
- "\nSymbol="+qual.tpe.termSymbol+"\nsymbol-info = "+qual.tpe.termSymbol.info+
- "\nscope-id = "+qual.tpe.termSymbol.info.decls.hashCode()+"\nmembers = "+qual.tpe.members+
- "\nname = "+name+"\nfound = "+sym+"\nowner = "+context.enclClass.owner
- )
+ debuglog(
+ "qual = " + qual + ":" + qual.tpe +
+ "\nSymbol=" + qual.tpe.termSymbol + "\nsymbol-info = " + qual.tpe.termSymbol.info +
+ "\nscope-id = " + qual.tpe.termSymbol.info.decls.hashCode() + "\nmembers = " + qual.tpe.members +
+ "\nname = " + name + "\nfound = " + sym + "\nowner = " + context.enclClass.owner)
- def makeInteractiveErrorTree = {
- val tree1 = tree match {
- case Select(_, _) => treeCopy.Select(tree, qual, name)
- case SelectFromTypeTree(_, _) => treeCopy.SelectFromTypeTree(tree, qual, name)
+ def makeInteractiveErrorTree = {
+ val tree1 = tree match {
+ case Select(_, _) => treeCopy.Select(tree, qual, name)
+ case SelectFromTypeTree(_, _) => treeCopy.SelectFromTypeTree(tree, qual, name)
+ }
+ setError(tree1)
}
- setError(tree1)
- }
- if (name == nme.ERROR && forInteractive)
- return makeInteractiveErrorTree
+ if (name == nme.ERROR && forInteractive)
+ return makeInteractiveErrorTree
- if (!qual.tpe.widen.isErroneous) {
- if ((mode & QUALmode) != 0) {
- val lastTry = rootMirror.missingHook(qual.tpe.typeSymbol, name)
- if (lastTry != NoSymbol) return typed1(tree setSymbol lastTry, mode, pt)
+ if (!qual.tpe.widen.isErroneous) {
+ if ((mode & QUALmode) != 0) {
+ val lastTry = rootMirror.missingHook(qual.tpe.typeSymbol, name)
+ if (lastTry != NoSymbol) return typed1(tree setSymbol lastTry, mode, pt)
+ }
+ NotAMemberError(tree, qual, name)
}
- NotAMemberError(tree, qual, name)
- }
- if (forInteractive) makeInteractiveErrorTree else setError(tree)
+ if (forInteractive) makeInteractiveErrorTree else setError(tree)
+ }
+ handleMissing
} else {
val tree1 = tree match {
case Select(_, _) => treeCopy.Select(tree, qual, name)
@@ -4871,13 +4891,16 @@ trait Typers extends Modes with Adaptations with Tags {
//if (settings.debug.value && tree.isDef) log("typing definition of "+sym);//DEBUG
tree match {
case PackageDef(pid, stats) =>
- val pid1 = typedQualifier(pid).asInstanceOf[RefTree]
- assert(sym.moduleClass ne NoSymbol, sym)
- // complete lazy annotations
- val annots = sym.annotations
- val stats1 = newTyper(context.make(tree, sym.moduleClass, sym.info.decls))
- .typedStats(stats, NoSymbol)
- treeCopy.PackageDef(tree, pid1, stats1) setType NoType
+ def typedPackageDef = {
+ val pid1 = typedQualifier(pid).asInstanceOf[RefTree]
+ assert(sym.moduleClass ne NoSymbol, sym)
+ // complete lazy annotations
+ val annots = sym.annotations
+ val stats1 = newTyper(context.make(tree, sym.moduleClass, sym.info.decls))
+ .typedStats(stats, NoSymbol)
+ treeCopy.PackageDef(tree, pid1, stats1) setType NoType
+ }
+ typedPackageDef
case tree @ ClassDef(_, _, _, _) =>
newTyper(context.makeNewScope(tree, sym)).typedClassDef(tree)
@@ -4902,23 +4925,26 @@ trait Typers extends Modes with Adaptations with Tags {
labelTyper(ldef).typedLabelDef(ldef)
case ddef @ DocDef(comment, defn) =>
- if (forScaladoc && (sym ne null) && (sym ne NoSymbol)) {
- docComments(sym) = comment
- comment.defineVariables(sym)
- val typer1 = newTyper(context.makeNewScope(tree, context.owner))
- for (useCase <- comment.useCases) {
- typer1.silent(_.typedUseCase(useCase)) match {
- case SilentTypeError(err) =>
- unit.warning(useCase.pos, err.errMsg)
- case _ =>
- }
- for (useCaseSym <- useCase.defined) {
- if (sym.name != useCaseSym.name)
- unit.warning(useCase.pos, "@usecase " + useCaseSym.name.decode + " does not match commented symbol: " + sym.name.decode)
+ def typedDocDef = {
+ if (forScaladoc && (sym ne null) && (sym ne NoSymbol)) {
+ docComments(sym) = comment
+ comment.defineVariables(sym)
+ val typer1 = newTyper(context.makeNewScope(tree, context.owner))
+ for (useCase <- comment.useCases) {
+ typer1.silent(_.typedUseCase(useCase)) match {
+ case SilentTypeError(err) =>
+ unit.warning(useCase.pos, err.errMsg)
+ case _ =>
+ }
+ for (useCaseSym <- useCase.defined) {
+ if (sym.name != useCaseSym.name)
+ unit.warning(useCase.pos, "@usecase " + useCaseSym.name.decode + " does not match commented symbol: " + sym.name.decode)
+ }
}
}
+ typed(defn, mode, pt)
}
- typed(defn, mode, pt)
+ typedDocDef
case Annotated(constr, arg) =>
typedAnnotated(constr, typed(arg, mode, pt))
@@ -4941,11 +4967,13 @@ trait Typers extends Modes with Adaptations with Tags {
typedBind(name, body)
case UnApply(fun, args) =>
- val fun1 = typed(fun)
- val tpes = formalTypes(unapplyTypeList(fun.symbol, fun1.tpe, args.length), args.length)
- val args1 = map2(args, tpes)(typedPattern)
- treeCopy.UnApply(tree, fun1, args1) setType pt
-
+ def typedUnApply = {
+ val fun1 = typed(fun)
+ val tpes = formalTypes(unapplyTypeList(fun.symbol, fun1.tpe, args.length), args.length)
+ val args1 = map2(args, tpes)(typedPattern)
+ treeCopy.UnApply(tree, fun1, args1) setType pt
+ }
+ typedUnApply
case ArrayValue(elemtpt, elems) =>
typedArrayValue(elemtpt, elems)
@@ -4970,28 +4998,31 @@ trait Typers extends Modes with Adaptations with Tags {
typedReturn(expr)
case Try(block, catches, finalizer) =>
- var block1 = typed(block, pt)
- var catches1 = typedCases(catches, ThrowableClass.tpe, pt)
-
- for (cdef <- catches1 if cdef.guard.isEmpty) {
- def warn(name: Name) = context.warning(cdef.pat.pos, s"This catches all Throwables. If this is really intended, use `case ${name.decoded} : Throwable` to clear this warning.")
- def unbound(t: Tree) = t.symbol == null || t.symbol == NoSymbol
- cdef.pat match {
- case Bind(name, i@Ident(_)) if unbound(i) => warn(name)
- case i@Ident(name) if unbound(i) => warn(name)
- case _ =>
+ def typedTry = {
+ var block1 = typed(block, pt)
+ var catches1 = typedCases(catches, ThrowableClass.tpe, pt)
+
+ for (cdef <- catches1 if cdef.guard.isEmpty) {
+ def warn(name: Name) = context.warning(cdef.pat.pos, s"This catches all Throwables. If this is really intended, use `case ${name.decoded} : Throwable` to clear this warning.")
+ def unbound(t: Tree) = t.symbol == null || t.symbol == NoSymbol
+ cdef.pat match {
+ case Bind(name, i @ Ident(_)) if unbound(i) => warn(name)
+ case i @ Ident(name) if unbound(i) => warn(name)
+ case _ =>
+ }
}
- }
- val finalizer1 = if (finalizer.isEmpty) finalizer
- else typed(finalizer, UnitClass.tpe)
- val (owntype, needAdapt) = ptOrLub(block1.tpe :: (catches1 map tpeOfTree), pt)
- if (needAdapt) {
- block1 = adapt(block1, mode, owntype)
- catches1 = catches1 map (adaptCase(_, mode, owntype))
- }
+ val finalizer1 = if (finalizer.isEmpty) finalizer
+ else typed(finalizer, UnitClass.tpe)
+ val (owntype, needAdapt) = ptOrLub(block1.tpe :: (catches1 map tpeOfTree), pt)
+ if (needAdapt) {
+ block1 = adapt(block1, mode, owntype)
+ catches1 = catches1 map (adaptCase(_, mode, owntype))
+ }
- treeCopy.Try(tree, block1, catches1, finalizer1) setType owntype
+ treeCopy.Try(tree, block1, catches1, finalizer1) setType owntype
+ }
+ typedTry
case Throw(expr) =>
val expr1 = typed(expr, EXPRmode | BYVALmode, ThrowableClass.tpe)
@@ -5001,102 +5032,116 @@ trait Typers extends Modes with Adaptations with Tags {
typedNew(tpt)
case Typed(expr, Function(List(), EmptyTree)) =>
- // find out whether the programmer is trying to eta-expand a macro def
- // to do that we need to typecheck the tree first (we need a symbol of the eta-expandee)
- // that typecheck must not trigger macro expansions, so we explicitly prohibit them
- // Q: "but, " - you may ask - ", `typed1` doesn't call adapt, which does macro expansion, so why explicit check?"
- // A: solely for robustness reasons. this mechanism might change in the future, which might break unprotected code
- val expr1 = context.withMacrosDisabled(typed1(expr, mode, pt))
- expr1 match {
- case macroDef if macroDef.symbol != null && macroDef.symbol.isTermMacro && !macroDef.symbol.isErroneous =>
- MacroEtaError(expr1)
- case _ =>
- typedEta(checkDead(expr1))
+ def typedEta0 = {
+ // find out whether the programmer is trying to eta-expand a macro def
+ // to do that we need to typecheck the tree first (we need a symbol of the eta-expandee)
+ // that typecheck must not trigger macro expansions, so we explicitly prohibit them
+ // Q: "but, " - you may ask - ", `typed1` doesn't call adapt, which does macro expansion, so why explicit check?"
+ // A: solely for robustness reasons. this mechanism might change in the future, which might break unprotected code
+ val expr1 = context.withMacrosDisabled(typed1(expr, mode, pt))
+ expr1 match {
+ case macroDef if macroDef.symbol != null && macroDef.symbol.isTermMacro && !macroDef.symbol.isErroneous =>
+ MacroEtaError(expr1)
+ case _ =>
+ typedEta(checkDead(expr1))
+ }
}
+ typedEta0
- case Typed(expr0, tpt @ Ident(tpnme.WILDCARD_STAR)) =>
- val expr = typed(expr0, onlyStickyModes(mode), WildcardType)
- def subArrayType(pt: Type) =
- if (isPrimitiveValueClass(pt.typeSymbol) || !isFullyDefined(pt)) arrayType(pt)
- else {
- val tparam = context.owner freshExistential "" setInfo TypeBounds.upper(pt)
- newExistentialType(List(tparam), arrayType(tparam.tpe))
- }
+ case Typed(expr0, tpt @ Ident(tpnme.WILDCARD_STAR)) =>
+ def typedVarArg = {
+ val expr = typed(expr0, onlyStickyModes(mode), WildcardType)
+ def subArrayType(pt: Type) =
+ if (isPrimitiveValueClass(pt.typeSymbol) || !isFullyDefined(pt)) arrayType(pt)
+ else {
+ val tparam = context.owner freshExistential "" setInfo TypeBounds.upper(pt)
+ newExistentialType(List(tparam), arrayType(tparam.tpe))
+ }
- val (expr1, baseClass) = expr.tpe.typeSymbol match {
- case ArrayClass => (adapt(expr, onlyStickyModes(mode), subArrayType(pt)), ArrayClass)
- case _ => (adapt(expr, onlyStickyModes(mode), seqType(pt)), SeqClass)
- }
- expr1.tpe.baseType(baseClass) match {
- case TypeRef(_, _, List(elemtp)) =>
- treeCopy.Typed(tree, expr1, tpt setType elemtp) setType elemtp
- case _ =>
- setError(tree)
+ val (expr1, baseClass) = expr.tpe.typeSymbol match {
+ case ArrayClass => (adapt(expr, onlyStickyModes(mode), subArrayType(pt)), ArrayClass)
+ case _ => (adapt(expr, onlyStickyModes(mode), seqType(pt)), SeqClass)
+ }
+ expr1.tpe.baseType(baseClass) match {
+ case TypeRef(_, _, List(elemtp)) =>
+ treeCopy.Typed(tree, expr1, tpt setType elemtp) setType elemtp
+ case _ =>
+ setError(tree)
+ }
}
+ typedVarArg
case Typed(expr, tpt) =>
- val tptTyped = typedType(tpt, mode)
- val exprTyped = typed(expr, onlyStickyModes(mode), tptTyped.tpe.deconst)
- val treeTyped = treeCopy.Typed(tree, exprTyped, tptTyped)
+ def typedTyped0 = {
+ val tptTyped = typedType(tpt, mode)
+ val exprTyped = typed(expr, onlyStickyModes(mode), tptTyped.tpe.deconst)
+ val treeTyped = treeCopy.Typed(tree, exprTyped, tptTyped)
+
+ if (isPatternMode) {
+ val uncheckedTypeExtractor = extractorForUncheckedType(tpt.pos, tptTyped.tpe)
+
+ // make fully defined to avoid bounded wildcard types that may be in pt from calling dropExistential (SI-2038)
+ val ptDefined = if (isFullyDefined(pt)) pt else makeFullyDefined(pt)
+ val ownType = inferTypedPattern(tptTyped, tptTyped.tpe, ptDefined, canRemedy = uncheckedTypeExtractor.nonEmpty)
+ treeTyped setType ownType
+
+ uncheckedTypeExtractor match {
+ case None => treeTyped
+ case Some(extractor) => wrapClassTagUnapply(treeTyped, extractor, tptTyped.tpe)
+ }
+ } else
+ treeTyped setType tptTyped.tpe
+ }
+ typedTyped0
- if (isPatternMode) {
- val uncheckedTypeExtractor = extractorForUncheckedType(tpt.pos, tptTyped.tpe)
+ case TypeApply(fun, args) =>
+ def typedTypeApply0 = {
+ // @M: kind-arity checking is done here and in adapt, full kind-checking is in checkKindBounds (in Infer)
+ //@M! we must type fun in order to type the args, as that requires the kinds of fun's type parameters.
+ // However, args should apparently be done first, to save context.undetparams. Unfortunately, the args
+ // *really* have to be typed *after* fun. We escape from this classic Catch-22 by simply saving&restoring undetparams.
- // make fully defined to avoid bounded wildcard types that may be in pt from calling dropExistential (SI-2038)
- val ptDefined = if (isFullyDefined(pt)) pt else makeFullyDefined(pt)
- val ownType = inferTypedPattern(tptTyped, tptTyped.tpe, ptDefined, canRemedy = uncheckedTypeExtractor.nonEmpty)
- treeTyped setType ownType
+ // @M TODO: the compiler still bootstraps&all tests pass when this is commented out..
+ //val undets = context.undetparams
- uncheckedTypeExtractor match {
- case None => treeTyped
- case Some(extractor) => wrapClassTagUnapply(treeTyped, extractor, tptTyped.tpe)
- }
- } else
- treeTyped setType tptTyped.tpe
+ // @M: fun is typed in TAPPmode because it is being applied to its actual type parameters
+ val fun1 = typed(fun, forFunMode(mode) | TAPPmode, WildcardType)
+ val tparams = fun1.symbol.typeParams
- case TypeApply(fun, args) =>
- // @M: kind-arity checking is done here and in adapt, full kind-checking is in checkKindBounds (in Infer)
- //@M! we must type fun in order to type the args, as that requires the kinds of fun's type parameters.
- // However, args should apparently be done first, to save context.undetparams. Unfortunately, the args
- // *really* have to be typed *after* fun. We escape from this classic Catch-22 by simply saving&restoring undetparams.
-
- // @M TODO: the compiler still bootstraps&all tests pass when this is commented out..
- //val undets = context.undetparams
-
- // @M: fun is typed in TAPPmode because it is being applied to its actual type parameters
- val fun1 = typed(fun, forFunMode(mode) | TAPPmode, WildcardType)
- val tparams = fun1.symbol.typeParams
-
- //@M TODO: val undets_fun = context.undetparams ?
- // "do args first" (by restoring the context.undetparams) in order to maintain context.undetparams on the function side.
-
- // @M TODO: the compiler still bootstraps when this is commented out.. TODO: run tests
- //context.undetparams = undets
-
- // @M maybe the well-kindedness check should be done when checking the type arguments conform to the type parameters' bounds?
- val args1 = if (sameLength(args, tparams)) map2Conserve(args, tparams) {
- //@M! the polytype denotes the expected kind
- (arg, tparam) => typedHigherKindedType(arg, mode, GenPolyType(tparam.typeParams, AnyClass.tpe))
- } else {
- //@M this branch is correctly hit for an overloaded polymorphic type. It also has to handle erroneous cases.
- // Until the right alternative for an overloaded method is known, be very liberal,
- // typedTypeApply will find the right alternative and then do the same check as
- // in the then-branch above. (see pos/tcpoly_overloaded.scala)
- // this assert is too strict: be tolerant for errors like trait A { def foo[m[x], g]=error(""); def x[g] = foo[g/*ERR: missing argument type*/] }
- //assert(fun1.symbol.info.isInstanceOf[OverloadedType] || fun1.symbol.isError) //, (fun1.symbol,fun1.symbol.info,fun1.symbol.info.getClass,args,tparams))
- args mapConserve (typedHigherKindedType(_, mode))
- }
+ //@M TODO: val undets_fun = context.undetparams ?
+ // "do args first" (by restoring the context.undetparams) in order to maintain context.undetparams on the function side.
+
+ // @M TODO: the compiler still bootstraps when this is commented out.. TODO: run tests
+ //context.undetparams = undets
+
+ // @M maybe the well-kindedness check should be done when checking the type arguments conform to the type parameters' bounds?
+ val args1 = if (sameLength(args, tparams)) map2Conserve(args, tparams) {
+ //@M! the polytype denotes the expected kind
+ (arg, tparam) => typedHigherKindedType(arg, mode, GenPolyType(tparam.typeParams, AnyClass.tpe))
+ }
+ else {
+ //@M this branch is correctly hit for an overloaded polymorphic type. It also has to handle erroneous cases.
+ // Until the right alternative for an overloaded method is known, be very liberal,
+ // typedTypeApply will find the right alternative and then do the same check as
+ // in the then-branch above. (see pos/tcpoly_overloaded.scala)
+ // this assert is too strict: be tolerant for errors like trait A { def foo[m[x], g]=error(""); def x[g] = foo[g/*ERR: missing argument type*/] }
+ //assert(fun1.symbol.info.isInstanceOf[OverloadedType] || fun1.symbol.isError) //, (fun1.symbol,fun1.symbol.info,fun1.symbol.info.getClass,args,tparams))
+ args mapConserve (typedHigherKindedType(_, mode))
+ }
- //@M TODO: context.undetparams = undets_fun ?
- typedTypeApply(tree, mode, fun1, args1)
+ //@M TODO: context.undetparams = undets_fun ?
+ typedTypeApply(tree, mode, fun1, args1)
+ }
+ typedTypeApply0
case Apply(Block(stats, expr), args) =>
typed1(atPos(tree.pos)(Block(stats, Apply(expr, args) setPos tree.pos.makeTransparent)), mode, pt)
case Apply(fun, args) =>
- typedApply(fun, args) match {
- case Apply(Select(New(tpt), name), args)
- if (tpt.tpe != null &&
+ def typedApply0 = {
+ typedApply(fun, args) match {
+ case Apply(Select(New(tpt), name), args)
+ if (tpt.tpe != null &&
tpt.tpe.typeSymbol == ArrayClass &&
args.length == 1 &&
erasure.GenericArray.unapply(tpt.tpe).isDefined) => // !!! todo simplify by using extractor
@@ -5115,7 +5160,9 @@ trait Typers extends Modes with Adaptations with Tags {
TooManyArgumentListsForConstructor(tree)
case tree1 =>
tree1
+ }
}
+ typedApply0
case ApplyDynamic(qual, args) =>
assert(phase.erasedTypes)
@@ -5137,41 +5184,44 @@ trait Typers extends Modes with Adaptations with Tags {
typedSelect(qual1, nme.CONSTRUCTOR)
case Select(qual, name) =>
- Statistics.incCounter(typedSelectCount)
- var qual1 = checkDead(typedQualifier(qual, mode))
- if (name.isTypeName) qual1 = checkStable(qual1)
-
- val tree1 = // temporarily use `filter` and an alternative for `withFilter`
- if (name == nme.withFilter)
- silent(_ => typedSelect(qual1, name)) match {
- case SilentResultValue(result) =>
- result
- case _ =>
- silent(_ => typed1(Select(qual1, nme.filter) setPos tree.pos, mode, pt)) match {
- case SilentResultValue(result2) =>
- unit.deprecationWarning(
- tree.pos, "`withFilter' method does not yet exist on "+qual1.tpe.widen+
- ", using `filter' method instead")
- result2
- case SilentTypeError(err) =>
- WithFilterError(tree, err)
- }
- }
- else
- typedSelect(qual1, name)
+ def typedSelect0 = {
+ Statistics.incCounter(typedSelectCount)
+ var qual1 = checkDead(typedQualifier(qual, mode))
+ if (name.isTypeName) qual1 = checkStable(qual1)
+
+ val tree1 = // temporarily use `filter` and an alternative for `withFilter`
+ if (name == nme.withFilter)
+ silent(_ => typedSelect(qual1, name)) match {
+ case SilentResultValue(result) =>
+ result
+ case _ =>
+ silent(_ => typed1(Select(qual1, nme.filter) setPos tree.pos, mode, pt)) match {
+ case SilentResultValue(result2) =>
+ unit.deprecationWarning(
+ tree.pos, "`withFilter' method does not yet exist on " + qual1.tpe.widen +
+ ", using `filter' method instead")
+ result2
+ case SilentTypeError(err) =>
+ WithFilterError(tree, err)
+ }
+ }
+ else
+ typedSelect(qual1, name)
- if (tree.isInstanceOf[PostfixSelect])
- checkFeature(tree.pos, PostfixOpsFeature, name.decode)
- if (tree1.symbol != null && tree1.symbol.isOnlyRefinementMember)
- checkFeature(tree1.pos, ReflectiveCallsFeature, tree1.symbol.toString)
+ if (tree.isInstanceOf[PostfixSelect])
+ checkFeature(tree.pos, PostfixOpsFeature, name.decode)
+ if (tree1.symbol != null && tree1.symbol.isOnlyRefinementMember)
+ checkFeature(tree1.pos, ReflectiveCallsFeature, tree1.symbol.toString)
- if (qual1.hasSymbolWhich(_.isRootPackage)) treeCopy.Ident(tree1, name)
- else tree1
+ if (qual1.hasSymbolWhich(_.isRootPackage)) treeCopy.Ident(tree1, name)
+ else tree1
+ }
+ typedSelect0
case Ident(name) =>
Statistics.incCounter(typedIdentCount)
if ((name == nme.WILDCARD && (mode & (PATTERNmode | FUNmode)) == PATTERNmode) ||
- (name == tpnme.WILDCARD && (mode & TYPEmode) != 0))
+ (name == tpnme.WILDCARD && (mode & TYPEmode) != 0))
tree setType makeFullyDefined(pt)
else
typedIdent(name)