You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
classC {
defget():Int=0
}
defg= {
vals:String|Null=???vall= s.length // okvalc:C|Null=???
c.get() // error: value get is not a member of C | Null
}
Output
-- [E008] Not Found Error: Stest.scala:13:6 ------------------------------------
13 | c.get()
| ^^^^^
| value get is not a member of C | Null
The nullable C is expected to have similar behaviour as nullable String.
I think the issue is at TypeOps.orDominator. String | Null after join becomes String. But C | Null after join becomes Object.
This code can be compiled using explicit-nulls and unsafeNulls (scalac -Yexplicit-nulls -language:unsafeNulls), since unsafeNulls will ignore Null type when searching members, then there is no need to join the OrType (see Types.goOr).
(String | Null).join can return a correct result, because the type of String after widenExpr is different, approximateOr uses subtyping and lub to decide the result.
However, the type of C after widenExpr is the same, approximateOr uses baseClasses of C and Null to decide. I think we need to handle bottom classes for commonBaseClasses more carefully to fix the issue.
// Step 3: Intersect base classes of both sidesvalcommonBaseClasses= tp.mapReduceOr(_.baseClasses)(intersect)
valdoms= dominators(commonBaseClasses, Nil)
defbaseTp(cls: ClassSymbol):Type=
tp.baseType(cls).mapReduceOr(identity)(mergeRefinedOrApplied)
doms.map(baseTp).reduceLeft(AndType.apply)
I don't understand the reason to use baseClasses here. Why don't we using subtyping compare in step 3 as well?
The text was updated successfully, but these errors were encountered:
I think there is indeed a subtype test missing, but it should come before we enter orDominator (or at the start of it). There was an implicit assumption that arguments in an OrType are incompatible with each other. This is true for OrTypes arising from lubs but not true for OrTypes given explicitly.
Output
The nullable
C
is expected to have similar behaviour as nullableString
.I think the issue is at
TypeOps.orDominator
.String | Null
after join becomesString
. ButC | Null
after join becomesObject
.This code can be compiled using explicit-nulls and unsafeNulls (
scalac -Yexplicit-nulls -language:unsafeNulls
), since unsafeNulls will ignore Null type when searching members, then there is no need to join the OrType (seeTypes.goOr
).(String | Null).join
can return a correct result, because the type ofString
afterwidenExpr
is different,approximateOr
uses subtyping andlub
to decide the result.However, the type of
C
afterwidenExpr
is the same,approximateOr
usesbaseClasses
ofC
andNull
to decide. I think we need to handle bottom classes for commonBaseClasses more carefully to fix the issue.I don't understand the reason to use baseClasses here. Why don't we using subtyping compare in step 3 as well?
The text was updated successfully, but these errors were encountered: