Skip to content

Commit

Permalink
Merge pull request #10445 from lrytz/t12408-backport
Browse files Browse the repository at this point in the history
[backport] warn about more unchecked type arguments
  • Loading branch information
lrytz committed Jun 27, 2023
2 parents cd3dec1 + 6467d54 commit 466edaf
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 16 deletions.
8 changes: 4 additions & 4 deletions src/compiler/scala/tools/nsc/typechecker/Checkable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,10 @@ trait Checkable {
}

private def isUnwarnableTypeArgSymbol(sym: Symbol) = (
sym.isTypeParameter // dummy
|| (sym.name.toTermName == nme.WILDCARD) // _
|| nme.isVariableName(sym.name) // type variable
)
(!settings.isScala213 && sym.isTypeParameter) || // dummy
sym.name.toTermName == nme.WILDCARD || // don't warn for `case l: List[_]`. Here, `List[_]` is a TypeRef, the arg refers an abstract type symbol `_`
nme.isVariableName(sym.name) // don't warn for `x.isInstanceOf[List[_]]`. Here, `List[_]` is an existential, quantified sym has `isVariableName`
)
private def isUnwarnableTypeArg(arg: Type) = (
uncheckedOk(arg) // @unchecked T
|| isUnwarnableTypeArgSymbol(arg.typeSymbolDirect) // has to be direct: see pos/t1439
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/scala/tools/nsc/typechecker/Infer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1154,7 +1154,7 @@ trait Infer extends Checkable {
}
}

def inferTypedPattern(tree0: Tree, pattp: Type, pt0: Type, canRemedy: Boolean): Type = {
def inferTypedPattern(tree0: Tree, pattp: Type, pt0: Type, canRemedy: Boolean, isUnapply: Boolean): Type = {
val pt = abstractTypesToBounds(pt0)
val ptparams = freeTypeParamsOfTerms(pt)
val tpparams = freeTypeParamsOfTerms(pattp)
Expand All @@ -1171,7 +1171,7 @@ trait Infer extends Checkable {
return ErrorType
}

checkCheckable(tree0, pattp, pt, inPattern = true, canRemedy)
checkCheckable(tree0, if (isUnapply && settings.isScala213) typer.applyTypeToWildcards(pattp) else pattp, pt, inPattern = true, canRemedy)
if (pattp <:< pt) ()
else {
debuglog("free type params (1) = " + tpparams)
Expand Down
18 changes: 13 additions & 5 deletions src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ trait PatternTypers {
case tp => tp
}

def applyTypeToWildcards(tp: Type) = tp match {
case tr @ TypeRef(pre, sym, args) if args.nonEmpty =>
// similar to `typedBind`
def wld = context.owner.newAbstractType(tpnme.WILDCARD, sym.pos) setInfo TypeBounds.empty
copyTypeRef(tr, pre, sym, args.map(_ => wld.tpe))
case t => t
}

def typedConstructorPattern(fun0: Tree, pt: Type): Tree = {
// Do some ad-hoc overloading resolution and update the tree's symbol and type
// do not update the symbol if the tree's symbol's type does not define an unapply member
Expand Down Expand Up @@ -168,7 +176,7 @@ trait PatternTypers {
case _ => extractor.nonEmpty
}

val ownType = inferTypedPattern(tptTyped, tpe, pt, canRemedy)
val ownType = inferTypedPattern(tptTyped, tpe, pt, canRemedy, isUnapply = false)
val treeTyped = treeCopy.Typed(tree, exprTyped, tptTyped) setType ownType

extractor match {
Expand Down Expand Up @@ -299,7 +307,7 @@ trait PatternTypers {
val GenPolyType(freeVars, unappFormal) = freshArgType(unapplyType.skolemizeExistential(context.owner, tree))
val unapplyContext = context.makeNewScope(context.tree, context.owner)
freeVars foreach unapplyContext.scope.enter
val pattp = newTyper(unapplyContext).infer.inferTypedPattern(tree, unappFormal, pt, canRemedy)
val pattp = newTyper(unapplyContext).infer.inferTypedPattern(tree, unappFormal, pt, canRemedy, isUnapply = true)
// turn any unresolved type variables in freevars into existential skolems
val skolems = freeVars map (fv => unapplyContext.owner.newExistentialSkolem(fv, fv))
pattp.substSym(freeVars, skolems)
Expand Down Expand Up @@ -369,9 +377,9 @@ trait PatternTypers {
}
// only look at top-level type, can't (reliably) do anything about unchecked type args (in general)
// but at least make a proper type before passing it elsewhere
val pt1 = pt.dealiasWiden match {
case tr @ TypeRef(pre, sym, args) if args.nonEmpty => copyTypeRef(tr, pre, sym, sym.typeParams map (_.tpeHK)) // replace actual type args with dummies
case pt1 => pt1
val pt1 = if (settings.isScala213) applyTypeToWildcards(pt.dealiasWiden) else pt.dealiasWiden match {
case tr@TypeRef(pre, sym, args) if args.nonEmpty => copyTypeRef(tr, pre, sym, sym.typeParams map (_.tpeHK)) // replace actual type args with dummies
case pt1 => pt1
}
if (isCheckable(pt1)) EmptyTree
else resolveClassTag(pos, pt1) match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,8 @@ trait SyntheticMethods extends ast.TreeDSL {
if (!syntheticsOk)
return templ

val synthesizer = new ClassMethodSynthesis(
clazz0,
newTyper( if (reporter.hasErrors) context makeSilent false else context )
)
val typer = newTyper(if (reporter.hasErrors) context.makeSilent(false) else context)
val synthesizer = new ClassMethodSynthesis(clazz0, typer)
import synthesizer._

if (clazz0 == AnyValClass || isPrimitiveValueClass(clazz0)) return {
Expand Down Expand Up @@ -154,7 +152,7 @@ trait SyntheticMethods extends ast.TreeDSL {
Match(
Ident(eqmeth.firstParam),
List(
CaseDef(Typed(Ident(nme.WILDCARD), TypeTree(clazz.tpe)), EmptyTree, TRUE),
CaseDef(Typed(Ident(nme.WILDCARD), TypeTree(typer.applyTypeToWildcards(clazz.tpe))), EmptyTree, TRUE),
CaseDef(Ident(nme.WILDCARD), EmptyTree, FALSE)
)
)
Expand Down
6 changes: 6 additions & 0 deletions test/files/neg/t12408-backport.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
t12408-backport.scala:2: warning: abstract type X in type pattern Some[X] is unchecked since it is eliminated by erasure
class A[X] { def f[Y](x: Option[Y]) = x match { case s: Some[X] => 0; case _ => 1 } }
^
error: No warnings can be incurred under -Xfatal-warnings.
one warning found
one error found
2 changes: 2 additions & 0 deletions test/files/neg/t12408-backport.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// scalac: -Xsource:2.13 -Werror
class A[X] { def f[Y](x: Option[Y]) = x match { case s: Some[X] => 0; case _ => 1 } }

0 comments on commit 466edaf

Please sign in to comment.