diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index ef8226229a7e..c0508c81d168 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -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)) @@ -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 } diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index d1e91799f31a..c50d154f2827 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -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 } diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index a3be000dbbc2..3fbb091bb702 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -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)) } } diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 95c5aa94dd37..f5eefa75c57c 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -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 @@ -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 } @@ -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 _ => @@ -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) = diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index 0443f346476e..1e6b8bf155f4 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -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) } } @@ -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) } @@ -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 @@ -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) diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala index 584139248959..7a99f20bb2c9 100644 --- a/compiler/src/dotty/tools/dotc/core/NameOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala @@ -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] @@ -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 @@ -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) } diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 3064078ed403..550cb47427d3 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -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) = @@ -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 @@ -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? */ @@ -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 @@ -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 */ diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 498660c9d82b..0ae384c500bc 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -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. @@ -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) @@ -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 diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 01144c3ddbfd..8cb791f066c8 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -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)) @@ -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 @@ -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 => diff --git a/compiler/src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala b/compiler/src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala index 6fd971c2a4c0..e63f685632ea 100644 --- a/compiler/src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala +++ b/compiler/src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala @@ -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 } diff --git a/compiler/src/dotty/tools/dotc/transform/Constructors.scala b/compiler/src/dotty/tools/dotc/transform/Constructors.scala index 89a3d16772a4..6f25948aadb6 100644 --- a/compiler/src/dotty/tools/dotc/transform/Constructors.scala +++ b/compiler/src/dotty/tools/dotc/transform/Constructors.scala @@ -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) diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index d0f7daa2cadc..fa3d10a645e1 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -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) diff --git a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala index b876a3a9b47e..1e2824027f72 100644 --- a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala +++ b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala @@ -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 diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala index 1435a5aaf099..9d90683184f3 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -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) diff --git a/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala b/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala index c0825c7e8bea..e34ba59a7523 100644 --- a/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala +++ b/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala @@ -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) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 7d77920e8741..5707f77ef20e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -23,6 +23,7 @@ import StdNames._ import NameKinds.DefaultGetterName import ProtoTypes._ import Inferencing._ +import rewrite.Rewrites.patch import collection.mutable import config.Printers.{overload, typr, unapp} @@ -242,7 +243,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => def success = ok protected def methodType = methType.asInstanceOf[MethodType] - private def methString: String = i"${methRef.symbol}: ${methType.show}" + private def methString: String = i"${methRef.symbol.showLocated}: ${methType.show}" /** Re-order arguments to correctly align named arguments */ def reorder[T >: Untyped](args: List[Trees.Tree[T]]): List[Trees.Tree[T]] = { @@ -669,10 +670,19 @@ trait Applications extends Compatibility { self: Typer with Dynamic => * or, if application is an operator assignment, also an `Assign` or * Block node. */ - def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = { - + def typedApply(tree: untpd.Apply, pt: Type, scala2InfixOp: Boolean = false)(implicit ctx: Context): Tree = { def realApply(implicit ctx: Context): Tree = track("realApply") { - val originalProto = new FunProto(tree.args, IgnoredProto(pt), this)(argCtx(tree)) + var originalProto = new FunProto(tree.args, IgnoredProto(pt), this)(argCtx(tree)) + + // In an infix operation `x op (y, z)` under Scala-2 mode, rewrite tuple on the + // right hand side to multi-parameters, i.e `x.op(y, z)`, relying on auto-tupling + // to revert this if `op` takes a single argument. + tree.args match { + case untpd.Tuple(elems) :: Nil if scala2InfixOp => + originalProto = new FunProto(elems, IgnoredProto(pt), this)(argCtx(tree)) + originalProto.scala2InfixOp = true + case _ => + } val fun1 = typedExpr(tree.fun, originalProto) // Warning: The following lines are dirty and fragile. We record that auto-tupling was demanded as @@ -682,7 +692,41 @@ trait Applications extends Compatibility { self: Typer with Dynamic => // 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. - val proto = if (originalProto.isTupled) originalProto.tupled else originalProto + // All of this is provisional in the long run, since it is only needed under Scala-2 mode. + val proto = + if (originalProto.isTupled) originalProto.tupled + else { + // If we see a multi-parameter infix operation `x op (y, z)` under Scala-2 mode, + // issue a migration warning and propose a rewrite to `x .op (y, z)` (or + // `(x) .op (y, z)` is `x` is itself an infix operation) where this is possible. + // Not possible are rewrites of operator assignments and right-associative operators. + tree.fun match { + case sel @ Select(qual, opName) + if originalProto.scala2InfixOp && !fun1.tpe.widen.isErroneous => + val opEndOffset = sel.pos.point + opName.toString.length + val isOpAssign = ctx.source(opEndOffset) == '=' + val isRightAssoc = !isLeftAssoc(opName) + val addendum = + if (isOpAssign) "\nThis requires a manual rewrite since it is part of an operator assignment." + else if (isRightAssoc) "\nThis requires a manual rewrite since the operator is right-associative." + else "\nThis can be fixed automatically using -rewrite." + ctx.migrationWarning( + em"""infix operator takes exactly one argument, + |use method call syntax with `.` instead.$addendum""", fun1.pos) + val Select(qual, _) = tree.fun + if (!isOpAssign && !isRightAssoc) { + patch(Position(sel.pos.point), ".") + qual match { + case qual: untpd.InfixOp => + patch(qual.pos.startPos, "(") + patch(qual.pos.endPos, ")") + case _ => + } + } + case _ => + } + originalProto + } // If some of the application's arguments are function literals without explicitly declared // parameter types, relate the normalized result type of the application with the @@ -750,12 +794,25 @@ trait Applications extends Compatibility { self: Typer with Dynamic => * { val xs = es; e' = e' + args } */ def typedOpAssign(implicit ctx: Context): Tree = track("typedOpAssign") { - val Apply(Select(lhs, name), rhss) = tree + val Apply(sel @ Select(lhs, name), rhss) = tree val lhs1 = typedExpr(lhs) val liftedDefs = new mutable.ListBuffer[Tree] val lhs2 = untpd.TypedSplice(LiftComplex.liftAssigned(liftedDefs, lhs1)) - val assign = untpd.Assign(lhs2, - untpd.Apply(untpd.Select(lhs2, name.asSimpleName.dropRight(1)), rhss)) + val opName = name.asSimpleName.dropRight(1) + + // If original operation was an infix operation under Scala-2 mode, generate + // again an infix operation insteadof an application, so that the logic does + // the right thing for migrating from auto-tupling and multi-parameter infix ops. + val app = rhss match { + case (rhs: untpd.Tuple) :: Nil if scala2InfixOp => + val opEndOffset = sel.pos.point + opName.length + assert(ctx.source(opEndOffset) == '=') + val op = untpd.Ident(opName).withPos(Position(sel.pos.point, opEndOffset)) + untpd.InfixOp(lhs2, op, rhs) + case _ => + untpd.Apply(untpd.Select(lhs2, opName), rhss) + } + val assign = untpd.Assign(lhs2, app) wrapDefs(liftedDefs, typed(assign)) } @@ -980,10 +1037,12 @@ trait Applications extends Compatibility { self: Typer with Dynamic => val (regularArgs, varArgs) = args.splitAt(argTypes.length - 1) regularArgs :+ untpd.SeqLiteral(varArgs, untpd.TypeTree()).withPos(tree.pos) } - else if (argTypes.lengthCompare(1) == 0 && args.lengthCompare(1) > 0 && ctx.canAutoTuple) - untpd.Tuple(args) :: Nil - else - args + else argTypes match { + case argType :: Nil if args.lengthCompare(1) > 0 && canAutoTuple(args) => + untpd.Tuple(args) :: Nil + case _ => + args + } if (argTypes.length != bunchedArgs.length) { ctx.error(UnapplyInvalidNumberOfArguments(qual, argTypes), tree.pos) argTypes = argTypes.take(args.length) ++ diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 698fdaff0c15..13250d2b2c16 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -850,6 +850,29 @@ trait Checking { checkEnumCaseRefsLegal(stat, enumContext) stats } + + /** `tp` refers to a method with exactly one parameter in its first parameter list. + * If `tp` is overloaded, all alternatives are unary in that sense. + */ + def isUnary(tp: Type)(implicit ctx: Context): Boolean = tp match { + case tp: MethodicType => + tp.firstParamTypes match { + case ptype :: Nil => !ptype.isRepeatedParam + case _ => false + } + case tp: TermRef => + tp.denot.alternatives.forall(alt => isUnary(alt.info)) + case _ => + false + } + + /** Under Scala-2 mode, issue a migration warning for a symbolic method that is + * not unary. + */ + def checkSymbolicUnary(sym: Symbol)(implicit ctx: Context): Unit = + if (sym.name.isSymbolic && !isUnary(sym.info) && ctx.scala2Mode) + ctx.migrationWarning(i"""symbolic operator `${sym.name}` should take exactly one parameter, + |otherwise it cannot be used in infix position.""", sym.pos) } trait ReChecking extends Checking { @@ -877,4 +900,5 @@ trait NoChecking extends ReChecking { override def checkCaseInheritance(parentSym: Symbol, caseCls: ClassSymbol, pos: Position)(implicit ctx: Context) = () override def checkNoForwardDependencies(vparams: List[ValDef])(implicit ctx: Context): Unit = () override def checkMembersOK(tp: Type, pos: Position)(implicit ctx: Context): Type = tp + override def checkSymbolicUnary(sym: Symbol)(implicit ctx: Context): Unit = () } diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 49a507e0994c..80aec515be66 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -564,13 +564,13 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) { } } - override def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context) = + override def typedApply(tree: untpd.Apply, pt: Type, scala2InfixOp: Boolean)(implicit ctx: Context) = tree.asInstanceOf[tpd.Tree] match { case Apply(Select(InlineableArg(closure(_, fn, _)), nme.apply), args) => inlining.println(i"reducing $tree with closure $fn") typed(fn.appliedToArgs(args), pt) case _ => - super.typedApply(tree, pt) + super.typedApply(tree, pt, scala2InfixOp) } } } diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 78c9d111cf9e..f1a5a089b258 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1029,7 +1029,7 @@ class Namer { typer: Typer => def moduleValSig(sym: Symbol)(implicit ctx: Context): Type = { val clsName = sym.name.moduleClassName val cls = ctx.denotNamed(clsName) suchThat (_ is ModuleClass) - ctx.owner.thisType select (clsName, cls) + ctx.owner.thisType.select(clsName, cls) } /** The type signature of a ValDef or DefDef diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index f06df5d03d74..9248edde5c4a 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -288,6 +288,11 @@ object ProtoTypes { def typeOfArg(arg: untpd.Tree)(implicit ctx: Context): Type = myTypedArg(arg).tpe + // `scala2InfixOp` and `tupled` only needed for Scala-2 compatibility and migration + + /** FunProto applies to an infix operation under -language:Scala2 */ + var scala2InfixOp = false + private[this] var myTupled: Type = NoType /** The same proto-type but with all arguments combined in a single tuple */ diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 431721dc44e6..24eea10ef8cd 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -151,7 +151,7 @@ class Typer extends Namer def qualifies(denot: Denotation): Boolean = reallyExists(denot) && !(pt.isInstanceOf[UnapplySelectionProto] && - (denot.symbol is (Method, butNot = Accessor))) && + (denot.symbol.is(Method, butNot = Accessor))) && !(denot.symbol is PackageClass) /** Find the denotation of enclosing `name` in given context `ctx`. @@ -1434,6 +1434,8 @@ class Typer extends Namer for (param <- tparams1 ::: vparamss1.flatten) checkRefsLegal(param, sym.owner, (name, sym) => sym.is(TypeParam), "secondary constructor") + checkSymbolicUnary(sym) + assignType(cpy.DefDef(ddef)(name, tparams1, vparamss1, tpt1, rhs1), sym) //todo: make sure dependent method types do not depend on implicits or by-name params } @@ -1707,7 +1709,7 @@ class Typer extends Namer */ def typedInfixOp(tree: untpd.InfixOp, pt: Type)(implicit ctx: Context): Tree = { val untpd.InfixOp(l, op, r) = tree - val app = typedApply(desugar.binop(l, op, r), pt) + val app = typedApply(desugar.binop(l, op, r), pt, scala2InfixOp = ctx.scala2Mode) if (untpd.isLeftAssoc(op.name)) app else { val defs = new mutable.ListBuffer[Tree] @@ -2032,6 +2034,17 @@ class Typer extends Namer } } + def canAutoTuple(args: List[untpd.Tree])(implicit ctx: Context): Boolean = { + val pos = Position(args.map(_.pos.start).min, args.map(_.pos.end).max) + ctx.testScala2Mode( + i"""auto-tupling is no longer supported, + |arguments now need to be enclosed in parentheses (...).""", + pos, { patch(pos.startPos, "("); patch(pos.endPos, ")") }) + } + + def takesAutoTupledArgs(tp: Type, pt: FunProto)(implicit ctx: Context): Boolean = + pt.args.lengthCompare(1) > 0 && isUnary(tp) && (pt.scala2InfixOp || canAutoTuple(pt.args)) + /** Perform the following adaptations of expression, pattern or type `tree` wrt to * given prototype `pt`: * (1) Resolve overloading @@ -2119,24 +2132,10 @@ class Typer extends Namer } } - def isUnary(tp: Type): Boolean = tp match { - case tp: MethodicType => - tp.firstParamTypes match { - case ptype :: Nil => !ptype.isRepeatedParam - case _ => false - } - case tp: TermRef => - tp.denot.alternatives.forall(alt => isUnary(alt.info)) - case _ => - false - } - def adaptToArgs(wtp: Type, pt: FunProto): Tree = wtp match { case _: MethodOrPoly => - if (pt.args.lengthCompare(1) > 0 && isUnary(wtp) && ctx.canAutoTuple) - adapt(tree, pt.tupled, locked) - else - tree + if (takesAutoTupledArgs(wtp, pt)) adapt(tree, pt.tupled, locked) + else tree case _ => tryInsertApplyOrImplicit(tree, pt, locked) { errorTree(tree, MethodDoesNotTakeParameters(tree, methPart(tree).tpe)(err)) } @@ -2499,10 +2498,9 @@ class Typer extends Namer case tp: FlexType => ensureReported(tp) tree - case ref: TermRef => + case ref: TermRef => // this case can happen in case tree.tpe is overloaded pt match { - case pt: FunProto - if pt.args.lengthCompare(1) > 0 && isUnary(ref) && ctx.canAutoTuple => + case pt: FunProto if takesAutoTupledArgs(ref, pt) => adapt(tree, pt.tupled, locked) case _ => adaptOverloaded(ref) diff --git a/compiler/src/dotty/tools/dotc/util/SimpleIdentityMap.scala b/compiler/src/dotty/tools/dotc/util/SimpleIdentityMap.scala index bdbba5605141..4606499fe211 100644 --- a/compiler/src/dotty/tools/dotc/util/SimpleIdentityMap.scala +++ b/compiler/src/dotty/tools/dotc/util/SimpleIdentityMap.scala @@ -22,7 +22,7 @@ abstract class SimpleIdentityMap[K <: AnyRef, +V >: Null <: AnyRef] extends (K = def toList: List[(K, V)] = map2((k, v) => (k, v)) override def toString = { def assocToString(key: K, value: V) = s"$key -> $value" - map2(assocToString) mkString ("(", ", ", ")") + map2(assocToString).mkString("(", ", ", ")") } } diff --git a/compiler/src/dotty/tools/repl/terminal/filters/ReadlineFilters.scala b/compiler/src/dotty/tools/repl/terminal/filters/ReadlineFilters.scala index c619238de2d0..f106c9a19510 100644 --- a/compiler/src/dotty/tools/repl/terminal/filters/ReadlineFilters.scala +++ b/compiler/src/dotty/tools/repl/terminal/filters/ReadlineFilters.scala @@ -121,7 +121,7 @@ object ReadlineFilters { } def cutCharLeft(b: Vector[Char], c: Int) = { /* Do not edit current cut. Zsh(zle) & Bash(readline) do not edit the yank ring for Ctrl-h */ - (b patch(from = c - 1, patch = Nil, replaced = 1), c - 1) + (b .patch(from = c - 1, patch = Nil, replaced = 1), c - 1) } def cutLineLeft(b: Vector[Char], c: Int) = { diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index d91b789b4f86..c0180adfcd28 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -180,7 +180,6 @@ class CompilationTests extends ParallelTesting { compileFilesInDir("tests/neg-custom-args/allow-double-bindings", allowDoubleBindings) + compileFile("tests/neg-custom-args/i3246.scala", scala2Mode) + compileFile("tests/neg-custom-args/overrideClass.scala", scala2Mode) + - compileFile("tests/neg-custom-args/autoTuplingTest.scala", defaultOptions.and("-language:noAutoTupling")) + compileFile("tests/neg-custom-args/i1050.scala", defaultOptions.and("-strict")) + compileFile("tests/neg-custom-args/nopredef.scala", defaultOptions.and("-Yno-predef")) + compileFile("tests/neg-custom-args/noimports.scala", defaultOptions.and("-Yno-imports")) + diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index 945d5fa3efb4..829ca85d52cc 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -331,7 +331,7 @@ trait ParallelTesting extends RunnerOrchestration { self => protected def compile(files0: Array[JFile], flags0: TestFlags, suppressErrors: Boolean, targetDir: JFile): TestReporter = { - val flags = flags0 and ("-d", targetDir.getAbsolutePath) + val flags = flags0.and("-d", targetDir.getAbsolutePath) def flattenFiles(f: JFile): Array[JFile] = if (f.isDirectory) f.listFiles.flatMap(flattenFiles) @@ -400,7 +400,7 @@ trait ParallelTesting extends RunnerOrchestration { self => protected def compileFromTasty(flags0: TestFlags, suppressErrors: Boolean, targetDir: JFile): TestReporter = { val tastyOutput = new JFile(targetDir.getPath + "_from-tasty") tastyOutput.mkdir() - val flags = flags0 and ("-d", tastyOutput.getAbsolutePath) and "-from-tasty" + val flags = flags0.and("-d", tastyOutput.getAbsolutePath).and("-from-tasty") def hasTastyFileToClassName(f: JFile): String = targetDir.toPath.relativize(f.toPath).toString.dropRight(".hasTasty".length).replace('/', '.') @@ -427,8 +427,10 @@ trait ParallelTesting extends RunnerOrchestration { self => val decompilationOutput = new JFile(targetDir.getPath) decompilationOutput.mkdir() val flags = - flags0 and ("-d", decompilationOutput.getAbsolutePath) and - "-decompile" and "-pagewidth" and "80" + flags0 + .and("-d", decompilationOutput.getAbsolutePath) + .and("-decompile") + .and("-pagewidth", "80") def hasTastyFileToClassName(f: JFile): String = targetDir.toPath.relativize(f.toPath).toString.dropRight(".hasTasty".length).replace('/', '.') diff --git a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala index 845908be2e0f..0bd8d5469c58 100644 --- a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala +++ b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala @@ -49,18 +49,18 @@ object TestConfiguration { val basicDefaultOptions = checkOptions ++ noCheckOptions ++ yCheckOptions val defaultUnoptimised = TestFlags(classPath, runClassPath, basicDefaultOptions) - val defaultOptimised = defaultUnoptimised and "-optimise" + val defaultOptimised = defaultUnoptimised.and("-optimise") val defaultOptions = defaultUnoptimised val defaultRunWithCompilerOptions = defaultOptions.withRunClasspath(Jars.dottyRunWithCompiler.mkString(":")) val allowDeepSubtypes = defaultOptions without "-Yno-deep-subtypes" val allowDoubleBindings = defaultOptions without "-Yno-double-bindings" - val picklingOptions = defaultUnoptimised and ( + val picklingOptions = defaultUnoptimised.and( "-Xprint-types", "-Ytest-pickler", "-Yprint-pos", "-Yprint-pos-syms" ) - val scala2Mode = defaultOptions and "-language:Scala2" - val explicitUTF8 = defaultOptions and ("-encoding", "UTF8") - val explicitUTF16 = defaultOptions and ("-encoding", "UTF16") + val scala2Mode = defaultOptions.and("-language:Scala2") + val explicitUTF8 = defaultOptions.and("-encoding", "UTF8") + val explicitUTF16 = defaultOptions.and("-encoding", "UTF16") } diff --git a/library/src/scalaShadowing/language.scala b/library/src/scalaShadowing/language.scala index 50d2bf069c04..d1d26f77af31 100644 --- a/library/src/scalaShadowing/language.scala +++ b/library/src/scalaShadowing/language.scala @@ -29,7 +29,6 @@ package scalaShadowing * and, for dotty: * * - [[Scala2 `Scala2`] backwards compatibility mode for Scala2 - * - [[noAtoTupling `noAutoTupling`]] disable auto-tupling * * @groupname production Language Features * @groupname experimental Experimental Language Features @@ -193,9 +192,6 @@ object language { /** Where imported, a backwards compatibility mode for Scala2 is enabled */ object Scala2 - /** Where imported, auto-tupling is disabled */ - object noAutoTupling - /* Where imported loose equality using eqAny is disabled */ object strictEquality } diff --git a/tests/neg-custom-args/autoTuplingTest.scala b/tests/neg-custom-args/autoTuplingTest.scala deleted file mode 100644 index 7321a83827bb..000000000000 --- a/tests/neg-custom-args/autoTuplingTest.scala +++ /dev/null @@ -1,9 +0,0 @@ -object autoTupling { - - val x = Some(1, 2) // error when running with -language:noAutoTupling - - x match { - case Some(a, b) => a + b // error // error when running with -language:noAutoTupling - case None => - } -} diff --git a/tests/neg/autoTuplingTest.scala b/tests/neg/autoTuplingTest.scala index 92126ab5dd60..c53ff99fc571 100644 --- a/tests/neg/autoTuplingTest.scala +++ b/tests/neg/autoTuplingTest.scala @@ -1,11 +1,9 @@ -import language.noAutoTupling - object autoTuplingNeg2 { val x = Some(1, 2) // error: too many arguments for method apply: (x: A)Some[A] x match { - case Some(a, b) => a + b // error: wrong number of argument patterns for Some // error: not found: b + case Some(a, b) => a + b // error: wrong number of argument patterns for Some // error: not found: a case None => } } diff --git a/tests/neg/i1286.scala b/tests/neg/i1286.scala index 40db9ab1d46d..b2b74c41a63e 100644 --- a/tests/neg/i1286.scala +++ b/tests/neg/i1286.scala @@ -10,7 +10,6 @@ import scala.io.{ Idontexist4 => Foo } // error import scala.io.{ Idontexist5 => _ } // error import scala.language.dynamics -import scala.language.noAutoTupling import scala.language.idontexist // error object Test diff --git a/tests/neg/i2033.scala b/tests/neg/i2033.scala index b28a0d99e5be..c717bc8679e6 100644 --- a/tests/neg/i2033.scala +++ b/tests/neg/i2033.scala @@ -4,10 +4,10 @@ object Test { def check(obj: AnyRef): Unit = { val bos = new ByteArrayOutputStream() val out = new ObjectOutputStream(println) // error - val arr = bos toByteArray () + val arr = bos.toByteArray () val in = (()) val deser = () - val lhs = mutable LinkedHashSet () + val lhs = mutable.LinkedHashSet () check(lhs) } } diff --git a/tests/neg/t6920.scala b/tests/neg/t6920.scala index 9601ed8d27e6..4a135f0d2d10 100644 --- a/tests/neg/t6920.scala +++ b/tests/neg/t6920.scala @@ -6,5 +6,5 @@ class DynTest extends Dynamic { class CompilerError { val test = new DynTest - test.crushTheCompiler(a = 1, b = 2) // error + test.crushTheCompiler(a = 1, b = 2) // error // error } diff --git a/tests/pos-special/strawman-collections/CollectionStrawMan6.scala b/tests/pos-special/strawman-collections/CollectionStrawMan6.scala index a2ff42ba783e..6c2a37adfda9 100644 --- a/tests/pos-special/strawman-collections/CollectionStrawMan6.scala +++ b/tests/pos-special/strawman-collections/CollectionStrawMan6.scala @@ -651,7 +651,7 @@ object CollectionStrawMan6 extends LowPriority { } def fromIterator[B](it: Iterator[B]): LazyList[B] = - new LazyList(if (it.hasNext) Some(it.next(), fromIterator(it)) else None) + new LazyList(if (it.hasNext) Some((it.next(), fromIterator(it))) else None) } // ------------------ Decorators to add collection ops to existing types ----------------------- diff --git a/tests/pos/Map.scala b/tests/pos/Map.scala index 5178d5a862cf..b5ba3b1627a6 100644 --- a/tests/pos/Map.scala +++ b/tests/pos/Map.scala @@ -176,7 +176,7 @@ object Map extends ImmutableMapFactory[Map] { else if (key == key2) new Map4(key1, value1, key2, value, key3, value3, key4, value4) else if (key == key3) new Map4(key1, value1, key2, value2, key3, value, key4, value4) else if (key == key4) new Map4(key1, value1, key2, value2, key3, value3, key4, value) - else new HashMap + ((key1, value1), (key2, value2), (key3, value3), (key4, value4), (key, value)) + else HashMap((key1, value1), (key2, value2), (key3, value3), (key4, value4), (key, value)) def + [B1 >: B](kv: (A, B1)): Map[A, B1] = updated(kv._1, kv._2) def - (key: A): Map[A, B] = if (key == key1) new Map3(key2, value2, key3, value3, key4, value4) diff --git a/tests/pos/autoTuplingTest.scala b/tests/pos/autoTuplingTest.scala deleted file mode 100644 index 523411a1a410..000000000000 --- a/tests/pos/autoTuplingTest.scala +++ /dev/null @@ -1,9 +0,0 @@ -object autoTupling { - - val x = Some(1, 2) - - x match { - case Some(a, b) => a + b - case None => - } -} diff --git a/tests/pos/i1318.scala b/tests/pos/i1318.scala index dfb882825166..6fb6357cbe88 100644 --- a/tests/pos/i1318.scala +++ b/tests/pos/i1318.scala @@ -3,7 +3,7 @@ object Foo { case class T(i: Int) extends S(i) object T { - def unapply(s: S): Option[(Int, Int)] = Some(5, 6) + def unapply(s: S): Option[(Int, Int)] = Some((5, 6)) // def unapply(o: Object): Option[(Int, Int, Int)] = Some(5, 6, 7) } @@ -22,7 +22,7 @@ object Bar { class S(i: Int) extends T(i) object T { - def unapply(s: S): Option[(Int, Int)] = Some(5, 6) + def unapply(s: S): Option[(Int, Int)] = Some((5, 6)) // def unapply(o: Object): Option[(Int, Int, Int)] = Some(5, 6, 7) } diff --git a/tests/pos/i903.scala b/tests/pos/i903.scala index 5afb6e53010c..dc64d6d5fef3 100644 --- a/tests/pos/i903.scala +++ b/tests/pos/i903.scala @@ -17,7 +17,7 @@ object Test { } def test2 = { - val f = "".contains("", (_: Int)) // dotc: + val f = (x: Int) => "".contains(("", x)) // dotc: f.apply(0) // sandbox/eta.scala:18: error: apply is not a member of Boolean(f) // f.apply(0) diff --git a/tests/pos/t1133.scala b/tests/pos/t1133.scala index 2e4793e998f3..60c1751ad402 100644 --- a/tests/pos/t1133.scala +++ b/tests/pos/t1133.scala @@ -11,21 +11,21 @@ object Match object Extractor1 { def unapply(x: Any) = x match { - case x: String => Some(x, x + x, x + x+x, x+x, x) + case x: String => Some((x, x + x, x + x+x, x+x, x)) case _ => None } } object Extractor2 { def unapply(x: Any) = x match { - case x: String => Some(x, x + x, x + x+x) + case x: String => Some((x, x + x, x + x+x)) case _ => None } } object Extractor3 { def unapply(x: Any) = x match { - case x: String => Some(x, x, x) + case x: String => Some((x, x, x)) case _ => None } } diff --git a/tests/pos/t2913.scala b/tests/pos/t2913.scala index f91ed7b51318..b599ca6a2924 100644 --- a/tests/pos/t2913.scala +++ b/tests/pos/t2913.scala @@ -10,8 +10,6 @@ class RichA { } object TestNoAutoTupling { - import language.noAutoTupling // try with on and off - implicit def AToRichA(a: A): RichA = new RichA val a = new A @@ -52,25 +50,3 @@ object Main { () } } - -object TestWithAutoTupling { - - implicit def AToRichA(a: A): RichA = new RichA - - val a = new A - a.foo() - a.foo(1) - - a.foo("") // Without implicits, a type error regarding invalid argument types is generated at `""`. This is - // the same position as an argument, so the 'second try' typing with an Implicit View is tried, - // and AToRichA(a).foo("") is found. - // - // My reading of the spec "7.3 Views" is that `a.foo` denotes a member of `a`, so the view should - // not be triggered. - // - // But perhaps the implementation was changed to solve See https://lampsvn.epfl.ch/trac/scala/ticket/1756 - - a.foo("a", "b") // Without implicits, a type error regarding invalid arity is generated at `foo("", "")`. - // Typers#tryTypedApply:3274 only checks if the error is as the same position as `foo`, `"a"`, or `"b"`. -} - diff --git a/tests/run/collections.scala b/tests/run/collections.scala index acc2d93fff82..2b90655a1deb 100644 --- a/tests/run/collections.scala +++ b/tests/run/collections.scala @@ -18,7 +18,7 @@ object Test extends dotty.runtime.LegacyApp { println("***** "+msg+":") var s = s0 s = s + 2 - s = s + (3, 4000, 10000) + s = s.+(3, 4000, 10000) println("test1: "+sum(s)) time { s = s ++ (List.range(0, iters) map (2*)) @@ -36,7 +36,7 @@ object Test extends dotty.runtime.LegacyApp { println("***** "+msg+":") var s = s0 s = s + 2 - s = s + (3, 4000, 10000) + s = s.+(3, 4000, 10000) println("test1: "+sum(s)) time { s = s ++ (List.range(0, iters) map (2*)) @@ -54,7 +54,7 @@ object Test extends dotty.runtime.LegacyApp { println("***** "+msg+":") var s = s0 s = s + (2 -> 2) - s = s + (3 -> 3, 4000 -> 4000, 10000 -> 10000) + s = s.+(3 -> 3, 4000 -> 4000, 10000 -> 10000) println("test1: "+sum(s map (_._2))) time { s = s ++ (List.range(0, iters) map (x => x * 2 -> x * 2)) @@ -89,7 +89,7 @@ object Test extends dotty.runtime.LegacyApp { println("***** "+msg+":") var s = s0 s = s + (2 -> 2) - s = s + (3 -> 3, 4000 -> 4000, 10000 -> 10000) + s = s.+(3 -> 3, 4000 -> 4000, 10000 -> 10000) println("test1: "+sum(s map (_._2))) time { s = s ++ (List.range(0, iters) map (x => x * 2 -> x * 2)) diff --git a/tests/run/colltest1.scala b/tests/run/colltest1.scala index ab519067b6f7..612b3e8c1c79 100644 --- a/tests/run/colltest1.scala +++ b/tests/run/colltest1.scala @@ -47,8 +47,8 @@ object Test extends dotty.runtime.LegacyApp { assert(vs1 == ten) assert((ten take 5) == firstFive) assert((ten drop 5) == secondFive) - assert(ten slice (3, 3) isEmpty) - assert((ten slice (3, 6)) == List(4, 5, 6), ten slice (3, 6)) + assert(ten.slice(3, 3) isEmpty) + assert((ten.slice(3, 6)) == List(4, 5, 6), ten .slice (3, 6)) assert((ten takeWhile (_ <= 5)) == firstFive) assert((ten dropWhile (_ <= 5)) == secondFive) assert((ten span (_ <= 5)) == (firstFive, secondFive)) @@ -139,7 +139,7 @@ object Test extends dotty.runtime.LegacyApp { def setTest(empty: => Set[String]): Unit = { var s = empty + "A" + "B" + "C" - s += ("D", "E", "F") + s = s.+("D", "E", "F") s ++= List("G", "H", "I") s ++= ('J' to 'Z') map (_.toString) assert(s forall (s contains)) @@ -156,8 +156,8 @@ object Test extends dotty.runtime.LegacyApp { assert(!s.isEmpty) val s1 = s intersect empty assert(s1 == empty, s1) - def abc = empty + ("a", "b", "c") - def bc = empty + ("b", "c") + def abc = empty.+("a", "b", "c") + def bc = empty.+("b", "c") assert(bc subsetOf abc) } @@ -173,7 +173,7 @@ object Test extends dotty.runtime.LegacyApp { def mapTest(empty: => Map[String, String]) = { var m = empty + ("A" -> "A") + ("B" -> "B") + ("C" -> "C") - m += (("D" -> "D"), ("E" -> "E"), ("F" -> "F")) + m = m.+(("D" -> "D"), ("E" -> "E"), ("F" -> "F")) m ++= List(("G" -> "G"), ("H" -> "H"), ("I" -> "I")) m ++= ('J' to 'Z') map (x => (x.toString -> x.toString)) println(m.toList.sorted) diff --git a/tests/run/colltest6/CollectionStrawMan6_1.scala b/tests/run/colltest6/CollectionStrawMan6_1.scala index 4fad57154775..a380deb9d74c 100644 --- a/tests/run/colltest6/CollectionStrawMan6_1.scala +++ b/tests/run/colltest6/CollectionStrawMan6_1.scala @@ -652,7 +652,7 @@ object CollectionStrawMan6 extends LowPriority { } def fromIterator[B](it: Iterator[B]): LazyList[B] = - new LazyList(if (it.hasNext) Some(it.next(), fromIterator(it)) else None) + new LazyList(if (it.hasNext) Some((it.next(), fromIterator(it))) else None) } // ------------------ Decorators to add collection ops to existing types ----------------------- diff --git a/tests/run/iterators.scala b/tests/run/iterators.scala index 2f70abd52193..a0696eace072 100644 --- a/tests/run/iterators.scala +++ b/tests/run/iterators.scala @@ -57,8 +57,8 @@ object Test { def check_drop: Int = { val it1 = Iterator.from(0) val it2 = it1 map { 2 * _ } - val n1 = it1 drop 2 next() - val n2 = it2 drop 2 next(); + val n1 = (it1 drop 2) .next() + val n2 = (it2 drop 2) .next(); n1 + n2 } diff --git a/tests/run/runtime.scala b/tests/run/runtime.scala index 89348b294db8..3a55069c3f0c 100644 --- a/tests/run/runtime.scala +++ b/tests/run/runtime.scala @@ -65,7 +65,7 @@ object Test1Test { // {System.out.print(12); java.lang}.System.out.println(); // {System.out.print(13); java.lang.System}.out.println(); {Console.print(14); Console}.println; - {Console.print(15); (() => Console.println):(() => Unit)} apply (); + {Console.print(15); (() => Console.println):(() => Unit)} .apply (); {Console.print(16); Console.println}; {Console.print(20)}; test1.bar.System.out.println(); @@ -73,7 +73,7 @@ object Test1Test { // {System.out.print(22); test1.bar}.System.out.println(); {Console.print(23); test1.bar.System}.out.println(); {Console.print(24); test1.bar.System.out}.println(); - {Console.print(25); test1.bar.System.out.println:(() => Unit)} apply (); + {Console.print(25); test1.bar.System.out.println:(() => Unit)} .apply (); {Console.print(26); test1.bar.System.out.println()}; } diff --git a/tests/run/t2544.scala b/tests/run/t2544.scala index 6bee2f108230..ff53cf4f18d7 100644 --- a/tests/run/t2544.scala +++ b/tests/run/t2544.scala @@ -11,10 +11,10 @@ object Test { ) def main(args: Array[String]) = { - println(Foo indexWhere(_ >= 2,1)) - println(Foo.toList indexWhere(_ >= 2,1)) - println(Foo segmentLength(_ <= 3,1)) - println(Foo.toList segmentLength(_ <= 3,1)) + println(Foo .indexWhere(_ >= 2,1)) + println(Foo.toList .indexWhere(_ >= 2,1)) + println(Foo .segmentLength(_ <= 3,1)) + println(Foo.toList .segmentLength(_ <= 3,1)) lengthEquiv(Foo lengthCompare 7) lengthEquiv(Foo.toList lengthCompare 7) lengthEquiv(Foo lengthCompare 2) diff --git a/tests/run/t4813.scala b/tests/run/t4813.scala index 1146bb16ec04..29fa71c5608f 100644 --- a/tests/run/t4813.scala +++ b/tests/run/t4813.scala @@ -31,7 +31,7 @@ object Test extends dotty.runtime.LegacyApp { runTest(TreeSet(1,2,3))(_.clone) { buf => buf add 4 } // Maps - runTest(HashMap(1->1,2->2,3->3))(_.clone) { buf => buf put (4,4) } - runTest(WeakHashMap(1->1,2->2,3->3))(_.clone) { buf => buf put (4,4) } + runTest(HashMap(1->1,2->2,3->3))(_.clone) { buf => buf.put(4,4) } + runTest(WeakHashMap(1->1,2->2,3->3))(_.clone) { buf => buf.put(4,4) } } diff --git a/tests/run/t5045.scala b/tests/run/t5045.scala index 3778339aa4b1..ef992da813f5 100644 --- a/tests/run/t5045.scala +++ b/tests/run/t5045.scala @@ -6,7 +6,7 @@ object Test extends dotty.runtime.LegacyApp { import scala.util.matching.{ Regex, UnanchoredRegex } val dateP1 = """(\d\d\d\d)-(\d\d)-(\d\d)""".r.unanchored - val dateP2 = """(\d\d\d\d)-(\d\d)-(\d\d)""" r ("year", "month", "day") unanchored + val dateP2 = """(\d\d\d\d)-(\d\d)-(\d\d)""" .r ("year", "month", "day") unanchored val dateP3 = new Regex("""(\d\d\d\d)-(\d\d)-(\d\d)""", "year", "month", "day") with UnanchoredRegex val yearStr = "2011" diff --git a/tests/run/t6271.scala b/tests/run/t6271.scala index e8047a9be7f2..a7b60b1df7ba 100644 --- a/tests/run/t6271.scala +++ b/tests/run/t6271.scala @@ -21,7 +21,7 @@ object Test extends dotty.runtime.LegacyApp { } def slicedIssue = { val viewed : Iterable[Iterable[Int]] = List(List(0).view).view - val filtered = viewed flatMap { x => List( x slice (2,3) ) } + val filtered = viewed flatMap { x => List( x.slice(2,3) ) } filtered.iterator.toIterable.flatten } filterIssue diff --git a/tests/run/t6827.scala b/tests/run/t6827.scala index 43e01831c340..7c9c7057aa62 100644 --- a/tests/run/t6827.scala +++ b/tests/run/t6827.scala @@ -10,7 +10,7 @@ object Test extends App { } catch { case e: Exception => e.toString } - println("%s: %s" format (label, status)) + println("%s: %s".format(label, status)) } tryit("start at -5", -5, 10) diff --git a/tests/run/t8610.scala b/tests/run/t8610.scala index 978900d42d09..f0ffabd0db54 100644 --- a/tests/run/t8610.scala +++ b/tests/run/t8610.scala @@ -3,7 +3,7 @@ case class X(name: String) { def x = "Hi, $name" // missing interp def f(p: (Int, Int)): Int = p._1 * p._2 - def g = f(3, 4) // adapted + def g = f((3, 4)) // adapted def u: Unit = () // unitarian universalist } diff --git a/tests/run/unapply.scala b/tests/run/unapply.scala index 7b10030ba76d..db8823f00eef 100644 --- a/tests/run/unapply.scala +++ b/tests/run/unapply.scala @@ -33,7 +33,7 @@ object VarFoo { object Foo { def unapply(x: Any): Option[Product2[Int, String]] = x match { - case y: Bar => Some(y.size, y.name) + case y: Bar => Some((y.size, y.name)) case _ => None } def doMatch1(b:Bar) = b match { @@ -69,7 +69,7 @@ object Foo { object Mas { object Gaz { def unapply(x: Any): Option[Product2[Int, String]] = x match { - case y: Baz => Some(y.size, y.name) + case y: Baz => Some((y.size, y.name)) case _ => None } } diff --git a/tests/run/virtpatmat_unapply.scala b/tests/run/virtpatmat_unapply.scala index 9915b8d924e5..c52556ae0b69 100644 --- a/tests/run/virtpatmat_unapply.scala +++ b/tests/run/virtpatmat_unapply.scala @@ -1,7 +1,7 @@ class IntList(val hd: Int, val tl: IntList) object NilIL extends IntList(0, null) object IntList { - def unapply(il: IntList): Option[(Int, IntList)] = if(il eq NilIL) None else Some(il.hd, il.tl) + def unapply(il: IntList): Option[(Int, IntList)] = if(il eq NilIL) None else Some((il.hd, il.tl)) def apply(x: Int, xs: IntList) = new IntList(x, xs) }