Skip to content

Try/auto tupling #51

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ object desugar {
*/
private object VarPattern {
def unapply(tree: Tree)(implicit ctx: Context): Option[VarInfo] = tree match {
case id: Ident => Some((id, TypeTree())) // Dotty deviation: No auto-tupling
case id: Ident => Some(id, TypeTree())
case Typed(id: Ident, tpt) => Some((id, tpt))
case _ => None
}
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/config/Settings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ object Settings {
copy(aliases = aliases :+ abbrv)(idx)

def dependsOn[U](setting: Setting[U], value: U): Setting[T] =
copy(depends = depends :+ ((setting, value)))(idx) // Dotty deviation: no auto-tupling
copy(depends = depends :+ (setting, value))(idx)

def valueIn(state: SettingsState): T =
state.value(idx).asInstanceOf[T]
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ object Contexts {
newctx.implicitsCache = null
newctx.setCreationTrace()
// Dotty deviation: Scala2x allows access to private members implicitCache and setCreationTrace
// even from a subclass prefix. Dotty (and Java) do not. I think that's a bug in Scala2x.
// even from a subclass prefix. Dotty (and Java) do not. It's confirmed as a bug in Scala2x.
newctx.asInstanceOf[FreshContext]
}

Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ class Definitions {
lazy val targs = ft.argInfos
if ((FunctionClasses contains tsym) &&
(targs.length - 1 <= MaxFunctionArity) &&
(FunctionClass(targs.length - 1) == tsym)) Some((targs.init, targs.last)) // Dotty deviation: no auto-tupling
(FunctionClass(targs.length - 1) == tsym)) Some(targs.init, targs.last)
else None
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,13 @@ object Types {
case _ => Nil
}

/** The parameter types in the first parameter section of a PolyType or MethodType, Empty list for others */
final def firstParamTypes: List[Type] = this match {
case mt: MethodType => mt.paramTypes
case pt: PolyType => pt.resultType.firstParamTypes
case _ => Nil
}

/** Is this either not a method at all, or a parameterless method? */
final def isParameterless: Boolean = this match {
case mt: MethodType => false
Expand Down
10 changes: 5 additions & 5 deletions src/dotty/tools/dotc/core/pickling/PickleBuffer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -229,25 +229,25 @@ object PickleBuffer {
PARAM -> Param,
PACKAGE -> Package,
MACRO -> Macro,
BYNAMEPARAM -> ((Method, Covariant)), // Dotty deviation: no auto-tupling
LABEL -> ((Label, Contravariant)), // Dotty deviation: no auto-tupling
BYNAMEPARAM -> (Method, Covariant),
LABEL -> (Label, Contravariant),
ABSOVERRIDE -> AbsOverride,
LOCAL -> Local,
JAVA -> JavaDefined,
SYNTHETIC -> Synthetic,
STABLE -> Stable,
STATIC -> Static,
CASEACCESSOR -> CaseAccessor,
DEFAULTPARAM -> ((DefaultParameterized, Trait)), // Dotty deviation: no auto-tupling
DEFAULTPARAM -> (DefaultParameterized, Trait),
BRIDGE -> Bridge,
ACCESSOR -> Accessor,
SUPERACCESSOR -> SuperAccessor,
PARAMACCESSOR -> ParamAccessor,
MODULEVAR -> Scala2ModuleVar,
LAZY -> Lazy,
MIXEDIN -> ((MixedIn, Scala2Existential)), // Dotty deviation: no auto-tupling
MIXEDIN -> (MixedIn, Scala2Existential),
EXPANDEDNAME -> ExpandedName,
IMPLCLASS -> ((Scala2PreSuper, ImplClass)), // Dotty deviation: no auto-tupling
IMPLCLASS -> (Scala2PreSuper, ImplClass),
SPECIALIZED -> Specialized,
DEFAULTINIT -> DefaultInit,
VBRIDGE -> VBridge,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ trait UniqueMessagePositions extends Reporter {
override def isHidden(d: Diagnostic)(implicit ctx: Context): Boolean =
super.isHidden(d) || {
d.pos.exists && {
positions get ((ctx.source, d.pos.point)) match { // Dotty deviation: no autotupling
positions get (ctx.source, d.pos.point) match {
case Some(s) if s.level >= d.severity.level => true
case _ => positions((ctx.source, d.pos.point)) = d.severity; false
}
Expand Down
16 changes: 14 additions & 2 deletions src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,17 @@ trait Applications extends Compatibility { self: Typer =>
def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = {

def realApply(implicit ctx: Context): Tree = track("realApply") {
val proto = new FunProto(tree.args, pt, this)
var proto = new FunProto(tree.args, pt, this)
val fun1 = typedExpr(tree.fun, proto)

// Warning: The following line is dirty and fragile. We record that auto-tupling was demanded as
// a side effect in adapt. If it was, we assume the tupled proto-type in the rest of the application.
// This crucially relies on he fact that `proto` is used only in a single call of `adapt`,
// otherwise we would get possible cross-talk between different `adapt` calls using the same
// prototype. A cleaner alternative would be to return a modified prototype from `adapt` together with
// a modified tree but this would be more convoluted and less efficient.
if (proto.isTupled) proto = proto.tupled

methPart(fun1).tpe match {
case funRef: TermRef =>
tryEither { implicit ctx =>
Expand Down Expand Up @@ -677,7 +686,10 @@ trait Applications extends Compatibility { self: Typer =>
var argTypes = unapplyArgs(unapplyApp.tpe)
for (argType <- argTypes) assert(!argType.isInstanceOf[TypeBounds], unapplyApp.tpe.show)
val bunchedArgs = argTypes match {
case argType :: Nil if argType.isRepeatedParam => untpd.SeqLiteral(args) :: Nil
case argType :: Nil =>
if (argType.isRepeatedParam) untpd.SeqLiteral(args) :: Nil
else if (args.lengthCompare(1) > 0) untpd.Tuple(args) :: Nil
else args
case _ => args
}
if (argTypes.length != bunchedArgs.length) {
Expand Down
14 changes: 14 additions & 0 deletions src/dotty/tools/dotc/typer/ProtoTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,20 @@ object ProtoTypes {
typer.adapt(targ, formal)
}

private var myTupled: Type = NoType

/** The same proto-type but with all arguments combined in a single tuple */
def tupled: FunProto = myTupled match {
case pt: FunProto =>
pt
case _ =>
myTupled = new FunProto(untpd.Tuple(args) :: Nil, resultType, typer)
tupled
}

/** Somebody called the `tupled` method of this prototype */
def isTupled: Boolean = myTupled.isInstanceOf[FunProto]

override def toString = s"FunProto(${args mkString ","} => $resultType)"

def map(tm: TypeMap)(implicit ctx: Context): FunProto =
Expand Down
10 changes: 8 additions & 2 deletions src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1069,8 +1069,14 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
}

def adaptToArgs(wtp: Type, pt: FunProto) = wtp match {
case _: MethodType | _: PolyType => tree
def adaptToArgs(wtp: Type, pt: FunProto): Tree = wtp match {
case _: MethodType | _: PolyType =>
def isUnary = wtp.firstParamTypes match {
case ptype :: Nil => !ptype.isRepeatedParam
case _ => false
}
if (pt.args.lengthCompare(1) > 0 && isUnary) adaptToArgs(wtp, pt.tupled)
else tree
case _ => tryInsertApply(tree, pt) {
val more = tree match {
case Apply(_, _) => " more"
Expand Down