diff options
author | Martin Odersky <odersky@gmail.com> | 2012-08-20 01:45:43 +0100 |
---|---|---|
committer | Grzegorz Kossakowski <grzegorz.kossakowski@gmail.com> | 2012-08-20 08:10:56 +0100 |
commit | 27606f83c4fe394a9b9547c70574e8c6935bc1a3 (patch) | |
tree | e16fbe1bea3d9170ba6c2788e42cc62cf82bfdc3 | |
parent | 1a6a9b4c75c5a8835ab1ed42a9e0269cf4bc2fe7 (diff) | |
download | scala-27606f83c4fe394a9b9547c70574e8c6935bc1a3.tar.gz scala-27606f83c4fe394a9b9547c70574e8c6935bc1a3.tar.bz2 scala-27606f83c4fe394a9b9547c70574e8c6935bc1a3.zip |
Splitting large methods into smaller ones.
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 914 |
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) |