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..1fcfff34f125 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 eq JavaMethodType + final override def isImplicitMethod: Boolean = companion eq ImplicitMethodType + 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,7 @@ object Types { def syntheticParamName(n: Int) = tpnme.syntheticTypeParamName(n) } - abstract class MethodTypeCompanion extends TermLambdaCompanion[MethodType] { + abstract class MethodTypeCompanion extends TermLambdaCompanion[MethodType] { self => /** Produce method type from parameter symbols, with special mappings for repeated * and inline parameters: @@ -2833,6 +2825,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) @@ -2844,20 +2839,9 @@ 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))) - } - - 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)) - } - - 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))) - } + 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/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/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..6720eb671f5c 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)