Skip to content

Commit

Permalink
Merge pull request #10560 from som-snytt/issue/9971-new-rewrite-local…
Browse files Browse the repository at this point in the history
…-case

Improve detection of case class in refinement vs local
  • Loading branch information
lrytz committed Jan 15, 2024
2 parents f1c9a40 + d25cc15 commit 6b27646
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 11 deletions.
17 changes: 7 additions & 10 deletions src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
Expand Up @@ -446,7 +446,7 @@ abstract class RefChecks extends Transform {
else if (other.isStable && !member.isStable) // (1.4)
overrideErrorWithMemberInfo("stable, immutable value required to override:")
else if (member.isValue && member.isLazy &&
other.isValue && other.hasFlag(STABLE) && !other.isDeferred && !other.isLazy)
other.isValue && other.hasStableFlag && !other.isDeferred && !other.isLazy)
overrideErrorWithMemberInfo("concrete non-lazy value cannot be overridden:")
else if (other.isValue && other.isLazy && member.isValue && !member.isLazy)
overrideErrorWithMemberInfo("value must be lazy when overriding concrete lazy value:")
Expand Down Expand Up @@ -1661,18 +1661,15 @@ abstract class RefChecks extends Transform {
case TypeApply(fun, targs) =>
isClassTypeAccessible(fun)
case Select(module, apply) =>
( // scala/bug#4859 `CaseClass1().InnerCaseClass2()` must not be rewritten to `new InnerCaseClass2()`;
// {expr; Outer}.Inner() must not be rewritten to `new Outer.Inner()`.
treeInfo.isQualifierSafeToElide(module) &&
// scala/bug#5626 Classes in refinement types cannot be constructed with `new`. In this case,
// the companion class is actually not a ClassSymbol, but a reference to an abstract type.
module.symbol.companionClass.isClass
)
// scala/bug#4859 `CaseClass1().InnerCaseClass2()` must not be rewritten to `new InnerCaseClass2()`;
// {expr; Outer}.Inner() must not be rewritten to `new Outer.Inner()`.
treeInfo.isQualifierSafeToElide(module) &&
// scala/bug#5626 Classes in refinement types cannot be constructed with `new`.
!module.exists { case t @ Select(_, _) => t.symbol != null && t.symbol.isStructuralRefinementMember case _ => false }
case x => throw new MatchError(x)
}

sym.name == nme.apply &&
!(sym hasFlag STABLE) && // ???
!sym.hasStableFlag && // ???
sym.isCase &&
isClassTypeAccessible(tree) &&
!tree.tpe.finalResultType.typeSymbol.primaryConstructor.isLessAccessibleThan(tree.symbol)
Expand Down
2 changes: 1 addition & 1 deletion src/reflect/scala/reflect/internal/Symbols.scala
Expand Up @@ -3060,7 +3060,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// Note also that trait vals are modelled as getters, and thus that user-supplied code appears in their rhs.
// Originally, it may have been an optimization to skip methods that were not user-defined (getters),
// but it doesn't even exclude setters, contrary to its original comment (// exclude all accessors)
override def isSourceMethod = !(this hasFlag STABLE)
override def isSourceMethod = !hasStableFlag

// unfortunately having the CASEACCESSOR flag does not actually mean you
// are a case accessor (you can also be a field.)
Expand Down
5 changes: 5 additions & 0 deletions test/files/pos/t5626.scala
@@ -1,3 +1,4 @@
//> using options -feature -Wconf:cat=feature-reflective-calls:s -Werror
class C {
val blob = {
new { case class Foo() }
Expand All @@ -6,7 +7,11 @@ class C {
class Inner { case class Foo() }
new Inner
}
val z: Any { def x: X.type } = new { def x = X }

val foo = blob.Foo()
val bar = blub.Foo()
val baz = z.x()
}

case class X()
11 changes: 11 additions & 0 deletions test/files/run/t9971.scala
@@ -0,0 +1,11 @@
object Test {
def main(args: Array[String]): Unit = assert(f == 42)
def f = {
object Foo {
val bar = Foo(42)
}
case class Foo(i: Int)

Foo.bar.i
}
}

0 comments on commit 6b27646

Please sign in to comment.