diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index 18a7a88e0b24..4a413a436559 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -2270,9 +2270,9 @@ class JSCodeGen()(implicit ctx: Context) { if (sym == defn.BoxedUnit_UNIT) { js.Undefined() } else { - val instance = genLoadModule(sym.owner) + val inst = genLoadModule(sym.owner) val method = encodeStaticMemberSym(sym) - js.Apply(instance, method, Nil)(toIRType(sym.info)) + js.Apply(inst, method, Nil)(toIRType(sym.info)) } } diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 493a515d1acc..695795c878db 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -163,11 +163,11 @@ object desugar { else vdef } - def makeImplicitParameters(tpts: List[Tree], forPrimaryConstructor: Boolean = false)(implicit ctx: Context): List[ValDef] = + def makeImplicitParameters(tpts: List[Tree], contextualFlag: FlagSet = EmptyFlags, forPrimaryConstructor: Boolean = false)(implicit ctx: Context): List[ValDef] = for (tpt <- tpts) yield { val paramFlags: FlagSet = if (forPrimaryConstructor) PrivateLocalParamAccessor else Param val epname = EvidenceParamName.fresh() - ValDef(epname, tpt, EmptyTree).withFlags(paramFlags | Implicit) + ValDef(epname, tpt, EmptyTree).withFlags(paramFlags | Implicit | contextualFlag) } /** 1. Expand context bounds to evidence params. E.g., @@ -197,12 +197,13 @@ object desugar { * inline def f(x: Boolean): Any = (if (x) 1 else ""): Any */ private def defDef(meth: DefDef, isPrimaryConstructor: Boolean = false)(implicit ctx: Context): Tree = { - val DefDef(name, tparams, vparamss, tpt, rhs) = meth + val DefDef(_, tparams, vparamss, tpt, rhs) = meth + val methName = normalizeName(meth, tpt).asTermName val mods = meth.mods val epbuf = new ListBuffer[ValDef] def desugarContextBounds(rhs: Tree): Tree = rhs match { case ContextBounds(tbounds, cxbounds) => - epbuf ++= makeImplicitParameters(cxbounds, isPrimaryConstructor) + epbuf ++= makeImplicitParameters(cxbounds, forPrimaryConstructor = isPrimaryConstructor) tbounds case LambdaTypeTree(tparams, body) => cpy.LambdaTypeTree(rhs)(tparams, desugarContextBounds(body)) @@ -213,7 +214,8 @@ object desugar { cpy.TypeDef(tparam)(rhs = desugarContextBounds(tparam.rhs)) } - var meth1 = addEvidenceParams(cpy.DefDef(meth)(tparams = tparams1), epbuf.toList) + var meth1 = addEvidenceParams( + cpy.DefDef(meth)(name = methName, tparams = tparams1), epbuf.toList) if (meth1.mods.is(Inline)) meth1.tpt match { @@ -245,7 +247,7 @@ object desugar { case (vparam :: vparams) :: vparamss1 => def defaultGetter: DefDef = DefDef( - name = DefaultGetterName(meth.name, n), + name = DefaultGetterName(methName, n), tparams = meth.tparams.map(tparam => dropContextBound(toDefParam(tparam))), vparamss = takeUpTo(normalizedVparamss.nestedMap(toDefParam), n), tpt = TypeTree(), @@ -302,8 +304,8 @@ object desugar { /** The expansion of a class definition. See inline comments for what is involved */ def classDef(cdef: TypeDef)(implicit ctx: Context): Tree = { - val className = checkNotReservedName(cdef).asTypeName - val impl @ Template(_, _, self, _) = cdef.rhs + val impl @ Template(constr0, _, self, _) = cdef.rhs + val className = normalizeName(cdef, impl).asTypeName val parents = impl.parents val mods = cdef.mods val companionMods = mods @@ -341,6 +343,7 @@ object desugar { val isCaseClass = mods.is(Case) && !mods.is(Module) val isCaseObject = mods.is(Case) && mods.is(Module) val isImplicit = mods.is(Implicit) + val isInstance = isImplicit && mods.mods.exists(_.isInstanceOf[Mod.Instance]) val isEnum = mods.isEnumClass && !mods.is(Module) def isEnumCase = mods.isEnumCase val isValueClass = parents.nonEmpty && isAnyVal(parents.head) @@ -445,7 +448,15 @@ object desugar { } // new C[Ts](paramss) - lazy val creatorExpr = New(classTypeRef, constrVparamss nestedMap refOfDef) + lazy val creatorExpr = { + val vparamss = constrVparamss match { + case (vparam :: _) :: _ if vparam.mods.is(Implicit) => // add a leading () to match class parameters + Nil :: constrVparamss + case _ => + constrVparamss + } + New(classTypeRef, vparamss.nestedMap(refOfDef)) + } val copiedAccessFlags = if (ctx.scala2Setting) EmptyFlags else AccessFlags @@ -660,16 +671,23 @@ object desugar { ctx.error(ImplicitCaseClass(cdef), cdef.sourcePos) Nil } - else if (arity != 1) { + else if (arity != 1 && !isInstance) { ctx.error(ImplicitClassPrimaryConstructorArity(), cdef.sourcePos) Nil } - else + else { + val defParamss = constrVparamss match { + case Nil :: paramss => + paramss // drop leading () that got inserted by class + // TODO: drop this once we do not silently insert empty class parameters anymore + case paramss => paramss + } // implicit wrapper is typechecked in same scope as constructor, so // we can reuse the constructor parameters; no derived params are needed. - DefDef(className.toTermName, constrTparams, constrVparamss, classTypeRef, creatorExpr) - .withMods(companionMods | Synthetic | Implicit) + DefDef(className.toTermName, constrTparams, defParamss, classTypeRef, creatorExpr) + .withMods(companionMods | Synthetic | Implicit | Final) .withSpan(cdef.span) :: Nil + } val self1 = { val selfType = if (self.tpt.isEmpty) classTypeRef else self.tpt @@ -713,9 +731,9 @@ object desugar { * final class name$ extends parents { self: name.type => body } */ def moduleDef(mdef: ModuleDef)(implicit ctx: Context): Tree = { - val moduleName = checkNotReservedName(mdef).asTermName val impl = mdef.impl val mods = mdef.mods + val moduleName = normalizeName(mdef, impl).asTermName def isEnumCase = mods.isEnumCase def flagSourcePos(flag: FlagSet) = mods.mods.find(_.flags == flag).fold(mdef.sourcePos)(_.sourcePos) @@ -793,19 +811,69 @@ object desugar { Thicket(aliasType :: companions.toList) } - /** The name of `mdef`, after checking that it does not redefine a Scala core class. - * If it does redefine, issue an error and return a mangled name instead of the original one. + /** The normalized name of `mdef`. This means + * 1. Check that the name does not redefine a Scala core class. + * If it does redefine, issue an error and return a mangled name instead of the original one. + * 2. If the name is missing (this can be the case for instance definitions), invent one instead. */ - def checkNotReservedName(mdef: MemberDef)(implicit ctx: Context): Name = { - val name = mdef.name + def normalizeName(mdef: MemberDef, impl: Tree)(implicit ctx: Context): Name = { + var name = mdef.name + if (name.isEmpty) name = name.likeSpaced(s"${inventName(impl)}_instance".toTermName) if (ctx.owner == defn.ScalaPackageClass && defn.reservedScalaClassNames.contains(name.toTypeName)) { def kind = if (name.isTypeName) "class" else "object" ctx.error(em"illegal redefinition of standard $kind $name", mdef.sourcePos) - name.errorName + name = name.errorName } - else name + name } + /** Invent a name for an anonymous instance with template `impl`. + */ + private def inventName(impl: Tree)(implicit ctx: Context): String = impl match { + case impl: Template => + if (impl.parents.isEmpty) + impl.body.find { + case dd: DefDef if dd.mods.is(Extension) => true + case _ => false + } match { + case Some(DefDef(name, _, (vparam :: _) :: _, _, _)) => + s"${name}_of_${inventTypeName(vparam.tpt)}" + case _ => + ctx.error(i"anonymous instance must have `for` part or must define at least one extension method", impl.sourcePos) + nme.ERROR.toString + } + else + impl.parents.map(inventTypeName(_)).mkString("_") + case impl: Tree => + inventTypeName(impl) + } + + private class NameExtractor(followArgs: Boolean) extends UntypedTreeAccumulator[String] { + private def extractArgs(args: List[Tree])(implicit ctx: Context): String = + args.map(argNameExtractor.apply("", _)).mkString("_") + override def apply(x: String, tree: Tree)(implicit ctx: Context): String = + if (x.isEmpty) + tree match { + case Select(pre, nme.CONSTRUCTOR) => foldOver(x, pre) + case tree: RefTree if tree.name.isTypeName => tree.name.toString + case tree: TypeDef => tree.name.toString + case tree: AppliedTypeTree if followArgs && tree.args.nonEmpty => + s"${apply(x, tree.tpt)}_${extractArgs(tree.args)}" + case tree: LambdaTypeTree => + apply(x, tree.body) + case tree: Tuple => + if (followArgs) extractArgs(tree.trees) else "Tuple" + case tree: Function if tree.args.nonEmpty => + if (followArgs) s"${extractArgs(tree.args)}_to_${apply("", tree.body)}" else "Function" + case _ => foldOver(x, tree) + } + else x + } + private val typeNameExtractor = new NameExtractor(followArgs = true) + private val argNameExtractor = new NameExtractor(followArgs = false) + + private def inventTypeName(tree: Tree)(implicit ctx: Context): String = typeNameExtractor("", tree) + /** val p1, ..., pN: T = E * ==> * makePatDef[[val p1: T1 = E]]; ...; makePatDef[[val pN: TN = E]] @@ -960,14 +1028,11 @@ object desugar { * def $anonfun(params) = body * Closure($anonfun) */ - def makeClosure(params: List[ValDef], body: Tree, tpt: Tree = null, isImplicit: Boolean)(implicit ctx: Context): Block = { - val span = params.headOption.fold(body.span)(_.span.union(body.span)) + def makeClosure(params: List[ValDef], body: Tree, tpt: Tree = null, isContextual: Boolean)(implicit ctx: Context): Block = Block( DefDef(nme.ANON_FUN, Nil, params :: Nil, if (tpt == null) TypeTree() else tpt, body) - .withSpan(span) .withMods(synthetic | Artifact), - Closure(Nil, Ident(nme.ANON_FUN), if (isImplicit) ImplicitEmptyTree else EmptyTree)).withSpan(span) - } + Closure(Nil, Ident(nme.ANON_FUN), if (isContextual) ContextualEmptyTree else EmptyTree)) /** If `nparams` == 1, expand partial function * @@ -1020,9 +1085,9 @@ object desugar { Function(param :: Nil, Block(vdefs, body)) } - def makeImplicitFunction(formals: List[Type], body: Tree)(implicit ctx: Context): Tree = { - val params = makeImplicitParameters(formals.map(TypeTree)) - new FunctionWithMods(params, body, Modifiers(Implicit)) + def makeContextualFunction(formals: List[Type], body: Tree)(implicit ctx: Context): Tree = { + val params = makeImplicitParameters(formals.map(TypeTree), Contextual) + new FunctionWithMods(params, body, Modifiers(Implicit | Contextual)) } /** Add annotation to tree: diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index 0ab4a727135c..c10adfbc5cbf 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -330,15 +330,15 @@ trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped] functionWithUnknownParamType(tree).isDefined /** Is `tree` an implicit function or closure, possibly nested in a block? */ - def isImplicitClosure(tree: Tree)(implicit ctx: Context): Boolean = unsplice(tree) match { - case tree: FunctionWithMods => tree.mods.is(Implicit) - case Function((param: untpd.ValDef) :: _, _) => param.mods.is(Implicit) + def isContextualClosure(tree: Tree)(implicit ctx: Context): Boolean = unsplice(tree) match { + case tree: FunctionWithMods => tree.mods.is(Contextual) + case Function((param: untpd.ValDef) :: _, _) => param.mods.is(Contextual) case Closure(_, meth, _) => true - case Block(Nil, expr) => isImplicitClosure(expr) + case Block(Nil, expr) => isContextualClosure(expr) case Block(DefDef(nme.ANON_FUN, _, params :: _, _, _) :: Nil, cl: Closure) => params match { - case param :: _ => param.mods.is(Implicit) - case Nil => cl.tpt.eq(untpd.ImplicitEmptyTree) || defn.isImplicitFunctionType(cl.tpt.typeOpt) + case param :: _ => param.mods.is(Contextual) + case Nil => cl.tpt.eq(untpd.ContextualEmptyTree) || defn.isImplicitFunctionType(cl.tpt.typeOpt) } case _ => false } diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index d4adec6800e3..6cc697bfb5d6 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -430,6 +430,8 @@ object Trees { case class Apply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]])(implicit @constructorOnly src: SourceFile) extends GenericApply[T] { type ThisTree[-T >: Untyped] = Apply[T] + + def isContextual = getAttachment(untpd.WithApply).nonEmpty } /** fun[args] */ @@ -951,7 +953,7 @@ object Trees { @sharable val EmptyTree: Thicket = genericEmptyTree @sharable val EmptyValDef: ValDef = genericEmptyValDef - @sharable val ImplicitEmptyTree: Thicket = new EmptyTree // an empty tree marking an implicit closure + @sharable val ContextualEmptyTree: Thicket = new EmptyTree // an empty tree marking a contextual closure // ----- Auxiliary creation methods ------------------ diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 0e577a5ac774..e0cddaa25f07 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -233,7 +233,10 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { val previousParamRefs = if (isParamDependent) new mutable.ListBuffer[TermRef]() else null def valueParam(name: TermName, origInfo: Type): TermSymbol = { - val maybeImplicit = if (tp.isImplicitMethod) Implicit else EmptyFlags + val maybeImplicit = + if (tp.isContextual) Implicit | Contextual + else if (tp.isImplicitMethod) Implicit + else EmptyFlags val maybeErased = if (tp.isErasedMethod) Erased else EmptyFlags def makeSym(info: Type) = ctx.newSymbol(sym, name, TermParam | maybeImplicit | maybeErased, info, coord = sym.coord) @@ -1039,9 +1042,10 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } } - def applyOverloaded(receiver: Tree, method: TermName, args: List[Tree], targs: List[Type], expectedType: Type)(implicit ctx: Context): Tree = { + def applyOverloaded(receiver: Tree, method: TermName, args: List[Tree], targs: List[Type], + expectedType: Type, isContextual: Boolean = false)(implicit ctx: Context): Tree = { val typer = ctx.typer - val proto = new FunProtoTyped(args, expectedType)(typer) + val proto = new FunProtoTyped(args, expectedType)(typer, isContextual) val denot = receiver.tpe.member(method) assert(denot.exists, i"no member $receiver . $method, members = ${receiver.tpe.decls}") val selected = diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index ea562d3d77cb..428c74c85960 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -68,7 +68,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { override def isType: Boolean = body.isType } - /** A function type with `implicit` or `erased` modifiers */ + /** A function type with `implicit`, `erased`, or `contextual` modifiers */ class FunctionWithMods(args: List[Tree], body: Tree, val mods: Modifiers)(implicit @constructorOnly src: SourceFile) extends Function(args, body) @@ -149,6 +149,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { case class Inline()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Inline) case class Enum()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Enum) + + case class Instance()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Implicit) } /** Modifiers and annotations for definitions @@ -213,6 +215,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def hasFlags: Boolean = flags != EmptyFlags def hasAnnotations: Boolean = annotations.nonEmpty def hasPrivateWithin: Boolean = privateWithin != tpnme.EMPTY + def hasMod(cls: Class[_]) = mods.exists(_.getClass == cls) private def isEnum = is(Enum, butNot = JavaDefined) @@ -269,6 +272,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { */ val OriginalSymbol: Property.Key[Symbol] = new Property.Key + /** Property key for contextual Apply trees of the form `fn with arg` */ + val WithApply: Property.StickyKey[Unit] = new Property.StickyKey + // ------ Creation methods for untyped only ----------------- def Ident(name: Name)(implicit src: SourceFile): Ident = new Ident(name) @@ -398,9 +404,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def makeParameter(pname: TermName, tpe: Tree, mods: Modifiers = EmptyModifiers)(implicit ctx: Context): ValDef = ValDef(pname, tpe, EmptyTree).withMods(mods | Param) - def makeSyntheticParameter(n: Int = 1, tpt: Tree = null)(implicit ctx: Context): ValDef = + def makeSyntheticParameter(n: Int = 1, tpt: Tree = null, flags: FlagSet = EmptyFlags)(implicit ctx: Context): ValDef = ValDef(nme.syntheticParamName(n), if (tpt == null) TypeTree() else tpt, EmptyTree) - .withFlags(SyntheticTermParam) + .withFlags(flags | SyntheticTermParam) def lambdaAbstract(tparams: List[TypeDef], tpt: Tree)(implicit ctx: Context): Tree = if (tparams.isEmpty) tpt else LambdaTypeTree(tparams, tpt) diff --git a/compiler/src/dotty/tools/dotc/config/Printers.scala b/compiler/src/dotty/tools/dotc/config/Printers.scala index cf10ab175937..27df2dfac103 100644 --- a/compiler/src/dotty/tools/dotc/config/Printers.scala +++ b/compiler/src/dotty/tools/dotc/config/Printers.scala @@ -17,7 +17,7 @@ object Printers { val checks: Printer = noPrinter val config: Printer = noPrinter val cyclicErrors: Printer = noPrinter - val debug = noPrinter + val debug = noPrinter // no type annotion here to force inlining val derive: Printer = noPrinter val dottydoc: Printer = noPrinter val exhaustivity: Printer = noPrinter diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 30f89c5c44d1..5bd447bfb590 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -99,8 +99,8 @@ class Definitions { * * ImplicitFunctionN traits follow this template: * - * trait ImplicitFunctionN[T0,...,T{N-1}, R] extends Object with FunctionN[T0,...,T{N-1}, R] { - * def apply(implicit $x0: T0, ..., $x{N_1}: T{N-1}): R + * trait ImplicitFunctionN[T0,...,T{N-1}, R] extends Object { + * def apply with ($x0: T0, ..., $x{N_1}: T{N-1}): R * } * * ErasedFunctionN traits follow this template: @@ -111,8 +111,8 @@ class Definitions { * * ErasedImplicitFunctionN traits follow this template: * - * trait ErasedImplicitFunctionN[T0,...,T{N-1}, R] extends Object with ErasedFunctionN[T0,...,T{N-1}, R] { - * def apply(erased implicit $x0: T0, ..., $x{N_1}: T{N-1}): R + * trait ErasedImplicitFunctionN[T0,...,T{N-1}, R] extends Object { + * def apply with (erased $x0: T0, ..., $x{N_1}: T{N-1}): R * } * * ErasedFunctionN and ErasedImplicitFunctionN erase to Function0. @@ -128,13 +128,14 @@ class Definitions { enterTypeParam(cls, paramNamePrefix ++ "T" ++ (i + 1).toString, Contravariant, decls).typeRef } val resParamRef = enterTypeParam(cls, paramNamePrefix ++ "R", Covariant, decls).typeRef - val methodType = MethodType.maker(isJava = false, name.isImplicitFunction, name.isErasedFunction) - val parentTraits = - if (!name.isImplicitFunction) Nil - else FunctionType(arity, isErased = name.isErasedFunction).appliedTo(argParamRefs ::: resParamRef :: Nil) :: Nil + val methodType = MethodType.maker( + isJava = false, + isImplicit = name.isImplicitFunction, + isContextual = name.isImplicitFunction, + isErased = name.isErasedFunction) decls.enter(newMethod(cls, nme.apply, methodType(argParamRefs, resParamRef), Deferred)) denot.info = - ClassInfo(ScalaPackageClass.thisType, cls, ObjectType :: parentTraits, decls) + ClassInfo(ScalaPackageClass.thisType, cls, ObjectType :: Nil, decls) } } newClassSymbol(ScalaPackageClass, name, Trait | NoInits, completer) @@ -388,9 +389,6 @@ class Definitions { def DottyPredefModule(implicit ctx: Context): Symbol = DottyPredefModuleRef.symbol - lazy val Predef_ImplicitConverterR: TypeRef = DottyPredefModule.requiredClass("ImplicitConverter").typeRef - def Predef_ImplicitConverter(implicit ctx: Context): Symbol = Predef_ImplicitConverterR.symbol - lazy val DottyArraysModuleRef: TermRef = ctx.requiredModuleRef("dotty.runtime.Arrays") def DottyArraysModule(implicit ctx: Context): Symbol = DottyArraysModuleRef.symbol def newGenericArrayMethod(implicit ctx: Context): TermSymbol = DottyArraysModule.requiredMethod("newGenericArray") @@ -591,6 +589,8 @@ class Definitions { def StringBuilderClass(implicit ctx: Context): ClassSymbol = StringBuilderType.symbol.asClass lazy val MatchErrorType: TypeRef = ctx.requiredClassRef("scala.MatchError") def MatchErrorClass(implicit ctx: Context): ClassSymbol = MatchErrorType.symbol.asClass + lazy val ConversionType: TypeRef = ctx.requiredClass("scala.Conversion").typeRef + def ConversionClass(implicit ctx: Context): ClassSymbol = ConversionType.symbol.asClass lazy val StringAddType: TypeRef = ctx.requiredClassRef("scala.runtime.StringAdd") def StringAddClass(implicit ctx: Context): ClassSymbol = StringAddType.symbol.asClass @@ -860,8 +860,8 @@ class Definitions { sym.owner.linkedClass.typeRef object FunctionOf { - def apply(args: List[Type], resultType: Type, isImplicit: Boolean = false, isErased: Boolean = false)(implicit ctx: Context): Type = - FunctionType(args.length, isImplicit, isErased).appliedTo(args ::: resultType :: Nil) + def apply(args: List[Type], resultType: Type, isContextual: Boolean = false, isErased: Boolean = false)(implicit ctx: Context): Type = + FunctionType(args.length, isContextual, isErased).appliedTo(args ::: resultType :: Nil) def unapply(ft: Type)(implicit ctx: Context): Option[(List[Type], Type, Boolean, Boolean)] = { val tsym = ft.typeSymbol if (isFunctionClass(tsym)) { @@ -949,10 +949,10 @@ class Definitions { lazy val TupleType: Array[TypeRef] = mkArityArray("scala.Tuple", MaxTupleArity, 1) - def FunctionClass(n: Int, isImplicit: Boolean = false, isErased: Boolean = false)(implicit ctx: Context): Symbol = - if (isImplicit && isErased) + def FunctionClass(n: Int, isContextual: Boolean = false, isErased: Boolean = false)(implicit ctx: Context): Symbol = + if (isContextual && isErased) ctx.requiredClass("scala.ErasedImplicitFunction" + n.toString) - else if (isImplicit) + else if (isContextual) ctx.requiredClass("scala.ImplicitFunction" + n.toString) else if (isErased) ctx.requiredClass("scala.ErasedFunction" + n.toString) @@ -964,9 +964,9 @@ class Definitions { lazy val Function0_applyR: TermRef = ImplementedFunctionType(0).symbol.requiredMethodRef(nme.apply) def Function0_apply(implicit ctx: Context): Symbol = Function0_applyR.symbol - def FunctionType(n: Int, isImplicit: Boolean = false, isErased: Boolean = false)(implicit ctx: Context): TypeRef = - if (n <= MaxImplementedFunctionArity && (!isImplicit || ctx.erasedTypes) && !isErased) ImplementedFunctionType(n) - else FunctionClass(n, isImplicit, isErased).typeRef + def FunctionType(n: Int, isContextual: Boolean = false, isErased: Boolean = false)(implicit ctx: Context): TypeRef = + if (n <= MaxImplementedFunctionArity && (!isContextual || ctx.erasedTypes) && !isErased) ImplementedFunctionType(n) + else FunctionClass(n, isContextual, isErased).typeRef /** If `cls` is a class in the scala package, its name, otherwise EmptyTypeName */ def scalaClassName(cls: Symbol)(implicit ctx: Context): TypeName = diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index 7368d85484be..f7bad7265047 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -312,7 +312,6 @@ object Flags { final val Contravariant: FlagSet = typeFlag(21, "") final val Label: FlagSet = termFlag(21, "