Skip to content

Commit 073534b

Browse files
committed
Merge branch 'master' into GenASM
2 parents a9b6c14 + f2ffc5b commit 073534b

File tree

11 files changed

+253
-21
lines changed

11 files changed

+253
-21
lines changed

src/compiler/scala/tools/nsc/matching/Patterns.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ trait Patterns extends ast.TreeDSL {
4949

5050
// 8.1.1 (b)
5151
case class WildcardPattern() extends Pattern {
52-
val tree = EmptyTree
52+
def tree = EmptyTree
5353
override def covers(sym: Symbol) = true
5454
override def isDefault = true
5555
override def description = "_"

src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,17 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
511511
* was both already used for a map and mucho long. So "sClass" is the
512512
* specialized subclass of "clazz" throughout this file.
513513
*/
514-
val sClass = clazz.owner.newClass(specializedName(clazz, env0).toTypeName, clazz.pos, (clazz.flags | SPECIALIZED) & ~CASE)
514+
515+
// SI-5545: Eliminate classes with the same name loaded from the bytecode already present - all we need to do is
516+
// to force .info on them, as their lazy type will be evaluated and the symbols will be eliminated. Unfortunately
517+
// evaluating the info after creating the specialized class will mess the specialized class signature, so we'd
518+
// better evaluate it before creating the new class symbol
519+
val clazzName = specializedName(clazz, env0).toTypeName
520+
val bytecodeClazz = clazz.owner.info.decl(clazzName)
521+
debuglog("Specializing " + clazz + " found " + bytecodeClazz + " already there")
522+
bytecodeClazz.info
523+
524+
val sClass = clazz.owner.newClass(clazzName, clazz.pos, (clazz.flags | SPECIALIZED) & ~CASE)
515525

516526
def cloneInSpecializedClass(member: Symbol, flagFn: Long => Long) =
517527
member.cloneSymbol(sClass, flagFn(member.flags | SPECIALIZED))

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1385,9 +1385,10 @@ trait Infer {
13851385
case _ =>
13861386
}
13871387
}
1388+
// todo: missing test case
13881389
NoBestExprAlternativeError(tree, pt)
13891390
} else if (!competing.isEmpty) {
1390-
if (secondTry) NoBestExprAlternativeError(tree, pt)
1391+
if (secondTry) { NoBestExprAlternativeError(tree, pt); setError(tree) }
13911392
else if (!pt.isErroneous) AmbiguousExprAlternativeError(tree, pre, best, competing.head, pt)
13921393
} else {
13931394
// val applicable = alts1 filter (alt =>

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

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
604604
* 1. Check that non-function pattern expressions are stable
605605
* 2. Check that packages and static modules are not used as values
606606
* 3. Turn tree type into stable type if possible and required by context.
607+
* 4. Give getClass calls a more precise type based on the type of the target of the call.
607608
*/
608609
private def stabilize(tree: Tree, pre: Type, mode: Int, pt: Type): Tree = {
609610
if (tree.symbol.isOverloaded && !inFunMode(mode))
@@ -627,7 +628,18 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
627628
if (sym.isStable && pre.isStable && !isByNameParamType(tree.tpe) &&
628629
(isStableContext(tree, mode, pt) || sym.isModule && !sym.isMethod))
629630
tree.setType(singleType(pre, sym))
630-
else tree
631+
// To fully benefit from special casing the return type of
632+
// getClass, we have to catch it immediately so expressions
633+
// like x.getClass().newInstance() are typed with the type of x.
634+
else if ( tree.symbol.name == nme.getClass_
635+
&& tree.tpe.params.isEmpty
636+
// TODO: If the type of the qualifier is inaccessible, we can cause private types
637+
// to escape scope here, e.g. pos/t1107. I'm not sure how to properly handle this
638+
// so for now it requires the type symbol be public.
639+
&& pre.typeSymbol.isPublic)
640+
tree setType MethodType(Nil, erasure.getClassReturnType(pre))
641+
else
642+
tree
631643
}
632644
}
633645

@@ -3802,7 +3814,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
38023814
if (settings.warnSelectNullable.value && isPotentialNullDeference && unit != null)
38033815
unit.warning(tree.pos, "potential null pointer dereference: "+tree)
38043816

3805-
val selection = result match {
3817+
result match {
38063818
// could checkAccessible (called by makeAccessible) potentially have skipped checking a type application in qual?
38073819
case SelectFromTypeTree(qual@TypeTree(), name) if qual.tpe.typeArgs nonEmpty => // TODO: somehow the new qual is not checked in refchecks
38083820
treeCopy.SelectFromTypeTree(
@@ -3824,22 +3836,6 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
38243836
case _ =>
38253837
result
38263838
}
3827-
// To fully benefit from special casing the return type of
3828-
// getClass, we have to catch it immediately so expressions
3829-
// like x.getClass().newInstance() are typed with the type of x.
3830-
val isRefinableGetClass = (
3831-
!selection.isErrorTyped
3832-
&& selection.symbol.name == nme.getClass_
3833-
&& selection.tpe.params.isEmpty
3834-
// TODO: If the type of the qualifier is inaccessible, we can cause private types
3835-
// to escape scope here, e.g. pos/t1107. I'm not sure how to properly handle this
3836-
// so for now it requires the type symbol be public.
3837-
&& qual.tpe.typeSymbol.isPublic
3838-
)
3839-
if (isRefinableGetClass)
3840-
selection setType MethodType(Nil, erasure.getClassReturnType(qual.tpe))
3841-
else
3842-
selection
38433839
}
38443840
}
38453841

test/files/neg/t5553_1.check

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
t5553_1.scala:18: error: ambiguous reference to overloaded definition,
2+
both method apply in object Foo1 of type (z: String)Base[T]
3+
and method apply in object Foo1 of type (a: Int)Base[T]
4+
match expected type ?
5+
def test1[T] = Foo1[T]
6+
^
7+
t5553_1.scala:19: error: type mismatch;
8+
found : [T](z: String)Base[T] <and> (a: Int)Base[T]
9+
required: Int
10+
def test2[T]: Int = Foo1[T]
11+
^
12+
t5553_1.scala:20: error: type mismatch;
13+
found : [T(in method apply)](z: String)Base[T(in method apply)] <and> (a: Int)Base[T(in method apply)]
14+
required: Base[T(in method test3)]
15+
def test3[T]: Base[T] = Foo1[T]
16+
^
17+
t5553_1.scala:24: error: ambiguous reference to overloaded definition,
18+
both method apply in object Foo2 of type (z: String)Base[T]
19+
and method apply in object Foo2 of type (a: Int)Base[T]
20+
match expected type ?
21+
def test4[T] = Foo2[T]
22+
^
23+
t5553_1.scala:25: error: type mismatch;
24+
found : [T](z: String)Base[T] <and> (a: Int)Base[T]
25+
required: Int
26+
def test5[T]: Int = Foo2[T]
27+
^
28+
t5553_1.scala:26: error: type mismatch;
29+
found : [T(in method apply)](z: String)Base[T(in method apply)] <and> (a: Int)Base[T(in method apply)]
30+
required: Base[T(in method test6)]
31+
def test6[T]: Base[T] = Foo2[T]
32+
^
33+
t5553_1.scala:30: error: ambiguous reference to overloaded definition,
34+
both method apply in object Foo3 of type (z: String)String
35+
and method apply in object Foo3 of type (a: Int)Base[T]
36+
match expected type ?
37+
def test7[T] = Foo3[T]
38+
^
39+
t5553_1.scala:31: error: type mismatch;
40+
found : [T](z: String)String <and> (a: Int)Base[T]
41+
required: String
42+
def test8[T]: String = Foo3[T]
43+
^
44+
t5553_1.scala:32: error: type mismatch;
45+
found : [T](z: String)String <and> (a: Int)Base[T]
46+
required: Int
47+
def test9[T]: Int = Foo3[T]
48+
^
49+
t5553_1.scala:33: error: type mismatch;
50+
found : [T(in method apply)](z: String)String <and> (a: Int)Base[T(in method apply)]
51+
required: Base[T(in method test10)]
52+
def test10[T]: Base[T] = Foo3[T]
53+
^
54+
10 errors found

test/files/neg/t5553_1.scala

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
class Base[T]
2+
3+
object Foo1 {
4+
def apply[T](a: Int): Base[T] = new Base[T]
5+
def apply[T](z: String): Base[T] = new Base[T]
6+
}
7+
8+
object Foo2 {
9+
def apply[T](a: Int): Base[T] = new Base[T]
10+
def apply[T](z: String="abc"): Base[T] = new Base[T]
11+
}
12+
13+
object Foo3 {
14+
def apply[T](a: Int): Base[T] = new Base[T]
15+
def apply[T](z: String="abc"): String = z
16+
}
17+
object Test {
18+
def test1[T] = Foo1[T]
19+
def test2[T]: Int = Foo1[T]
20+
def test3[T]: Base[T] = Foo1[T]
21+
}
22+
23+
object Test2 {
24+
def test4[T] = Foo2[T]
25+
def test5[T]: Int = Foo2[T]
26+
def test6[T]: Base[T] = Foo2[T]
27+
}
28+
29+
object Test3{
30+
def test7[T] = Foo3[T]
31+
def test8[T]: String = Foo3[T]
32+
def test9[T]: Int = Foo3[T]
33+
def test10[T]: Base[T] = Foo3[T]
34+
}

test/files/neg/t5553_2.check

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
t5553_2.scala:27: error: type mismatch;
2+
found : Base[T]
3+
required: Int
4+
def test4[T]: Int = Foo1[T](1)
5+
^
6+
t5553_2.scala:34: error: type mismatch;
7+
found : String
8+
required: Base[T]
9+
def test7[T]: Base[T] = Foo2[T]
10+
^
11+
t5553_2.scala:35: error: type mismatch;
12+
found : String
13+
required: Int
14+
def test8[T]: Int = Foo2[T]
15+
^
16+
t5553_2.scala:40: error: type mismatch;
17+
found : String
18+
required: Int
19+
def test9[T]: Int = Foo3[T]
20+
^
21+
t5553_2.scala:41: error: type mismatch;
22+
found : String
23+
required: Base[T]
24+
def test10[T]: Base[T] = Foo3[T]
25+
^
26+
t5553_2.scala:47: error: could not find implicit value for parameter z: String
27+
def test13[T]: Int = Foo3[T]
28+
^
29+
t5553_2.scala:48: error: could not find implicit value for parameter z: String
30+
def test14[T]: Base[T] = Foo3[T]
31+
^
32+
t5553_2.scala:49: error: could not find implicit value for parameter z: String
33+
def test15[T]: String = Foo3[T]
34+
^
35+
t5553_2.scala:50: error: could not find implicit value for parameter z: String
36+
def test16[T] = Foo3[T]
37+
^
38+
t5553_2.scala:54: error: ambiguous reference to overloaded definition,
39+
both method apply in object Foo4 of type (x: Int)(implicit z: String)Base[T]
40+
and method apply in object Foo4 of type (x: Int)Base[T]
41+
match argument types (Int)
42+
def test17[T] = Foo4[T](1)
43+
^
44+
t5553_2.scala:55: error: ambiguous reference to overloaded definition,
45+
both method apply in object Foo4 of type (x: Int)(implicit z: String)Base[T]
46+
and method apply in object Foo4 of type (x: Int)Base[T]
47+
match argument types (Int) and expected result type Base[T]
48+
def test18[T]: Base[T] = Foo4[T](1)
49+
^
50+
11 errors found

test/files/neg/t5553_2.scala

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
class Base[T]
2+
3+
object Foo1 {
4+
def apply[T](x: Int): Base[T] = new Base[T]
5+
def apply[T](x: Int, z: String="abc"): String = z
6+
}
7+
8+
object Foo2 {
9+
def apply[T](a: Int): Base[T] = new Base[T]
10+
def apply[T]: String = "abc"
11+
}
12+
13+
object Foo3 {
14+
def apply[T](x: Int): Base[T] = new Base[T]
15+
def apply[T](implicit z: String): String = z
16+
}
17+
18+
object Foo4 {
19+
def apply[T](x: Int): Base[T] = new Base[T]
20+
def apply[T](x: Int)(implicit z: String): Base[T] = new Base[T]
21+
}
22+
23+
object Test1 {
24+
def test1[T] = Foo1[T](1)
25+
def test2[T]: String = Foo1[T](1)
26+
def test3[T]: Base[T] = Foo1[T](1)
27+
def test4[T]: Int = Foo1[T](1)
28+
29+
}
30+
31+
object Test2 {
32+
def test5[T] = Foo2[T]
33+
def test6[T]: String = Foo2[T]
34+
def test7[T]: Base[T] = Foo2[T]
35+
def test8[T]: Int = Foo2[T]
36+
}
37+
38+
object Test3 {
39+
implicit val v: String = "abc"
40+
def test9[T]: Int = Foo3[T]
41+
def test10[T]: Base[T] = Foo3[T]
42+
def test11[T]: String = Foo3[T]
43+
def test12[T] = Foo3[T]
44+
}
45+
46+
object Test4 {
47+
def test13[T]: Int = Foo3[T]
48+
def test14[T]: Base[T] = Foo3[T]
49+
def test15[T]: String = Foo3[T]
50+
def test16[T] = Foo3[T]
51+
}
52+
53+
object Test5 {
54+
def test17[T] = Foo4[T](1)
55+
def test18[T]: Base[T] = Foo4[T](1)
56+
//def test19[T]: String = Foo4[T](1) // #5554
57+
}
58+
59+

test/files/pos/t5546.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
class A { def foo: Class[_ <: A] = getClass }

test/files/run/t5545.check

Whitespace-only changes.

test/files/run/t5545.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import scala.tools.partest._
2+
import java.io._
3+
4+
object Test extends DirectTest {
5+
6+
override def extraSettings: String = "-usejavacp -d " + testOutput.path + " -cp " + testOutput.path
7+
8+
override def code = """
9+
// SI-5545
10+
trait F[@specialized(Int) T1, R] {
11+
def f(v1: T1): R
12+
def g = v1 => f(v1)
13+
}
14+
""".trim
15+
16+
override def show(): Unit = {
17+
// redirect err to out, for logging
18+
val prevErr = System.err
19+
System.setErr(System.out)
20+
compile()
21+
// the bug manifests at the second compilation, when the bytecode is already there
22+
compile()
23+
System.setErr(prevErr)
24+
}
25+
26+
override def isDebug = false // so we don't get the newSettings warning
27+
}

0 commit comments

Comments
 (0)