diff --git a/compiler/src/dotty/tools/dotc/core/Decorators.scala b/compiler/src/dotty/tools/dotc/core/Decorators.scala index ce488ef23885..14a9d884cf9c 100644 --- a/compiler/src/dotty/tools/dotc/core/Decorators.scala +++ b/compiler/src/dotty/tools/dotc/core/Decorators.scala @@ -184,6 +184,9 @@ object Decorators { loop(xs, xs, 0) end mapWithIndexConserve + /** True if two lists have the same length. Since calling length on linear sequences + * is Θ(n), it is an inadvisable way to test length equality. This method is Θ(n min m). + */ final def hasSameLengthAs[U](ys: List[U]): Boolean = { @tailrec def loop(xs: List[T], ys: List[U]): Boolean = if (xs.isEmpty) ys.isEmpty diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index 0109fabb1744..f183cb35d9cc 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -551,7 +551,7 @@ object Denotations { case _ => NoType case tp1: PolyType => tp2 match - case tp2: PolyType if sameLength(tp1.paramNames, tp2.paramNames) => + case tp2: PolyType if tp1.paramNames.hasSameLengthAs(tp2.paramNames) => val resType = infoMeet(tp1.resType, tp2.resType.subst(tp2, tp1), safeIntersection) if resType.exists then tp1.derivedLambdaType( diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 2ddf22d8db71..9628504fbfbd 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -1948,7 +1948,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling case tp1: PolyType => tp2.widen match { case tp2: PolyType => - sameLength(tp1.paramNames, tp2.paramNames) && + tp1.paramNames.hasSameLengthAs(tp2.paramNames) && matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), relaxed) case _ => false diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 8f0d325e04f8..24794011bf5b 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -286,7 +286,7 @@ trait TypeAssigner { def assignType(tree: untpd.Apply, fn: Tree, args: List[Tree])(using Context): Apply = { val ownType = fn.tpe.widen match { case fntpe: MethodType => - if (sameLength(fntpe.paramInfos, args) || ctx.phase.prev.relaxedTyping) + if (fntpe.paramInfos.hasSameLengthAs(args) || ctx.phase.prev.relaxedTyping) safeSubstMethodParams(fntpe, args.tpes) else errorType(i"wrong number of arguments at ${ctx.phase.prev} for $fntpe: ${fn.tpe}, expected: ${fntpe.paramInfos.length}, found: ${args.length}", tree.srcPos) @@ -358,7 +358,7 @@ trait TypeAssigner { if tp eq pt then pt.newLikeThis(pt.paramNames, pt.paramInfos, pt.resType) else tp) val argTypes = args.tpes.mapConserve(ensureFresh) - if (sameLength(argTypes, paramNames)) pt.instantiate(argTypes) + if (argTypes.hasSameLengthAs(paramNames)) pt.instantiate(argTypes) else wrongNumberOfTypeArgs(fn.tpe, pt.typeParams, args, tree.srcPos) } } @@ -474,7 +474,7 @@ trait TypeAssigner { assert(!hasNamedArg(args) || ctx.reporter.errorsReported, tree) val tparams = tycon.tpe.typeParams val ownType = - if (sameLength(tparams, args)) + if (tparams.hasSameLengthAs(args)) if (tycon.symbol == defn.andType) AndType(args(0).tpe, args(1).tpe) else if (tycon.symbol == defn.orType) OrType(args(0).tpe, args(1).tpe, soft = false) else tycon.tpe.appliedTo(args.tpes) diff --git a/compiler/src/dotty/tools/package.scala b/compiler/src/dotty/tools/package.scala index f6bf4314e262..79488c70cf6b 100644 --- a/compiler/src/dotty/tools/package.scala +++ b/compiler/src/dotty/tools/package.scala @@ -8,18 +8,6 @@ package object tools { val ListOfNil: List[Nil.type] = Nil :: Nil - /** True if two lists have the same length. Since calling length on linear sequences - * is O(n), it is an inadvisable way to test length equality. - */ - final def sameLength[T](xs: List[T], ys: List[T]): Boolean = xs match { - case _ :: xs1 => - ys match { - case _ :: ys1 => sameLength(xs1, ys1) - case _ => false - } - case _ => ys.isEmpty - } - /** Throws an `UnsupportedOperationException` with the given method name. */ def unsupported(methodName: String): Nothing = throw new UnsupportedOperationException(methodName)