Skip to content

Commit f4ddef7

Browse files
som-snyttlrytz
authored andcommitted
Fold selection of unary ops
1 parent fd209dc commit f4ddef7

File tree

3 files changed

+50
-21
lines changed

3 files changed

+50
-21
lines changed

src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,13 @@ abstract class ConstantFolder {
5555
}
5656

5757
/** If tree is a constant operation, replace with result. */
58-
def apply(tree: Tree, site: Symbol): Tree = {
58+
def apply(tree: Tree, site: Symbol): Tree = if (isPastTyper) tree else
5959
try {
6060
tree match {
61-
case Apply(Select(FoldableTerm(x), op), List(FoldableTerm(y))) => fold(tree, foldBinop(op, x, y), true)
62-
case Apply(Select(ConstantTerm(x), op), List(ConstantTerm(y))) => fold(tree, foldBinop(op, x, y), false)
63-
case Select(FoldableTerm(x), op) => fold(tree, foldUnop(op, x), true)
64-
case Select(ConstantTerm(x), op) => fold(tree, foldUnop(op, x), false)
61+
case Apply(Select(FoldableTerm(x), op), List(FoldableTerm(y))) => fold(tree, foldBinop(op, x, y), foldable = true)
62+
case Apply(Select(ConstantTerm(x), op), List(ConstantTerm(y))) => fold(tree, foldBinop(op, x, y), foldable = false)
63+
case Select(FoldableTerm(x), op) => fold(tree, foldUnop(op, x), foldable = true)
64+
case Select(ConstantTerm(x), op) => fold(tree, foldUnop(op, x), foldable = false)
6565
case _ => tree
6666
}
6767
} catch {
@@ -70,39 +70,39 @@ abstract class ConstantFolder {
7070
runReporting.warning(tree.pos, s"Evaluation of a constant expression results in an arithmetic error: ${e.getMessage}", WarningCategory.LintConstant, site)
7171
tree
7272
}
73-
}
7473

75-
/** If tree is a constant value that can be converted to type `pt`, perform
76-
* the conversion.
74+
/** If tree is a constant value that can be converted to type `pt`, perform the conversion.
7775
*/
7876
def apply(tree: Tree, pt: Type, site: Symbol): Tree = {
7977
val orig = apply(tree, site)
8078
orig.tpe match {
81-
case tp@ConstantType(x) => fold(orig, x convertTo pt, isConstantType(tp))
79+
case tp@ConstantType(x) => fold(orig, x.convertTo(pt), foldable = isConstantType(tp))
8280
case _ => orig
8381
}
8482
}
8583

84+
/** Set the computed constant type.
85+
*/
8686
private def fold(orig: Tree, folded: Constant, foldable: Boolean): Tree =
8787
if ((folded eq null) || folded.tag == UnitTag) orig
88-
else if(foldable) orig setType FoldableConstantType(folded)
88+
else if (foldable) orig setType FoldableConstantType(folded)
8989
else orig setType LiteralType(folded)
9090

9191
private def foldUnop(op: Name, x: Constant): Constant = (op, x.tag) match {
9292
case (nme.UNARY_!, BooleanTag) => Constant(!x.booleanValue)
9393

94-
case (nme.UNARY_~ , IntTag ) => Constant(~x.intValue)
95-
case (nme.UNARY_~ , LongTag ) => Constant(~x.longValue)
94+
case (nme.UNARY_~, IntTag ) => Constant(~x.intValue)
95+
case (nme.UNARY_~, LongTag ) => Constant(~x.longValue)
9696

97-
case (nme.UNARY_+ , IntTag ) => Constant(+x.intValue)
98-
case (nme.UNARY_+ , LongTag ) => Constant(+x.longValue)
99-
case (nme.UNARY_+ , FloatTag ) => Constant(+x.floatValue)
100-
case (nme.UNARY_+ , DoubleTag ) => Constant(+x.doubleValue)
97+
case (nme.UNARY_+, IntTag ) => Constant(+x.intValue)
98+
case (nme.UNARY_+, LongTag ) => Constant(+x.longValue)
99+
case (nme.UNARY_+, FloatTag ) => Constant(+x.floatValue)
100+
case (nme.UNARY_+, DoubleTag ) => Constant(+x.doubleValue)
101101

102-
case (nme.UNARY_- , IntTag ) => Constant(-x.intValue)
103-
case (nme.UNARY_- , LongTag ) => Constant(-x.longValue)
104-
case (nme.UNARY_- , FloatTag ) => Constant(-x.floatValue)
105-
case (nme.UNARY_- , DoubleTag ) => Constant(-x.doubleValue)
102+
case (nme.UNARY_-, IntTag ) => Constant(-x.intValue)
103+
case (nme.UNARY_-, LongTag ) => Constant(-x.longValue)
104+
case (nme.UNARY_-, FloatTag ) => Constant(-x.floatValue)
105+
case (nme.UNARY_-, DoubleTag ) => Constant(-x.doubleValue)
106106

107107
case _ => null
108108
}

src/compiler/scala/tools/nsc/typechecker/Typers.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5453,7 +5453,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
54535453
)
54545454
case _ =>
54555455
if (settings.lintUniversalMethods && qualTp.widen.eq(UnitTpe)) checkDubiousUnitSelection(result)
5456-
result
5456+
if (isConstantType(qualTp) && nme.isEncodedUnary(name)) constfold(result, context.owner)
5457+
else result
54575458
}
54585459
}
54595460
}

test/files/pos/t12792.scala

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
2+
// scalac: -Werror -Xlint
3+
4+
import annotation._
5+
6+
object Foo {
7+
final val w = 1 << (java.lang.Integer.SIZE - 1)
8+
final val x = 1 << (java.lang.Integer.SIZE - 2)
9+
final val y = 1 << (java.lang.Integer.SIZE - 3)
10+
final val z = 1 << (java.lang.Integer.SIZE - 4)
11+
final val c = 0xffffffff & ~w & ~x & ~y & ~z
12+
13+
final val i = +42 // 42.unary_+
14+
final val j = -27 // literal -42
15+
}
16+
17+
class Ann(value: Int) extends ConstantAnnotation
18+
class Byt(value: Byte) extends ConstantAnnotation
19+
20+
class Test {
21+
import Foo._
22+
@Ann(w) def fw = 42
23+
@Ann(x) def fx = 42
24+
@Ann(c) def fc = 42
25+
@Ann(i) def fi = 42
26+
@Ann(j) def fj = 42
27+
@Byt(42) def byteMe = 42
28+
}

0 commit comments

Comments
 (0)