Skip to content

Commit 2553f3e

Browse files
som-snytttgodzik
authored andcommitted
ExtensionNullifiedByMember requires both opaque params
[Cherry-picked aa44a3c]
1 parent 5ca51d1 commit 2553f3e

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

compiler/src/dotty/tools/dotc/typer/RefChecks.scala

+8-1
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,11 @@ object RefChecks {
10551055
*
10561056
* If the extension method is nullary, it is always hidden by a member of the same name.
10571057
* (Either the member is nullary, or the reference is taken as the eta-expansion of the member.)
1058+
*
1059+
* This check is in lieu of a more expensive use-site check that an application failed to use an extension.
1060+
* That check would account for accessibility and opacity. As a limitation, this check considers
1061+
* only public members, a target receiver that is not an alias, and corresponding method parameters
1062+
* that are either both opaque types or both not.
10581063
*/
10591064
def checkExtensionMethods(sym: Symbol)(using Context): Unit =
10601065
if sym.is(Extension) && !sym.nextOverriddenSymbol.exists then
@@ -1078,7 +1083,9 @@ object RefChecks {
10781083
val memberParamTps = member.info.stripPoly.firstParamTypes
10791084
!memberParamTps.isEmpty
10801085
&& memberParamTps.lengthCompare(paramTps) == 0
1081-
&& memberParamTps.lazyZip(paramTps).forall((m, x) => x frozen_<:< m)
1086+
&& memberParamTps.lazyZip(paramTps).forall: (m, x) =>
1087+
m.typeSymbol.denot.isOpaqueAlias == x.typeSymbol.denot.isOpaqueAlias
1088+
&& (x frozen_<:< m)
10821089
}
10831090
}
10841091
.exists

tests/warn/i22279.scala

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
import scala.io.Source
3+
4+
object Lengths:
5+
opaque type Length = Int
6+
object Length:
7+
def apply(i: Int): Length = i
8+
extension (source: Source)
9+
def take(length: Length): IndexedSeq[Char] = // no warn
10+
source.take(length).to(IndexedSeq)
11+
end Lengths
12+
13+
trait Taken:
14+
def take(n: Lengths.Length): Taken = ???
15+
16+
object Lengthy:
17+
import Lengths.*
18+
extension (taken: Taken) def take(n: Length): Taken = ??? // warn
19+
20+
@main def test() = println:
21+
import Lengths.*
22+
val src = Source.fromString("hello, world")
23+
val len = Length("hello".length)
24+
src.take(len)

0 commit comments

Comments
 (0)