Skip to content
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

Remove Two Warts: Auto-Tupling and Multi-Parameter Infix Operations #4311

Closed
wants to merge 7 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
18 changes: 8 additions & 10 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -776,18 +776,16 @@ object desugar {
* ==> r.op(l) if op is right-associative
*/
def binop(left: Tree, op: Ident, right: Tree)(implicit ctx: Context): Apply = {
def assignToNamedArg(arg: Tree) = arg match {

def assignToNamedArg(arg: Tree): Tree = arg match {
case Assign(Ident(name), rhs) => cpy.NamedArg(arg)(name, rhs)
case Parens(arg1) => untpd.cpy.Parens(arg)(assignToNamedArg(arg1))
case Tuple(args) => untpd.cpy.Tuple(arg)(args.mapConserve(assignToNamedArg))
case _ => arg
}
def makeOp(fn: Tree, arg: Tree, selectPos: Position) = {
val args: List[Tree] = arg match {
case Parens(arg) => assignToNamedArg(arg) :: Nil
case Tuple(args) => args.mapConserve(assignToNamedArg)
case _ => arg :: Nil
}
Apply(Select(fn, op.name).withPos(selectPos), args)
}

def makeOp(fn: Tree, arg: Tree, selectPos: Position) =
Apply(Select(fn, op.name).withPos(selectPos), assignToNamedArg(arg))

if (isLeftAssoc(op.name))
makeOp(left, right, Position(left.pos.start, op.pos.end, op.pos.start))
Expand Down Expand Up @@ -1216,7 +1214,7 @@ object desugar {
*/
private object IdPattern {
def unapply(tree: Tree)(implicit ctx: Context): Option[VarInfo] = tree match {
case id: Ident => Some(id, TypeTree())
case id: Ident => Some((id, TypeTree()))
case Typed(id: Ident, tpt) => Some((id, tpt))
case _ => None
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
object closure {
def unapply(tree: Tree): Option[(List[Tree], Tree, Tree)] = tree match {
case Block(_, expr) => unapply(expr)
case Closure(env, meth, tpt) => Some(env, meth, tpt)
case Closure(env, meth, tpt) => Some((env, meth, tpt))
case Typed(expr, _) => unapply(expr)
case _ => None
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1009,8 +1009,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
/** An extractor that pulls out type arguments */
object MaybePoly {
def unapply(tree: Tree): Option[(Tree, List[Tree])] = tree match {
case TypeApply(tree, targs) => Some(tree, targs)
case _ => Some(tree, Nil)
case TypeApply(tree, targs) => Some((tree, targs))
case _ => Some((tree, Nil))
}
}

Expand Down
23 changes: 19 additions & 4 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,6 @@ class Definitions {
lazy val ArrayModuleType = ctx.requiredModuleRef("scala.Array")
def ArrayModule(implicit ctx: Context) = ArrayModuleType.symbol.moduleClass.asClass


lazy val UnitType: TypeRef = valueTypeRef("scala.Unit", BoxedUnitType, java.lang.Void.TYPE, UnitEnc, nme.specializedTypeNames.Void)
def UnitClass(implicit ctx: Context) = UnitType.symbol.asClass
def UnitModuleClass(implicit ctx: Context) = UnitType.symbol.asClass.linkedClass
Expand Down Expand Up @@ -776,7 +775,7 @@ class Definitions {
if (isFunctionClass(tsym)) {
val targs = ft.dealias.argInfos
if (targs.isEmpty) None
else Some(targs.init, targs.last, tsym.name.isImplicitFunction, tsym.name.isErasedFunction)
else Some((targs.init, targs.last, tsym.name.isImplicitFunction, tsym.name.isErasedFunction))
}
else None
}
Expand Down Expand Up @@ -821,8 +820,8 @@ class Definitions {
case ArrayOf(elemtp) =>
def recur(elemtp: Type): Option[(Type, Int)] = elemtp.dealias match {
case TypeBounds(lo, hi) => recur(hi)
case MultiArrayOf(finalElemTp, n) => Some(finalElemTp, n + 1)
case _ => Some(elemtp, 1)
case MultiArrayOf(finalElemTp, n) => Some((finalElemTp, n + 1))
case _ => Some((elemtp, 1))
}
recur(elemtp)
case _ =>
Expand Down Expand Up @@ -879,6 +878,22 @@ class Definitions {
name.length > prefix.length &&
name.drop(prefix.length).forall(_.isDigit))

// Currently unused:
/** If `cls` has name s"$prefix$digits" where $digits is a valid integer, that
* that integer, otherwise -1.
*/
def arity(cls: Symbol, prefix: String): Int =
scalaClassName(cls).applySimple(-1) { name =>
if (name.startsWith(prefix)) {
val digits = name.drop(prefix.length)
if (!digits.isEmpty && digits.forall(_.isDigit))
try digits.toString.toInt
catch { case ex: NumberFormatException => -1 }
else -1
}
else -1
}

def isBottomClass(cls: Symbol) =
cls == NothingClass || cls == NullClass
def isBottomType(tp: Type) =
Expand Down
12 changes: 6 additions & 6 deletions compiler/src/dotty/tools/dotc/core/Denotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ object Denotations {
val r = mergeDenot(this, that)
if (r.exists) r else MultiDenotation(this, that)
case that @ MultiDenotation(denot1, denot2) =>
this & (denot1, pre) & (denot2, pre)
this .& (denot1, pre) .& (denot2, pre)
}
}

Expand Down Expand Up @@ -634,11 +634,11 @@ object Denotations {
else if (!that.exists) that
else this match {
case denot1 @ MultiDenotation(denot11, denot12) =>
denot1.derivedUnionDenotation(denot11 | (that, pre), denot12 | (that, pre))
denot1.derivedUnionDenotation(denot11 .| (that, pre), denot12 .| (that, pre))
case denot1: SingleDenotation =>
that match {
case denot2 @ MultiDenotation(denot21, denot22) =>
denot2.derivedUnionDenotation(this | (denot21, pre), this | (denot22, pre))
denot2.derivedUnionDenotation(this .| (denot21, pre), this .| (denot22, pre))
case denot2: SingleDenotation =>
unionDenot(denot1, denot2)
}
Expand Down Expand Up @@ -1180,7 +1180,7 @@ object Denotations {
final case class DenotUnion(denot1: PreDenotation, denot2: PreDenotation) extends MultiPreDenotation {
def exists = true
def toDenot(pre: Type)(implicit ctx: Context) =
(denot1 toDenot pre) & (denot2 toDenot pre, pre)
(denot1 toDenot pre) .& (denot2 toDenot pre, pre)
def containsSym(sym: Symbol) =
(denot1 containsSym sym) || (denot2 containsSym sym)
type AsSeenFromResult = PreDenotation
Expand Down Expand Up @@ -1218,8 +1218,8 @@ object Denotations {
def hasAltWith(p: SingleDenotation => Boolean): Boolean =
denot1.hasAltWith(p) || denot2.hasAltWith(p)
def accessibleFrom(pre: Type, superAccess: Boolean)(implicit ctx: Context): Denotation = {
val d1 = denot1 accessibleFrom (pre, superAccess)
val d2 = denot2 accessibleFrom (pre, superAccess)
val d1 = denot1.accessibleFrom(pre, superAccess)
val d2 = denot2.accessibleFrom(pre, superAccess)
if (!d1.exists) d2
else if (!d2.exists) d1
else derivedUnionDenotation(d1, d2)
Expand Down
15 changes: 14 additions & 1 deletion compiler/src/dotty/tools/dotc/core/NameOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ object NameOps {
case _ => false
}

def applySimple[T](default: T)(f: SimpleName => T): T = name match {
case name: SimpleName => f(name)
case name: TypeName => name.toTermName.applySimple(default)(f)
case _ => default
}

def likeSpaced(n: PreName): N =
(if (name.isTermName) n.toTermName else n.toTypeName).asInstanceOf[N]

Expand All @@ -81,6 +87,13 @@ object NameOps {
}
}

/** Is name an operator name that does not start with a letter or `_` or `$`? */
def isSymbolic = name match {
case name: SimpleName =>
!Chars.isIdentifierStart(name.head) && NameTransformer.encode(name) != name
case _ => false
}

def isOpAssignmentName: Boolean = name match {
case raw.NE | raw.LE | raw.GE | EMPTY =>
false
Expand Down Expand Up @@ -110,7 +123,7 @@ object NameOps {

/** If flags is a ModuleClass but not a Package, add module class suffix */
def adjustIfModuleClass(flags: Flags.FlagSet): N = likeSpaced {
if (flags is (ModuleClass, butNot = Package)) name.asTypeName.moduleClassName
if (flags.is(ModuleClass, butNot = Package)) name.asTypeName.moduleClassName
else name.toTermName.exclude(AvoidClashName)
}

Expand Down
12 changes: 6 additions & 6 deletions compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ object SymDenotations {
* in `butNot` are set?
*/
final def is(fs: FlagSet, butNot: FlagSet)(implicit ctx: Context) =
(if (isCurrent(fs) && isCurrent(butNot)) myFlags else flags) is (fs, butNot)
(if (isCurrent(fs) && isCurrent(butNot)) myFlags else flags).is(fs, butNot)

/** Has this denotation all of the flags in `fs` set? */
final def is(fs: FlagConjunction)(implicit ctx: Context) =
Expand All @@ -200,7 +200,7 @@ object SymDenotations {
* in `butNot` are set?
*/
final def is(fs: FlagConjunction, butNot: FlagSet)(implicit ctx: Context) =
(if (isCurrent(fs) && isCurrent(butNot)) myFlags else flags) is (fs, butNot)
(if (isCurrent(fs) && isCurrent(butNot)) myFlags else flags).is(fs, butNot)

/** The type info.
* The info is an instance of TypeType iff this is a type denotation
Expand Down Expand Up @@ -457,13 +457,13 @@ object SymDenotations {
/** Is symbol known to not exist, or potentially not completed yet? */
final def unforcedIsAbsent(implicit ctx: Context): Boolean =
myInfo == NoType ||
(this is (ModuleVal, butNot = Package)) && moduleClass.unforcedIsAbsent
(this.is(ModuleVal, butNot = Package)) && moduleClass.unforcedIsAbsent

/** Is symbol known to not exist? */
final def isAbsent(implicit ctx: Context): Boolean = {
ensureCompleted()
(myInfo `eq` NoType) ||
(this is (ModuleVal, butNot = Package)) && moduleClass.isAbsent
(this.is(ModuleVal, butNot = Package)) && moduleClass.isAbsent
}

/** Is this symbol the root class or its companion object? */
Expand Down Expand Up @@ -921,7 +921,7 @@ object SymDenotations {
* A local dummy owner is mapped to the primary constructor of the class.
*/
final def enclosingMethod(implicit ctx: Context): Symbol =
if (this is (Method, butNot = Label)) symbol
if (this.is(Method, butNot = Label)) symbol
else if (this.isClass) primaryConstructor
else if (this.exists) owner.enclosingMethod
else NoSymbol
Expand Down Expand Up @@ -1352,7 +1352,7 @@ object SymDenotations {

// ----- denotation fields and accessors ------------------------------

if (initFlags is (Module, butNot = Package))
if (initFlags.is(Module, butNot = Package))
assert(name.is(ModuleClassName), s"module naming inconsistency: ${name.debugString}")

/** The symbol asserted to have type ClassSymbol */
Expand Down
9 changes: 3 additions & 6 deletions compiler/src/dotty/tools/dotc/core/TypeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import util.Property
import collection.mutable
import ast.tpd._
import reporting.trace
import reporting.diagnostic.Message
import reporting.diagnostic.{Message, NoExplanation}

trait TypeOps { this: Context => // TODO: Make standalone object.

Expand Down Expand Up @@ -313,10 +313,6 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
hasImport(ctx.withPhase(ctx.typerPhase)) || hasOption
}

/** Is auto-tupling enabled? */
def canAutoTuple =
!featureEnabled(defn.LanguageModuleClass, nme.noAutoTupling)

def scala2Mode =
featureEnabled(defn.LanguageModuleClass, nme.Scala2)

Expand All @@ -325,7 +321,8 @@ trait TypeOps { this: Context => // TODO: Make standalone object.

def testScala2Mode(msg: => Message, pos: Position, rewrite: => Unit = ()) = {
if (scala2Mode) {
migrationWarning(msg, pos)
migrationWarning(
new NoExplanation(msg.msg ++ "\nThis can be fixed automatically using -rewrite"), pos)
rewrite
}
scala2Mode
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ object Types {
else pdenot.info recoverable_& rinfo
pdenot.asSingleDenotation.derivedSingleDenotation(pdenot.symbol, jointInfo)
} else {
pdenot & (
pdenot .& (
new JointRefDenotation(NoSymbol, rinfo, Period.allInRun(ctx.runId)),
pre,
safeIntersection = ctx.pendingMemberSearches.contains(name))
Expand Down Expand Up @@ -643,7 +643,7 @@ object Types {
}

def goAnd(l: Type, r: Type) = {
go(l) & (go(r), pre, safeIntersection = ctx.pendingMemberSearches.contains(name))
go(l) .& (go(r), pre, safeIntersection = ctx.pendingMemberSearches.contains(name))
}

val recCount = ctx.findMemberCount
Expand Down Expand Up @@ -980,7 +980,7 @@ object Types {
case res => res
}
case tp @ AndType(tp1, tp2) =>
tp derived_& (tp1.widenUnion, tp2.widenUnion)
tp.derived_&(tp1.widenUnion, tp2.widenUnion)
case tp: RefinedType =>
tp.derivedRefinedType(tp.parent.widenUnion, tp.refinedName, tp.refinedInfo)
case tp: RecType =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ trait UniqueMessagePositions extends Reporter {
m.pos.exists && {
var shouldHide = false
for (pos <- m.pos.start to m.pos.end) {
positions get (ctx.source, pos) match {
positions.get((ctx.source, pos)) match {
case Some(level) if level >= m.level => shouldHide = true
case _ => positions((ctx.source, pos)) = m.level
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/Constructors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ class Constructors extends MiniPhase with IdentityDenotTransformer { thisPhase =
override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
case Ident(_) | Select(This(_), _) =>
var sym = tree.symbol
if (sym is (ParamAccessor, butNot = Mutable)) sym = sym.subst(accessors, paramSyms)
if (sym.is(ParamAccessor, butNot = Mutable)) sym = sym.subst(accessors, paramSyms)
if (sym.owner.isConstructor) ref(sym).withPos(tree.pos) else tree
case Apply(fn, Nil) =>
val fn1 = transform(fn)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/Erasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ object Erasure {
/** Besides normal typing, this method collects all arguments
* to a compacted function into a single argument of array type.
*/
override def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = {
override def typedApply(tree: untpd.Apply, pt: Type, scala2InfixOp: Boolean)(implicit ctx: Context): Tree = {
val Apply(fun, args) = tree
if (fun.symbol == defn.cbnArg)
typedUnadapted(args.head, pt)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class ParamForwarding(thisPhase: DenotTransformer) {
* }
*/
val candidate = sym.owner.asClass.superClass
.info.decl(sym.name).suchThat(_ is (ParamAccessor, butNot = Mutable)).symbol
.info.decl(sym.name).suchThat(_.is(ParamAccessor, butNot = Mutable)).symbol
if (candidate.isAccessibleFrom(currentClass.thisType, superAccess = true)) candidate
else if (candidate.exists) inheritedAccessor(candidate)
else NoSymbol
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class SuperAccessors(thisPhase: DenotTransformer) {
// SI-4989 Check if an intermediate class between `clazz` and `sym.owner` redeclares the method as abstract.
for (intermediateClass <- clazz.info.baseClasses.tail.takeWhile(_ != sym.owner)) {
val overriding = sym.overridingSymbol(intermediateClass)
if ((overriding is (Deferred, butNot = AbsOverride)) && !(overriding.owner is Trait))
if (overriding.is(Deferred, butNot = AbsOverride) && !overriding.owner.is(Trait))
ctx.error(
s"${sym.showLocated} cannot be directly accessed from ${clazz} because ${overriding.owner} redeclares it as abstract",
sel.pos)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ abstract class TransformByNameApply extends MiniPhase { thisPhase: DenotTransfor

/** If denotation had an ExprType before, it now gets a function type */
protected def exprBecomesFunction(symd: SymDenotation)(implicit ctx: Context) =
(symd is Param) || (symd is (ParamAccessor, butNot = Method))
symd.is(Param) || symd.is(ParamAccessor, butNot = Method)

protected def isByNameRef(tree: Tree)(implicit ctx: Context) = {
val origDenot = originalDenotation(tree)
Expand Down
Loading