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

Address new warnings with the strict patmat exhaustivity of 2.13.4. #4272

Closed
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
120 changes: 62 additions & 58 deletions compiler/src/main/scala/org/scalajs/nscplugin/GenJSCode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,10 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
try {
def collectClassDefs(tree: Tree): List[ClassDef] = {
tree match {
case EmptyTree => Nil
case PackageDef(_, stats) => stats flatMap collectClassDefs
case cd: ClassDef => cd :: Nil
case EmptyTree => Nil
case PackageDef(_, stats) => stats.flatMap(collectClassDefs)
case cd: ClassDef => cd :: Nil
case _ => abort(s"Unexpected top-level tree at ${tree.pos}:\n$tree")
}
}
val allClassDefs = collectClassDefs(cunit.body)
Expand Down Expand Up @@ -1652,6 +1653,8 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
(Nil, applyCtor)
case js.Block(prepStats :+ (applyCtor: js.ApplyStatic)) =>
(prepStats, applyCtor)
case _ =>
abort(s"Unexpected body for JS constructor dispatch resolution at ${body.pos}:\n$body")
}
val js.ApplyStatic(_, _, js.MethodIdent(ctorName), js.This() :: ctorArgs) =
applyCtor
Expand Down Expand Up @@ -1731,6 +1734,9 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
if method.name.isConstructor =>
method.name
}.get

case _ =>
abort(s"Unexpected secondary constructor body at ${tree.pos}:\n$tree")
}

val (primaryCtor :: Nil, secondaryCtors) = ctors.partition {
Expand Down Expand Up @@ -2759,6 +2765,8 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
true
case pat @ Bind(_, _) =>
isMaybeJavaScriptException(pat.symbol.tpe)
case pat =>
abort(s"Unexpected pattern at ${pat.pos}: $pat")
}
}

Expand Down Expand Up @@ -2791,6 +2799,8 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
val ident = encodeLocalSym(pat.symbol)
val origName = originalNameOfLocal(pat.symbol)
(pat.symbol.tpe, Some((ident, origName)))
case _ =>
abort(s"Unexpected pattern at ${pat.pos}: $pat")
})

// Generate the body that must be executed if the exception matches
Expand Down Expand Up @@ -4606,28 +4616,6 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
params.size == 1 && params.head.tpe.typeSymbol == ObjectClass
}

/** check if the method we are invoking conforms to a method on
* scala.Array. If this is the case, we check that case specially at
* runtime to avoid having reflective call proxies on scala.Array.
* (Also, note that the element type of Array#update is not erased and
* therefore the method name mangling would turn out wrong)
*
* Note that we cannot check if the expected return type is correct,
* since this type information is already erased.
*/
def isArrayLikeOp = name match {
case nme.update =>
params.size == 2 && params.head.tpe.typeSymbol == IntClass
case nme.apply =>
params.size == 1 && params.head.tpe.typeSymbol == IntClass
case nme.length =>
params.size == 0
case nme.clone_ =>
params.size == 0
case _ =>
false
}

/**
* Tests whether one of our reflective "boxes" for primitive types
* implements the particular method. If this is the case
Expand Down Expand Up @@ -4670,6 +4658,9 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
var callStatement: js.Tree = js.Apply(js.ApplyFlags.empty, callTrg,
encodeMethodSym(sym, reflProxy = true), arguments)(jstpe.AnyType)

def addCodePath(condition: js.Tree)(ifTrue: js.Tree): Unit =
callStatement = js.If(condition, ifTrue, callStatement)(jstpe.AnyType)

if (!isAnyRefPrimitive) {
def boxIfNeeded(call: js.Tree, returnType: Type): js.Tree = {
if (isPrimitiveValueType(returnType))
Expand All @@ -4678,30 +4669,44 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
call
}

if (isArrayLikeOp) {
def genRTCall(method: Symbol, args: js.Tree*) =
genApplyMethod(genLoadModule(ScalaRunTimeModule),
method, args.toList)
val isArrayTree =
genRTCall(ScalaRunTime_isArray, callTrg, js.IntLiteral(1))
callStatement = js.If(isArrayTree, {
name match {
case nme.update =>
js.Block(
genRTCall(currentRun.runDefinitions.arrayUpdateMethod,
callTrg, arguments(0), arguments(1)),
js.Undefined()) // Boxed Unit
case nme.apply =>
genRTCall(currentRun.runDefinitions.arrayApplyMethod, callTrg,
arguments(0))
case nme.length =>
genRTCall(currentRun.runDefinitions.arrayLengthMethod, callTrg)
case nme.clone_ =>
genApplyMethod(callTrg, Object_clone, arguments)
/* Handle the primitive methods available on scala.Array's.
*
* If the method we are invoking conforms to a method of scala.Array,
* we test at run-time whether the receiver is an array and then
* delegate to a method of ScalaRunTime. This is necessary because they
* are primitives without any equivalent IR definitions, hence without
* reflective proxies.
*
* Note that we cannot check if the returned value matches the
* expected type, since this type information was already erased.
*/
def genRTCall(method: Symbol, args: js.Tree*): js.Tree =
genApplyMethod(genLoadModule(ScalaRunTimeModule), method, args.toList)
def addCodePathForArray(ifArray: js.Tree): Unit =
addCodePath(genRTCall(ScalaRunTime_isArray, callTrg, js.IntLiteral(1)))(ifArray)
name match {
case nme.update if params.size == 2 && params.head.tpe.typeSymbol == IntClass =>
addCodePathForArray {
js.Block(
genRTCall(currentRun.runDefinitions.arrayUpdateMethod,
callTrg, arguments(0), arguments(1)),
js.Undefined()) // Boxed Unit
}
case nme.apply if params.size == 1 && params.head.tpe.typeSymbol == IntClass =>
addCodePathForArray {
genRTCall(currentRun.runDefinitions.arrayApplyMethod, callTrg,
arguments(0))
}
case nme.length if params.isEmpty =>
addCodePathForArray {
genRTCall(currentRun.runDefinitions.arrayLengthMethod, callTrg)
}
}, {
callStatement
})(jstpe.AnyType)
case nme.clone_ if params.isEmpty =>
addCodePathForArray {
genApplyMethod(callTrg, Object_clone, arguments)
}
case _ =>
()
}

/* Add an explicit type test for a hijacked class with a call to a
Expand All @@ -4717,14 +4722,12 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
hijackedMethod != NoSymbol && hijackedMethod.isPublic
if (isApplicable) {
val hijackedClassTpe = hijackedClass.tpe
callStatement = js.If(genIsInstanceOf(callTrg, hijackedClassTpe), {
addCodePath(genIsInstanceOf(callTrg, hijackedClassTpe)) {
boxIfNeeded(
genApplyMethod(genAsInstanceOf(callTrg, hijackedClassTpe),
hijackedMethod, arguments),
hijackedMethod.tpe.resultType)
}, { // else
callStatement
})(jstpe.AnyType)
}
}
isApplicable
}
Expand Down Expand Up @@ -4763,15 +4766,13 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
false
} else {
val boxedTpe = boxedClass.tpe
callStatement = js.If(genIsInstanceOf(callTrg, boxedTpe), {
addCodePath(genIsInstanceOf(callTrg, boxedTpe)) {
val castCallTrg =
makePrimitiveUnbox(callTrg, primitiveClass.tpe)
val call = genPrimitiveOpForReflectiveCall(methodInPrimClass,
castCallTrg, arguments)
boxIfNeeded(call, methodInPrimClass.tpe.resultType)
}, { // else
callStatement
})(jstpe.AnyType)
}
true
}
} else {
Expand Down Expand Up @@ -5209,7 +5210,7 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
} else if (jsInterop.isJSBracketAccess(sym)) {
assert(argc == 1 || argc == 2,
s"@JSBracketAccess methods should have 1 or 2 non-varargs arguments")
argsNoSpread match {
(argsNoSpread: @unchecked) match {
case List(keyArg) =>
genSelectGet(keyArg)
case List(keyArg, valueArg) =>
Expand Down Expand Up @@ -6427,7 +6428,10 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
import jsPrimitives._
if (isPrimitive(sym)) {
getPrimitive(sym) match {
case UNITVAL => js.Undefined()
case UNITVAL =>
js.Undefined()
case _ =>
abort(s"Unexpected primitive in genStaticField at $pos: ${sym.fullName}")
}
} else {
val className = encodeClassName(sym.owner)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ abstract class PrepJSInterop[G <: Global with Singleton](val global: G)

checkJSNameAnnots(sym)

val transformedTree: Tree = tree match {
// @unchecked needed on 2.13.4+ because MemberDef is not marked `sealed`
val transformedTree: Tree = (tree: @unchecked) match {
case tree: ImplDef =>
if (shouldPrepareExports)
registerClassOrModuleExports(sym)
Expand Down Expand Up @@ -828,6 +829,9 @@ abstract class PrepJSInterop[G <: Global with Singleton](val global: G)
}
Some(loadSpec)

case Some(annot) =>
abort(s"checkAndGetJSNativeLoadingSpecAnnotOf returned unexpected annotation $annot")

case None =>
/* We already emitted an error. Invent something not to cause
* cascading errors.
Expand Down
2 changes: 1 addition & 1 deletion ir/src/main/scala/org/scalajs/ir/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1235,7 +1235,7 @@ object Trees {

def isConstructor: Boolean = (ordinal & ConstructorFlag) != 0

def prefixString: String = this match {
def prefixString: String = (this: @unchecked) match {
case Public => ""
case Private => "private "
case PublicStatic => "static "
Expand Down
2 changes: 1 addition & 1 deletion javalib/src/main/scala/java/math/BigDecimal.scala
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ object BigDecimal {
val absFraction = Math.abs(fraction)
val sigFraction = java.lang.Integer.signum(fraction)
// the carry after rounding
roundingMode match {
(roundingMode: @unchecked) match {
case UP => sigFraction
case DOWN => 0
case CEILING => Math.max(sigFraction, 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ abstract class CharsetDecoder protected (cs: Charset,
if (result2.isUnmappable()) unmappableCharacterAction()
else malformedInputAction()

action match {
(action: @unchecked) match {
case CodingErrorAction.REPLACE =>
if (out.remaining() < replacement().length) {
CoderResult.OVERFLOW
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ abstract class CharsetEncoder protected (cs: Charset,
if (result2.isUnmappable()) unmappableCharacterAction()
else malformedInputAction()

action match {
(action: @unchecked) match {
case CodingErrorAction.REPLACE =>
if (out.remaining() < replacement().length) {
CoderResult.OVERFLOW
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ object ModuleKind {
extends Fingerprint[ModuleKind] {

override def fingerprint(moduleKind: ModuleKind): String = {
moduleKind match {
(moduleKind: @unchecked) match {
case NoModule => "NoModule"
case ESModule => "ESModule"
case CommonJSModule => "CommonJSModule"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ object ModuleSplitStyle {
extends Fingerprint[ModuleSplitStyle] {

override def fingerprint(moduleSplitStyle: ModuleSplitStyle): String = {
moduleSplitStyle match {
(moduleSplitStyle: @unchecked) match {
case FewestModules => "FewestModules"
case SmallestModules => "SmallestModules"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ object Report {
}

private def writeModuleKind(kind: ModuleKind): Unit = {
val i = kind match {
val i = (kind: @unchecked) match {
case ModuleKind.NoModule => 0
case ModuleKind.ESModule => 1
case ModuleKind.CommonJSModule => 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
methodFun0
}

val field = namespace match {
val field = (namespace: @unchecked) match {
case MemberNamespace.Private => "p"
case MemberNamespace.PublicStatic => "s"
case MemberNamespace.PrivateStatic => "ps"
Expand Down Expand Up @@ -1220,7 +1220,7 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
private def genConstValueExportDef(exportName: String,
exportedValue: js.Tree)(
implicit pos: Position): WithGlobals[js.Tree] = {
moduleKind match {
(moduleKind: @unchecked) match {
case ModuleKind.NoModule =>
genAssignToNoModuleExportVar(exportName, exportedValue)

Expand Down Expand Up @@ -1261,7 +1261,7 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {

val varScope = (className, field.name)

moduleKind match {
(moduleKind: @unchecked) match {
case ModuleKind.NoModule =>
/* Initial value of the export. Updates are taken care of explicitly
* when we assign to the static field.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ final class Emitter(config: Emitter.Config) {
def emit(moduleSet: ModuleSet, logger: Logger): Result = {
val WithGlobals(body, globalRefs) = emitInternal(moduleSet, logger)

moduleKind match {
(moduleKind: @unchecked) match {
case ModuleKind.NoModule =>
assert(moduleSet.modules.size <= 1)
val topLevelVars = moduleSet.modules
Expand Down Expand Up @@ -294,7 +294,7 @@ final class Emitter(config: Emitter.Config) {
)
).toList.sortBy(_._1.name)

moduleKind match {
(moduleKind: @unchecked) match {
case ModuleKind.NoModule =>
WithGlobals(Nil)

Expand Down
Loading