From 81dc91db0ef630dd5cc6527f1aef5a048f8115ed Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 29 Sep 2017 17:47:12 +0200 Subject: [PATCH 1/3] Remove ImplicitMethodType and JavaMethodType --- .../backend/jvm/DottyBackendInterface.scala | 2 +- .../src/dotty/tools/dotc/ast/TreeInfo.scala | 3 +- compiler/src/dotty/tools/dotc/ast/tpd.scala | 2 +- .../dotty/tools/dotc/core/Denotations.scala | 4 +- .../dotty/tools/dotc/core/TypeComparer.scala | 6 +- .../dotty/tools/dotc/core/TypeErasure.scala | 4 +- .../src/dotty/tools/dotc/core/Types.scala | 59 +++++++++---------- .../core/unpickleScala2/Scala2Unpickler.scala | 3 +- .../tools/dotc/printing/PlainPrinter.scala | 2 +- .../src/dotty/tools/dotc/sbt/ExtractAPI.scala | 2 +- .../tools/dotc/transform/ElimRepeated.scala | 2 +- .../dotty/tools/dotc/typer/Applications.scala | 4 +- .../tools/dotc/typer/ErrorReporting.scala | 2 +- .../dotty/tools/dotc/typer/EtaExpansion.scala | 2 +- .../dotty/tools/dotc/typer/Implicits.scala | 6 +- .../src/dotty/tools/dotc/typer/Namer.scala | 7 +-- .../dotty/tools/dotc/typer/ProtoTypes.scala | 2 +- .../src/dotty/tools/dotc/typer/Typer.scala | 11 ++-- .../tools/dottydoc/model/factories.scala | 2 +- 19 files changed, 61 insertions(+), 64 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index d75335f09931..c6fc78139190 100644 --- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -267,7 +267,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma toDenot(fun.symbol).owner == defn.ArrayClass.linkedClass && fun.symbol.name == nme_apply => val arrAnnotV: AnnotationVisitor = av.visitArray(name) - var actualArgs = if (fun.tpe.isInstanceOf[ImplicitMethodType]) { + var actualArgs = if (fun.tpe.isImplicitMethod) { // generic array method, need to get implicit argument out of the way fun.asInstanceOf[Apply].args } else args diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index 6b24e3f3643c..0861b7d870c2 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -450,7 +450,8 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => */ def mayBeVarGetter(sym: Symbol)(implicit ctx: Context): Boolean = { def maybeGetterType(tpe: Type): Boolean = tpe match { - case _: ExprType | _: ImplicitMethodType => true + case _: ExprType => true + case tpe: MethodType => tpe.isImplicitMethod case tpe: PolyType => maybeGetterType(tpe.resultType) case _ => false } diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 862d44c0be57..8e23819aa77d 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -195,7 +195,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { def valueParamss(tp: Type): (List[List[TermSymbol]], Type) = tp match { case tp: MethodType => def valueParam(name: TermName, info: Type): TermSymbol = { - val maybeImplicit = if (tp.isInstanceOf[ImplicitMethodType]) Implicit else EmptyFlags + val maybeImplicit = if (tp.isImplicitMethod) Implicit else EmptyFlags ctx.newSymbol(sym, name, TermParam | maybeImplicit, info) } val params = (tp.paramNames, tp.paramInfos).zipped.map(valueParam) diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index 9efa9cfe9a79..64768a302ebf 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -325,7 +325,7 @@ object Denotations { if (tp1.isInstanceOf[PolyType] && tp2.isInstanceOf[MethodType]) tp2 else if (tp2.isInstanceOf[PolyType] && tp1.isInstanceOf[MethodType]) tp1 else if (ctx.typeComparer.matchingParams(tp1, tp2) && - tp1.isImplicit == tp2.isImplicit) + tp1.isImplicitMethod == tp2.isImplicitMethod) tp1.derivedLambdaType( mergeParamNames(tp1, tp2), tp1.paramInfos, infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1))) @@ -481,7 +481,7 @@ object Denotations { tp2 match { case tp2: MethodOrPoly if ctx.typeComparer.matchingParams(tp1, tp2) && - tp1.isImplicit == tp2.isImplicit => + tp1.isImplicitMethod == tp2.isImplicitMethod => tp1.derivedLambdaType( mergeParamNames(tp1, tp2), tp1.paramInfos, tp1.resultType | tp2.resultType.subst(tp2, tp1)) diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 69d1c2a4454a..42c7748f274c 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -508,7 +508,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case tp1: MethodOrPoly => (tp1.signature consistentParams tp2.signature) && matchingParams(tp1, tp2) && - tp1.isImplicit == tp2.isImplicit && + tp1.isImplicitMethod == tp2.isImplicitMethod && isSubType(tp1.resultType, tp2.resultType.subst(tp2, tp1)) case _ => false @@ -1136,8 +1136,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case formal2 :: rest2 => val formal2a = if (lam2.isParamDependent) formal2.subst(lam2, lam1) else formal2 (isSameTypeWhenFrozen(formal1, formal2a) - || lam1.isJava && (formal2 isRef ObjectClass) && (formal1 isRef AnyClass) - || lam2.isJava && (formal1 isRef ObjectClass) && (formal2 isRef AnyClass)) && + || lam1.isJavaMethod && (formal2 isRef ObjectClass) && (formal1 isRef AnyClass) + || lam2.isJavaMethod && (formal1 isRef ObjectClass) && (formal2 isRef AnyClass)) && loop(rest1, rest2) case nil => false diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index 9c3a872b8f65..43acca10a1d1 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -206,7 +206,7 @@ object TypeErasure { !tp.symbol.is(JavaDefined) case tp: TypeParamRef => !tp.derivesFrom(defn.ObjectClass) && - !tp.binder.resultType.isInstanceOf[JavaMethodType] + !tp.binder.resultType.isJavaMethod case tp: TypeAlias => isUnboundedGeneric(tp.alias) case tp: TypeBounds => !tp.hi.derivesFrom(defn.ObjectClass) case tp: TypeProxy => isUnboundedGeneric(tp.underlying) @@ -398,7 +398,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean ctx.typeComparer.orType(this(tp1), this(tp2), erased = true) case tp: MethodType => def paramErasure(tpToErase: Type) = - erasureFn(tp.isJava, semiEraseVCs, isConstructor, wildcardOK)(tpToErase) + erasureFn(tp.isJavaMethod, semiEraseVCs, isConstructor, wildcardOK)(tpToErase) val (names, formals0) = if (tp.paramInfos.exists(_.isPhantom)) tp.paramNames.zip(tp.paramInfos).filterNot(_._2.isPhantom).unzip else (tp.paramNames, tp.paramInfos) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 54c3113ddfe0..74f62069cac5 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -288,6 +288,12 @@ object Types { /** Is this an alias TypeBounds? */ final def isAlias: Boolean = this.isInstanceOf[TypeAlias] + /** Is this a MethodType which is from Java */ + def isJavaMethod: Boolean = false + + /** Is this a MethodType which has implicit parameters */ + def isImplicitMethod: Boolean = false + // ----- Higher-order combinators ----------------------------------- /** Returns true if there is a part of this type that satisfies predicate `p`. @@ -1317,7 +1323,7 @@ object Types { case mt: MethodType if !mt.isDependent || ctx.mode.is(Mode.AllowDependentFunctions) => val formals1 = if (dropLast == 0) mt.paramInfos else mt.paramInfos dropRight dropLast defn.FunctionOf( - formals1 mapConserve (_.underlyingIfRepeated(mt.isJava)), mt.resultType, mt.isImplicit && !ctx.erasedTypes) + formals1 mapConserve (_.underlyingIfRepeated(mt.isJavaMethod)), mt.resultType, mt.isImplicitMethod && !ctx.erasedTypes) } /** The signature of this type. This is by default NotAMethod, @@ -2552,9 +2558,6 @@ object Types { override def resultType(implicit ctx: Context) = resType - def isJava: Boolean = false - def isImplicit = false - def isDependent(implicit ctx: Context): Boolean def isParamDependent(implicit ctx: Context): Boolean @@ -2708,12 +2711,17 @@ object Types { type This = MethodType + def companion: MethodTypeCompanion + + final override def isJavaMethod: Boolean = companion.isJava + final override def isImplicitMethod: Boolean = companion.isImplicit + val paramInfos = paramInfosExp(this) val resType = resultTypeExp(this) assert(resType.exists) def computeSignature(implicit ctx: Context): Signature = - resultSignature.prepend(paramInfos, isJava) + resultSignature.prepend(paramInfos, isJavaMethod) final override def computeHash = doHash(paramNames, resType, paramInfos) @@ -2740,24 +2748,8 @@ object Types { protected def prefixString = "MethodType" } - final class CachedMethodType(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type) - extends MethodType(paramNames)(paramInfosExp, resultTypeExp) { - def companion = MethodType - } - - final class JavaMethodType(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type) - extends MethodType(paramNames)(paramInfosExp, resultTypeExp) { - def companion = JavaMethodType - override def isJava = true - override protected def prefixString = "JavaMethodType" - } - - final class ImplicitMethodType(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type) - extends MethodType(paramNames)(paramInfosExp, resultTypeExp) { - def companion = ImplicitMethodType - override def isImplicit = true - override protected def prefixString = "ImplicitMethodType" - } + final class CachedMethodType(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type, val companion: MethodTypeCompanion) + extends MethodType(paramNames)(paramInfosExp, resultTypeExp) abstract class LambdaTypeCompanion[N <: Name, PInfo <: Type, LT <: LambdaType] { def syntheticParamName(n: Int): N @@ -2802,7 +2794,10 @@ object Types { def syntheticParamName(n: Int) = tpnme.syntheticTypeParamName(n) } - abstract class MethodTypeCompanion extends TermLambdaCompanion[MethodType] { + abstract class MethodTypeCompanion extends TermLambdaCompanion[MethodType] { self => + + def isJava: Boolean = false + def isImplicit: Boolean = false /** Produce method type from parameter symbols, with special mappings for repeated * and inline parameters: @@ -2833,6 +2828,9 @@ object Types { tl => tl.integrate(params, resultType)) } + final def apply(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType = + checkValid(new CachedMethodType(paramNames)(paramInfosExp, resultTypeExp, self)) + def checkValid(mt: MethodType)(implicit ctx: Context): mt.type = { if (Config.checkMethodTypes) for ((paramInfo, idx) <- mt.paramInfos.zipWithIndex) @@ -2845,18 +2843,19 @@ object Types { } object MethodType extends MethodTypeCompanion { - def apply(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType = - checkValid(unique(new CachedMethodType(paramNames)(paramInfosExp, resultTypeExp))) + def withKind(isJava: Boolean = false, isImplicit: Boolean = false): MethodTypeCompanion = { + if (isJava) JavaMethodType + else if (isImplicit) ImplicitMethodType + else MethodType + } } object JavaMethodType extends MethodTypeCompanion { - def apply(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType = - unique(new JavaMethodType(paramNames)(paramInfosExp, resultTypeExp)) + override def isJava: Boolean = true } object ImplicitMethodType extends MethodTypeCompanion { - def apply(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType = - checkValid(unique(new ImplicitMethodType(paramNames)(paramInfosExp, resultTypeExp))) + override def isImplicit: Boolean = true } /** A ternary extractor for MethodType */ diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 19e79f36d4a9..9b991d35cce0 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -774,8 +774,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas def isImplicit = tag == IMPLICITMETHODtpe || params.nonEmpty && (params.head is Implicit) - val maker = if (isImplicit) ImplicitMethodType else MethodType - maker.fromSymbols(params, restpe) + MethodType.withKind(isImplicit = isImplicit).fromSymbols(params, restpe) case POLYtpe => val restpe = readTypeRef() val typeParams = until(end, readSymbolRef) diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index ce8b4240fcac..6294bacf3417 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -182,7 +182,7 @@ class PlainPrinter(_ctx: Context) extends Printer { case tp: MethodType => def paramText(name: TermName, tp: Type) = toText(name) ~ ": " ~ toText(tp) changePrec(GlobalPrec) { - (if (tp.isImplicit) "(implicit " else "(") ~ + (if (tp.isImplicitMethod) "(implicit " else "(") ~ Text((tp.paramNames, tp.paramInfos).zipped map paramText, ", ") ~ (if (tp.resultType.isInstanceOf[MethodType]) ")" else "): ") ~ toText(tp.resultType) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 0533de0f36f6..8f78369371b4 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -308,7 +308,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val params = (pnames, ptypes, defaults).zipped.map((pname, ptype, isDefault) => new api.MethodParameter(pname.toString, apiType(ptype), isDefault, api.ParameterModifier.Plain)) - new api.ParameterList(params.toArray, mt.isImplicit) :: paramLists(restpe, params.length) + new api.ParameterList(params.toArray, mt.isImplicitMethod) :: paramLists(restpe, params.length) case _ => Nil } diff --git a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala index 60da2e7c33b6..5b88ed439913 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala @@ -54,7 +54,7 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati val resultType1 = elimRepeated(resultType) val paramTypes1 = if (paramTypes.nonEmpty && paramTypes.last.isRepeatedParam) { - val last = paramTypes.last.underlyingIfRepeated(tp.isJava) + val last = paramTypes.last.underlyingIfRepeated(tp.isJavaMethod) paramTypes.init :+ last } else paramTypes tp.derivedLambdaType(paramNames, paramTypes1, resultType1) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 4bb4b7820c98..3d10e6a630ce 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -557,7 +557,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => typedArgBuf.trimEnd(n) val elemtpt = TypeTree(elemFormal) val seqLit = - if (methodType.isJava) JavaSeqLiteral(args, elemtpt) + if (methodType.isJavaMethod) JavaSeqLiteral(args, elemtpt) else SeqLiteral(args, elemtpt) typedArgBuf += seqToRepeated(seqLit) } @@ -1149,7 +1149,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => /** Drop any implicit parameter section */ def stripImplicit(tp: Type): Type = tp match { - case mt: ImplicitMethodType => + case mt: MethodType if mt.isImplicitMethod => resultTypeApprox(mt) case pt: PolyType => pt.derivedLambdaType(pt.paramNames, pt.paramInfos, stripImplicit(pt.resultType)) diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala index 83397e4dd532..9714549b6bee 100644 --- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -116,7 +116,7 @@ object ErrorReporting { def dropJavaMethod(tp: Type): Type = tp match { case tp: PolyType => tp.derivedLambdaType(resType = dropJavaMethod(tp.resultType)) - case tp: JavaMethodType => + case tp: MethodType if tp.isJavaMethod => MethodType(tp.paramNames, tp.paramInfos, dropJavaMethod(tp.resultType)) case tp => tp } diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala index 0d8d3384a3a7..828b559a47ae 100644 --- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala +++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala @@ -145,7 +145,7 @@ object EtaExpansion { ids = ids.init :+ repeated(ids.last) var body: Tree = Apply(lifted, ids) mt.resultType match { - case rt: MethodType if !rt.isImplicit => body = PostfixOp(body, Ident(nme.WILDCARD)) + case rt: MethodType if !rt.isImplicitMethod => body = PostfixOp(body, Ident(nme.WILDCARD)) case _ => } val fn = untpd.Function(params, body) diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 9cececffd041..cc62d3448d0d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -65,7 +65,7 @@ object Implicits { def discardForView(tpw: Type, argType: Type): Boolean = tpw match { case mt: MethodType => - mt.isImplicit || + mt.isImplicitMethod || mt.paramInfos.length != 1 || !ctx.typerState.test(argType relaxed_<:< mt.paramInfos.head) case poly: PolyType => @@ -73,7 +73,7 @@ object Implicits { // `refMatches` is always called with mode TypevarsMissContext enabled. poly.resultType match { case mt: MethodType => - mt.isImplicit || + mt.isImplicitMethod || mt.paramInfos.length != 1 || !ctx.typerState.test(argType relaxed_<:< wildApprox(mt.paramInfos.head, null, Set.empty)) case rtp => @@ -109,7 +109,7 @@ object Implicits { } def discardForValueType(tpw: Type): Boolean = tpw.stripPoly match { - case tpw: MethodType => !tpw.isImplicit + case tpw: MethodType => !tpw.isImplicitMethod case _ => false } diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index abbf36bf50f7..9868977901b9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -107,14 +107,11 @@ trait NamerContextOps { this: Context => def methodType(typeParams: List[Symbol], valueParamss: List[List[Symbol]], resultType: Type, isJava: Boolean = false)(implicit ctx: Context): Type = { val monotpe = (valueParamss :\ resultType) { (params, resultType) => - val make = - if (params.nonEmpty && (params.head is Implicit)) ImplicitMethodType - else if (isJava) JavaMethodType - else MethodType + val isImplicit = params.nonEmpty && (params.head is Implicit) if (isJava) for (param <- params) if (param.info.isDirectRef(defn.ObjectClass)) param.info = defn.AnyType - make.fromSymbols(params.asInstanceOf[List[TermSymbol]], resultType) + MethodType.withKind(isJava, isImplicit).fromSymbols(params.asInstanceOf[List[TermSymbol]], resultType) } if (typeParams.nonEmpty) PolyType.fromParams(typeParams.asInstanceOf[List[TypeSymbol]], monotpe) else if (valueParamss.isEmpty) ExprType(monotpe) diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index e7fe53bff0c6..4f9addf9e8d9 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -446,7 +446,7 @@ object ProtoTypes { case poly: PolyType => normalize(constrained(poly).resultType, pt) case mt: MethodType => - if (mt.isImplicit) normalize(resultTypeApprox(mt), pt) + if (mt.isImplicitMethod) normalize(resultTypeApprox(mt), pt) else if (mt.isDependent) tp else { val rt = normalize(mt.resultType, pt) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 0b50276fb4e2..dc4bc06a01b6 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1345,7 +1345,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit * @param cinfo The info of its constructor */ def maybeCall(ref: Tree, psym: Symbol, cinfo: Type): Tree = cinfo.stripPoly match { - case cinfo @ MethodType(Nil) if cinfo.resultType.isInstanceOf[ImplicitMethodType] => + case cinfo @ MethodType(Nil) if cinfo.resultType.isImplicitMethod => val icall = New(ref).select(nme.CONSTRUCTOR).appliedToNone typedExpr(untpd.TypedSplice(icall))(superCtx) case cinfo @ MethodType(Nil) if !cinfo.resultType.isInstanceOf[MethodType] => @@ -1990,7 +1990,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } } - def adaptNoArgsImplicitMethod(wtp: ImplicitMethodType): Tree = { + def adaptNoArgsImplicitMethod(wtp: MethodType): Tree = { + assert(wtp.isImplicitMethod) val tvarsToInstantiate = tvarsInParams(tree) wtp.paramInfos.foreach(instantiateSelected(_, tvarsToInstantiate)) val constr = ctx.typerState.constraint @@ -2085,7 +2086,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit typed(etaExpand(tree, wtp, arity), pt) else if (wtp.paramInfos.isEmpty && isAutoApplied(tree.symbol)) adaptInterpolated(tpd.Apply(tree, Nil), pt) - else if (wtp.isImplicit) + else if (wtp.isImplicitMethod) err.typeMismatch(tree, pt) else missingArgs(wtp) @@ -2148,8 +2149,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit wtp match { case wtp: ExprType => adaptInterpolated(tree.withType(wtp.resultType), pt) - case wtp: ImplicitMethodType - if constrainResult(wtp, followAlias(pt)) || !functionExpected => + case wtp: MethodType + if wtp.isImplicitMethod && constrainResult(wtp, followAlias(pt)) || !functionExpected => adaptNoArgsImplicitMethod(wtp) case wtp: MethodType if !pt.isInstanceOf[SingletonType] => val arity = diff --git a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala index 2f76859395c1..b1f3e530ee55 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala @@ -170,7 +170,7 @@ object factories { isByName = tpe.isInstanceOf[ExprType], isRepeated = tpe.isRepeatedParam ) - }, mt.isImplicit) :: paramLists(mt.resultType) + }, mt.isImplicitMethod) :: paramLists(mt.resultType) case mp: TermParamRef => paramLists(mp.underlying) From 481188961ebd41642997a70f3a7bebe0df18f468 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 4 Oct 2017 21:42:10 +0200 Subject: [PATCH 2/3] Remove unneeded abstractions --- .../src/dotty/tools/dotc/core/Types.scala | 25 ++++--------------- .../core/unpickleScala2/Scala2Unpickler.scala | 3 ++- .../src/dotty/tools/dotc/typer/Namer.scala | 7 ++++-- 3 files changed, 12 insertions(+), 23 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 74f62069cac5..1fcfff34f125 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2713,8 +2713,8 @@ object Types { def companion: MethodTypeCompanion - final override def isJavaMethod: Boolean = companion.isJava - final override def isImplicitMethod: Boolean = companion.isImplicit + final override def isJavaMethod: Boolean = companion eq JavaMethodType + final override def isImplicitMethod: Boolean = companion eq ImplicitMethodType val paramInfos = paramInfosExp(this) val resType = resultTypeExp(this) @@ -2796,9 +2796,6 @@ object Types { abstract class MethodTypeCompanion extends TermLambdaCompanion[MethodType] { self => - def isJava: Boolean = false - def isImplicit: Boolean = false - /** Produce method type from parameter symbols, with special mappings for repeated * and inline parameters: * - replace @repeated annotations on Seq or Array types by types @@ -2842,21 +2839,9 @@ object Types { } } - object MethodType extends MethodTypeCompanion { - def withKind(isJava: Boolean = false, isImplicit: Boolean = false): MethodTypeCompanion = { - if (isJava) JavaMethodType - else if (isImplicit) ImplicitMethodType - else MethodType - } - } - - object JavaMethodType extends MethodTypeCompanion { - override def isJava: Boolean = true - } - - object ImplicitMethodType extends MethodTypeCompanion { - override def isImplicit: Boolean = true - } + object MethodType extends MethodTypeCompanion + object JavaMethodType extends MethodTypeCompanion + object ImplicitMethodType extends MethodTypeCompanion /** A ternary extractor for MethodType */ object MethodTpe { diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 9b991d35cce0..19e79f36d4a9 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -774,7 +774,8 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas def isImplicit = tag == IMPLICITMETHODtpe || params.nonEmpty && (params.head is Implicit) - MethodType.withKind(isImplicit = isImplicit).fromSymbols(params, restpe) + val maker = if (isImplicit) ImplicitMethodType else MethodType + maker.fromSymbols(params, restpe) case POLYtpe => val restpe = readTypeRef() val typeParams = until(end, readSymbolRef) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 9868977901b9..abbf36bf50f7 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -107,11 +107,14 @@ trait NamerContextOps { this: Context => def methodType(typeParams: List[Symbol], valueParamss: List[List[Symbol]], resultType: Type, isJava: Boolean = false)(implicit ctx: Context): Type = { val monotpe = (valueParamss :\ resultType) { (params, resultType) => - val isImplicit = params.nonEmpty && (params.head is Implicit) + val make = + if (params.nonEmpty && (params.head is Implicit)) ImplicitMethodType + else if (isJava) JavaMethodType + else MethodType if (isJava) for (param <- params) if (param.info.isDirectRef(defn.ObjectClass)) param.info = defn.AnyType - MethodType.withKind(isJava, isImplicit).fromSymbols(params.asInstanceOf[List[TermSymbol]], resultType) + make.fromSymbols(params.asInstanceOf[List[TermSymbol]], resultType) } if (typeParams.nonEmpty) PolyType.fromParams(typeParams.asInstanceOf[List[TypeSymbol]], monotpe) else if (valueParamss.isEmpty) ExprType(monotpe) From d39513e7bf1cdb1e345e4d2f114b242017b58e98 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 6 Oct 2017 09:03:53 +0200 Subject: [PATCH 3/3] Fix implicit MethodType guard --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index dc4bc06a01b6..6720eb671f5c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2150,7 +2150,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case wtp: ExprType => adaptInterpolated(tree.withType(wtp.resultType), pt) case wtp: MethodType - if wtp.isImplicitMethod && constrainResult(wtp, followAlias(pt)) || !functionExpected => + if wtp.isImplicitMethod && (constrainResult(wtp, followAlias(pt)) || !functionExpected) => adaptNoArgsImplicitMethod(wtp) case wtp: MethodType if !pt.isInstanceOf[SingletonType] => val arity =