diff options
Diffstat (limited to 'src')
22 files changed, 130 insertions, 67 deletions
diff --git a/src/dotty/tools/dotc/Driver.scala b/src/dotty/tools/dotc/Driver.scala index 7e9d4a5e4..3b382da58 100644 --- a/src/dotty/tools/dotc/Driver.scala +++ b/src/dotty/tools/dotc/Driver.scala @@ -12,7 +12,7 @@ abstract class Driver extends DotClass { protected def newCompiler(): Compiler - protected def emptyReporter: Reporter = new StoreReporter + protected def emptyReporter: Reporter = new StoreReporter(null) protected def doCompile(compiler: Compiler, fileNames: List[String])(implicit ctx: Context): Reporter = if (fileNames.nonEmpty) @@ -24,7 +24,7 @@ abstract class Driver extends DotClass { catch { case ex: FatalError => ctx.error(ex.getMessage) // signals that we should fail compilation. - ctx.typerState.reporter + ctx.reporter } else emptyReporter @@ -44,8 +44,14 @@ abstract class Driver extends DotClass { doCompile(newCompiler(), fileNames)(ctx) } + // We overload `process` instead of using a default argument so that we + // can easily call this method using reflection from `RawCompiler` in sbt. + def process(args: Array[String]): Reporter = { + process(args, initCtx) + } + def main(args: Array[String]): Unit = - sys.exit(if (process(args, initCtx).hasErrors) 1 else 0) + sys.exit(if (process(args).hasErrors) 1 else 0) } class FatalError(msg: String) extends Exception diff --git a/src/dotty/tools/dotc/Resident.scala b/src/dotty/tools/dotc/Resident.scala index 9578e7d2c..3ae369f27 100644 --- a/src/dotty/tools/dotc/Resident.scala +++ b/src/dotty/tools/dotc/Resident.scala @@ -47,7 +47,7 @@ class Resident extends Driver { nextCtx = rootCtx line = getLine() } - if (line.startsWith(quit)) ctx.typerState.reporter + if (line.startsWith(quit)) ctx.reporter else loop(line split "\\s+", nextCtx) } loop(args, rootCtx) diff --git a/src/dotty/tools/dotc/Run.scala b/src/dotty/tools/dotc/Run.scala index 553805d95..ba86e3e70 100644 --- a/src/dotty/tools/dotc/Run.scala +++ b/src/dotty/tools/dotc/Run.scala @@ -50,6 +50,7 @@ class Run(comp: Compiler)(implicit ctx: Context) { } protected def compileUnits() = Stats.monitorHeartBeat { + ctx.checkSingleThreaded() val phases = ctx.squashPhases(ctx.phasePlan, ctx.settings.Yskip.value, ctx.settings.YstopBefore.value, ctx.settings.YstopAfter.value, ctx.settings.Ycheck.value) ctx.usePhases(phases) @@ -84,7 +85,7 @@ class Run(comp: Compiler)(implicit ctx: Context) { /** Print summary; return # of errors encountered */ def printSummary(): Reporter = { ctx.runInfo.printMaxConstraint() - val r = ctx.typerState.reporter + val r = ctx.reporter r.printSummary r } diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala index d1f101283..1ef883bf2 100644 --- a/src/dotty/tools/dotc/ast/Desugar.scala +++ b/src/dotty/tools/dotc/ast/Desugar.scala @@ -556,14 +556,20 @@ object desugar { DefDef(nme.ANON_FUN, Nil, params :: Nil, tpt, body).withMods(synthetic), Closure(Nil, Ident(nme.ANON_FUN), EmptyTree)) - /** Expand partial function + /** If `nparams` == 1, expand partial function + * * { cases } * ==> - * x$0 => x$0 match { cases } + * x$1 => x$1 match { cases } + * + * If `nparams` != 1, expand instead to + * + * (x$1, ..., x$n) => (x$0, ..., x${n-1}) match { cases } */ - def makeCaseLambda(cases: List[CaseDef])(implicit ctx: Context) = { - val param = makeSyntheticParameter() - Function(param :: Nil, Match(Ident(param.name), cases)) + def makeCaseLambda(cases: List[CaseDef], nparams: Int = 1)(implicit ctx: Context) = { + val params = (1 to nparams).toList.map(makeSyntheticParameter(_)) + val selector = makeTuple(params.map(p => Ident(p.name))) + Function(params, Match(selector, cases)) } /** Add annotation with class `cls` to tree: diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala index a10dfaa16..54ace3be4 100644 --- a/src/dotty/tools/dotc/ast/Trees.scala +++ b/src/dotty/tools/dotc/ast/Trees.scala @@ -146,7 +146,7 @@ object Trees { * type. (Overridden by empty trees) */ def withType(tpe: Type)(implicit ctx: Context): ThisTree[Type] = { - if (tpe == ErrorType) assert(ctx.errorsReported) + if (tpe == ErrorType) assert(ctx.reporter.errorsReported) withTypeUnchecked(tpe) } diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index f9d64b2cc..d5fdba1af 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -611,6 +611,16 @@ object Contexts { superIdOfClass.clear() lastSuperId = -1 } + + // Test that access is single threaded + + /** The thread on which `checkSingleThreaded was invoked last */ + @sharable private var thread: Thread = null + + /** Check that we are on the same thread as before */ + def checkSingleThreaded() = + if (thread == null) thread = Thread.currentThread() + else assert(thread == Thread.currentThread(), "illegal multithreaded access to ContextBase") } object Context { diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index bd03cc056..65df55a9d 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -193,9 +193,11 @@ object Denotations { */ def requiredSymbol(p: Symbol => Boolean, source: AbstractFile = null, generateStubs: Boolean = true)(implicit ctx: Context): Symbol = disambiguate(p) match { - case MissingRef(ownerd, name) => - if (generateStubs) + case m @ MissingRef(ownerd, name) => + if (generateStubs) { + m.ex.printStackTrace() ctx.newStubSymbol(ownerd.symbol, name, source) + } else NoSymbol case NoDenotation | _: NoQualifyingRef => throw new TypeError(s"None of the alternatives of $this satisfies required predicate") @@ -858,7 +860,9 @@ object Denotations { /** An error denotation that provides more info about the missing reference. * Produced by staticRef, consumed by requiredSymbol. */ - case class MissingRef(val owner: SingleDenotation, name: Name)(implicit ctx: Context) extends ErrorDenotation + case class MissingRef(val owner: SingleDenotation, name: Name)(implicit ctx: Context) extends ErrorDenotation { + val ex: Exception = new Exception + } /** An error denotation that provides more info about alternatives * that were found but that do not qualify. diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index f2a4c9e1e..684e9cbfd 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -123,7 +123,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { pendingSubTypes = new mutable.HashSet[(Type, Type)] ctx.log(s"!!! deep subtype recursion involving ${tp1.show} <:< ${tp2.show}, constraint = ${state.constraint.show}") ctx.log(s"!!! constraint = ${constraint.show}") - assert(!ctx.settings.YnoDeepSubtypes.value) + if (ctx.settings.YnoDeepSubtypes.value) throw new Error("deep subtype") if (Config.traceDeepSubTypeRecursions && !this.isInstanceOf[ExplainingTypeComparer]) ctx.log(TypeComparer.explained(implicit ctx => ctx.typeComparer.isSubType(tp1, tp2))) } @@ -197,8 +197,10 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { val cls1 = tp1.cls cls1.classInfo.selfType.derivesFrom(cls2) && cls2.classInfo.selfType.derivesFrom(cls1) - case tp1: TermRef if tp2.cls eq tp1.symbol.moduleClass => - isSubType(tp1.prefix, cls2.owner.thisType) + case tp1: TermRef if cls2.is(Module) && cls2.eq(tp1.widen.typeSymbol) => + cls2.isStaticOwner || + isSubType(tp1.prefix, cls2.owner.thisType) || + secondTry(tp1, tp2) case _ => secondTry(tp1, tp2) } @@ -257,9 +259,12 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { } comparePolyParam case tp1: ThisType => + val cls1 = tp1.cls tp2 match { - case tp2: TermRef if tp1.cls eq tp2.symbol.moduleClass => - isSubType(tp1.cls.owner.thisType, tp2.prefix) + case tp2: TermRef if cls1.is(Module) && cls1.eq(tp2.widen.typeSymbol) => + cls1.isStaticOwner || + isSubType(cls1.owner.thisType, tp2.prefix) || + thirdTry(tp1, tp2) case _ => thirdTry(tp1, tp2) } @@ -779,8 +784,24 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { else { val t2 = mergeIfSub(tp2, tp1) if (t2.exists) t2 - else andType(tp1, tp2) - } + else tp1 match { + case tp1: ConstantType => + tp2 match { + case tp2: ConstantType => + // Make use of the fact that the intersection of two constant types + // types which are not subtypes of each other is known to be empty. + // Note: The same does not apply to singleton types in general. + // E.g. we could have a pattern match against `x.type & y.type` + // which might succeed if `x` and `y` happen to be the same ref + // at run time. It would not work to replace that with `Nothing`. + // However, maybe we can still apply the replacement to + // types which are not explicitly written. + defn.NothingType + case _ => andType(tp1, tp2) + } + case _ => andType(tp1, tp2) + } + } } } } diff --git a/src/dotty/tools/dotc/core/TyperState.scala b/src/dotty/tools/dotc/core/TyperState.scala index 5617f568a..36f026107 100644 --- a/src/dotty/tools/dotc/core/TyperState.scala +++ b/src/dotty/tools/dotc/core/TyperState.scala @@ -98,7 +98,7 @@ extends TyperState(r) { override def fresh(isCommittable: Boolean): TyperState = - new MutableTyperState(this, new StoreReporter, isCommittable) + new MutableTyperState(this, new StoreReporter(reporter), isCommittable) override def withReporter(reporter: Reporter) = new MutableTyperState(this, reporter, isCommittable) @@ -169,7 +169,7 @@ extends TyperState(r) { * found a better solution. */ override def tryWithFallback[T](op: => T)(fallback: => T)(implicit ctx: Context): T = { - val storeReporter = new StoreReporter + val storeReporter = new StoreReporter(myReporter) val savedReporter = myReporter myReporter = storeReporter val savedConstraint = myConstraint diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index c7df3c400..cdb733efa 100644 --- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -405,6 +405,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas // println(owner.info.decls.toList.map(_.debugString).mkString("\n ")) // !!! DEBUG // } // (5) Create a stub symbol to defer hard failure a little longer. + new Exception().printStackTrace() ctx.newStubSymbol(owner, name, source) } } diff --git a/src/dotty/tools/dotc/parsing/JavaParsers.scala b/src/dotty/tools/dotc/parsing/JavaParsers.scala index 297f3c0f9..7b9d29ce3 100644 --- a/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -356,7 +356,7 @@ object JavaParsers { // assumed true unless we see public/private/protected var isPackageAccess = true var annots: List[Tree] = Nil - def addAnnot(sym: ClassSymbol) = annots :+= New(TypeTree(sym.typeRef)) + def addAnnot(sym: ClassSymbol) = annots :+= New(TypeTree(sym.typeRef)).withPos(Position(in.offset)) while (true) { in.token match { diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index 4b22eac95..caa15c7ff 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -322,6 +322,7 @@ object Parsers { case Ident(name1) => placeholderParams.nonEmpty && name1 == placeholderParams.head.name case Typed(t1, _) => isWildcard(t1) case Annotated(t1, _) => isWildcard(t1) + case Parens(t1) => isWildcard(t1) case _ => false } diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala index a46665ec0..d50b551fa 100644 --- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -45,8 +45,10 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { override def nameString(name: Name): String = name.decode.toString - override protected def simpleNameString(sym: Symbol): String = - sym.name.decode.toString + override protected def simpleNameString(sym: Symbol): String = { + val name = sym.originalName + nameString(if (sym is ExpandedTypeParam) name.asTypeName.unexpandedName else name) + } override protected def fullNameOwner(sym: Symbol) = { val owner = super.fullNameOwner(sym) @@ -86,10 +88,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { else { val tsym = tp.parent.member(tp.refinedName).symbol if (!tsym.exists) super.refinementNameString(tp) - else { - val name = tsym.originalName - nameString(if (tsym is ExpandedTypeParam) name.asTypeName.unexpandedName else name) - } + else simpleNameString(tsym) } override def toText(tp: Type): Text = controlled { diff --git a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala index 26e6324eb..3e2aaa880 100644 --- a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala +++ b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala @@ -40,8 +40,9 @@ class ConsoleReporter( } } - override def doReport(d: Diagnostic)(implicit ctx: Context): Unit = - if (!d.isSuppressed || !hasErrors) d match { + override def doReport(d: Diagnostic)(implicit ctx: Context): Boolean = { + val issue = !(d.isSuppressed && hasErrors) + if (issue) d match { case d: Error => printMessageAndPos(s"error: ${d.msg}", d.pos) if (ctx.settings.prompt.value) displayPrompt() @@ -51,6 +52,8 @@ class ConsoleReporter( case _ => printMessageAndPos(d.msg, d.pos) } + issue + } def displayPrompt(): Unit = { writer.print("\na)bort, s)tack, r)esume: ") diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala index 086575fb4..0358f71f6 100644 --- a/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/src/dotty/tools/dotc/reporting/Reporter.scala @@ -173,8 +173,6 @@ trait Reporting { this: Context => throw ex } } - - def errorsReported: Boolean = outersIterator exists (_.reporter.hasErrors) } /** @@ -183,8 +181,10 @@ trait Reporting { this: Context => */ abstract class Reporter { - /** Report a diagnostic */ - def doReport(d: Diagnostic)(implicit ctx: Context): Unit + /** Report a diagnostic, unless it is suppressed because it is nonsensical + * @return a diagnostic was reported. + */ + def doReport(d: Diagnostic)(implicit ctx: Context): Boolean /** Whether very long lines can be truncated. This exists so important * debugging information (like printing the classpath) is not rendered @@ -213,20 +213,24 @@ abstract class Reporter { def hasErrors = errorCount > 0 def hasWarnings = warningCount > 0 + /** Have errors been reported by this reporter, or in the + * case where this is a StoreReporter, by an outer reporter? + */ + def errorsReported = hasErrors + val unreportedWarnings = new mutable.HashMap[String, Int] { override def default(key: String) = 0 } - def report(d: Diagnostic)(implicit ctx: Context): Unit = if (!isHidden(d)) { - doReport(d)(ctx.addMode(Mode.Printing)) - d match { - case d: ConditionalWarning if !d.enablingOption.value => unreportedWarnings(d.enablingOption.name) += 1 - case d: Warning => warningCount += 1 - case d: Error => errorCount += 1 - case d: Info => // nothing to do here - // match error if d is something else - } - } + def report(d: Diagnostic)(implicit ctx: Context): Unit = + if (!isHidden(d) && doReport(d)(ctx.addMode(Mode.Printing))) + d match { + case d: ConditionalWarning if !d.enablingOption.value => unreportedWarnings(d.enablingOption.name) += 1 + case d: Warning => warningCount += 1 + case d: Error => errorCount += 1 + case d: Info => // nothing to do here + // match error if d is something else + } def incomplete(d: Diagnostic)(implicit ctx: Context): Unit = incompleteHandler(d)(ctx) diff --git a/src/dotty/tools/dotc/reporting/StoreReporter.scala b/src/dotty/tools/dotc/reporting/StoreReporter.scala index 51d3df110..8209839eb 100644 --- a/src/dotty/tools/dotc/reporting/StoreReporter.scala +++ b/src/dotty/tools/dotc/reporting/StoreReporter.scala @@ -10,14 +10,15 @@ import config.Printers._ /** * This class implements a Reporter that stores all messages */ -class StoreReporter extends Reporter { +class StoreReporter(outer: Reporter) extends Reporter { private var infos: mutable.ListBuffer[Diagnostic] = null - def doReport(d: Diagnostic)(implicit ctx: Context): Unit = { + def doReport(d: Diagnostic)(implicit ctx: Context): Boolean = { typr.println(s">>>> StoredError: ${d.msg}") // !!! DEBUG if (infos == null) infos = new mutable.ListBuffer infos += d + true } override def hasPending: Boolean = infos != null && { @@ -33,4 +34,6 @@ class StoreReporter extends Reporter { infos foreach ctx.reporter.report infos = null } + + override def errorsReported = hasErrors || outer.errorsReported } diff --git a/src/dotty/tools/dotc/reporting/ThrowingReporter.scala b/src/dotty/tools/dotc/reporting/ThrowingReporter.scala index 026453036..7c63383e9 100644 --- a/src/dotty/tools/dotc/reporting/ThrowingReporter.scala +++ b/src/dotty/tools/dotc/reporting/ThrowingReporter.scala @@ -11,7 +11,7 @@ import Reporter._ * info to the underlying reporter. */ class ThrowingReporter(reportInfo: Reporter) extends Reporter { - def doReport(d: Diagnostic)(implicit ctx: Context): Unit = d match { + def doReport(d: Diagnostic)(implicit ctx: Context): Boolean = d match { case _: Error => throw d case _ => reportInfo.doReport(d) } diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala index 2296ae658..1f47b4486 100644 --- a/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -118,7 +118,7 @@ class TreeChecker extends Phase with SymTransformer { val squahsedPhase = ctx.squashed(prevPhase) ctx.println(s"checking ${ctx.compilationUnit} after phase ${squahsedPhase}") val checkingCtx = ctx.fresh - .setTyperState(ctx.typerState.withReporter(new ThrowingReporter(ctx.typerState.reporter))) + .setTyperState(ctx.typerState.withReporter(new ThrowingReporter(ctx.reporter))) val checker = new Checker(previousPhases(phasesToRun.toList)(ctx)) try checker.typedExpr(ctx.compilationUnit.tpdTree)(checkingCtx) catch { diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala index 87ad0831c..0fee17bcd 100644 --- a/src/dotty/tools/dotc/typer/Applications.scala +++ b/src/dotty/tools/dotc/typer/Applications.scala @@ -153,7 +153,7 @@ trait Applications extends Compatibility { self: Typer => def ok = _ok def ok_=(x: Boolean) = { - assert(x || ctx.errorsReported || !ctx.typerState.isCommittable) // !!! DEBUG + assert(x || ctx.reporter.errorsReported || !ctx.typerState.isCommittable) // !!! DEBUG _ok = x } diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala index 5444dddb0..e3626fe20 100644 --- a/src/dotty/tools/dotc/typer/Implicits.scala +++ b/src/dotty/tools/dotc/typer/Implicits.scala @@ -495,7 +495,7 @@ trait Implicits { self: Typer => case _ => false } } - if (ctx.typerState.reporter.hasErrors) + if (ctx.reporter.hasErrors) nonMatchingImplicit(ref) else if (contextual && !ctx.mode.is(Mode.ImplicitShadowing) && !shadowing.tpe.isError && !refMatches(shadowing)) { diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala index f414d3bce..ac4ad1b35 100644 --- a/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/src/dotty/tools/dotc/typer/Inferencing.scala @@ -141,7 +141,7 @@ object Inferencing { if (toTest.isEmpty) acc else tree match { case Apply(fn, _) => - fn.tpe match { + fn.tpe.widen match { case mtp: MethodType => val (occ, nocc) = toTest.partition(tvar => mtp.paramTypes.exists(tvar.occursIn)) occurring(fn, nocc, occ ::: acc) diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 745eee8f8..60ecaac0b 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -200,7 +200,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit */ def isDefinedInCurrentUnit(denot: Denotation): Boolean = denot match { case MultiDenotation(d1, d2) => isDefinedInCurrentUnit(d1) || isDefinedInCurrentUnit(d2) - case denot: SingleDenotation => denot.symbol.sourceFile == ctx.source + case denot: SingleDenotation => denot.symbol.sourceFile == ctx.source.file } /** Is `denot` the denotation of a self symbol? */ @@ -502,6 +502,16 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit assignType(cpy.If(tree)(cond1, thenp2, elsep2), thenp2, elsep2) } + private def decomposeProtoFunction(pt: Type, defaultArity: Int)(implicit ctx: Context): (List[Type], Type) = pt match { + case _ if defn.isFunctionType(pt) => + (pt.dealias.argInfos.init, pt.dealias.argInfos.last) + case SAMType(meth) => + val mt @ MethodType(_, paramTypes) = meth.info + (paramTypes, mt.resultType) + case _ => + (List.range(0, defaultArity) map alwaysWildcardType, WildcardType) + } + def typedFunction(tree: untpd.Function, pt: Type)(implicit ctx: Context) = track("typedFunction") { val untpd.Function(args, body) = tree if (ctx.mode is Mode.Type) @@ -509,15 +519,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit untpd.TypeTree(defn.FunctionClass(args.length).typeRef), args :+ body), pt) else { val params = args.asInstanceOf[List[untpd.ValDef]] - val (protoFormals, protoResult): (List[Type], Type) = pt match { - case _ if defn.isFunctionType(pt) => - (pt.dealias.argInfos.init, pt.dealias.argInfos.last) - case SAMType(meth) => - val mt @ MethodType(_, paramTypes) = meth.info - (paramTypes, mt.resultType) - case _ => - (params map alwaysWildcardType, WildcardType) - } + val (protoFormals, protoResult) = decomposeProtoFunction(pt, params.length) def refersTo(arg: untpd.Tree, param: untpd.ValDef): Boolean = arg match { case Ident(name) => name == param.name @@ -563,7 +565,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit val pos = params indexWhere (_.name == param.name) if (pos < mtpe.paramTypes.length) { val ptype = mtpe.paramTypes(pos) - if (isFullyDefined(ptype, ForceDegree.none)) return ptype + if (isFullyDefined(ptype, ForceDegree.noBottom)) return ptype } case _ => } @@ -629,7 +631,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def typedMatch(tree: untpd.Match, pt: Type)(implicit ctx: Context) = track("typedMatch") { tree.selector match { case EmptyTree => - typed(desugar.makeCaseLambda(tree.cases) withPos tree.pos, pt) + val (protoFormals, _) = decomposeProtoFunction(pt, 1) + typed(desugar.makeCaseLambda(tree.cases, protoFormals.length) withPos tree.pos, pt) case _ => val sel1 = typedExpr(tree.selector) val selType = widenForMatchSelector( @@ -1000,7 +1003,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit */ def ensureConstrCall(cls: ClassSymbol, parents: List[Tree])(implicit ctx: Context): List[Tree] = { val firstParent :: otherParents = parents - if (firstParent.isType && !(cls is Trait)) + if (firstParent.isType && !(cls is Trait) && !cls.is(JavaDefined)) typed(untpd.New(untpd.TypedSplice(firstParent), Nil)) :: otherParents else parents } @@ -1238,7 +1241,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def adapt(tree: Tree, pt: Type, original: untpd.Tree = untpd.EmptyTree)(implicit ctx: Context) = /*>|>*/ track("adapt") /*<|<*/ { /*>|>*/ ctx.traceIndented(i"adapting $tree of type ${tree.tpe} to $pt", typr, show = true) /*<|<*/ { - interpolateUndetVars(tree, if (tree.isDef) tree.symbol else NoSymbol) + if (tree.isDef) interpolateUndetVars(tree, tree.symbol) + else if (!tree.tpe.widen.isInstanceOf[MethodOrPoly]) interpolateUndetVars(tree, NoSymbol) tree.overwriteType(tree.tpe.simplified) adaptInterpolated(tree, pt, original) } |