-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Null <:< "foo" and other problems with Null subtyping (also in -Yexplicit-nulls) #17467
Comments
sjrd
added a commit
to dotty-staging/dotty
that referenced
this issue
May 11, 2023
The Scala language specification has a peculiar clause about the nullness of singleton types of the form `path.type`. It says that `Null <:< path.type` if the *underlying* type `U` of `path` is nullable itself. The previous implementation of that rule was overly broad, as it indiscrimately widened all types. This resulted in problematic subtyping relationships like `Null <:< "foo"`. We do not widen anymore. Instead, we specifically handle `TermRef`s of stable members, which are how dotc represents singleton types. We also have a rule for `Null <:< null`, which is necessary for pattern matching exhaustivity to keep working in the presence of nulls.
sjrd
added a commit
to dotty-staging/dotty
that referenced
this issue
May 17, 2023
The Scala language specification has a peculiar clause about the nullness of singleton types of the form `path.type`. It says that `Null <:< path.type` if the *underlying* type `U` of `path` is nullable itself. The previous implementation of that rule was overly broad, as it indiscrimately widened all types. This resulted in problematic subtyping relationships like `Null <:< "foo"`. We do not widen anymore. Instead, we specifically handle `TermRef`s of stable members, which are how dotc represents singleton types. We also have a rule for `Null <:< null`, which is necessary for pattern matching exhaustivity to keep working in the presence of nulls.
sjrd
added a commit
to dotty-staging/dotty
that referenced
this issue
May 17, 2023
The Scala language specification has a peculiar clause about the nullness of singleton types of the form `path.type`. It says that `Null <:< path.type` if the *underlying* type `U` of `path` is nullable itself. The previous implementation of that rule was overly broad, as it indiscrimately widened all types. This resulted in problematic subtyping relationships like `Null <:< "foo"`. We do not widen anymore. Instead, we specifically handle `TermRef`s of stable members, which are how dotc represents singleton types. We also have a rule for `Null <:< null`, which is necessary for pattern matching exhaustivity to keep working in the presence of nulls.
sjrd
added a commit
to dotty-staging/dotty
that referenced
this issue
Aug 2, 2023
The Scala language specification has a peculiar clause about the nullness of singleton types of the form `path.type`. It says that `Null <:< path.type` if the *underlying* type `U` of `path` is nullable itself. The previous implementation of that rule was overly broad, as it indiscrimately widened all types. This resulted in problematic subtyping relationships like `Null <:< "foo"`. We do not widen anymore. Instead, we specifically handle `TermRef`s of stable members, which are how dotc represents singleton types. We also have a rule for `Null <:< null`, which is necessary for pattern matching exhaustivity to keep working in the presence of nulls.
Kordyjan
added a commit
that referenced
this issue
Aug 4, 2023
…r explicit nulls. (#17470) The Scala language specification has a peculiar clause about the nullness of singleton types of the form `path.type`. It says that `Null <:< path.type` if the *underlying* type `U` of `path` is nullable itself. The previous implementation of that rule was overly broad, as it indiscrimately widened all types. This resulted in problematic subtyping relationships like `Null <:< "foo"`. We do not widen anymore. Instead, we specifically handle `TermRef`s of stable members, which are how dotc represents singleton types. We also have a rule for `Null <:< null`, which is necessary for pattern matching exhaustivity to keep working in the presence of nulls. --- #### Under explicit nulls, remove the rule Null <:< x.type. The specified rule that `Null <:< x.type` when the underlying type `U` of `x` is nullable is dubious to begin with. Under explicit nulls, it becomes decidedly out of place. We now disable that rule under `-Yexplicit-nulls`.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Compiler version
3.3.0-RC5
Problem at a glance
Null
is considered to be a subtype of anything thatwidenDealias
es to a nullable type.Spec context
The spec actually says that
Null <:< x.type
if the underlying type ofx
is a nullable. But that is supposed to only apply to singleton types of the formpath.type
. Currently in dotty, we even have absurd things likeNull <:< "foo"
because"foo"
widens to"String"
which is nullable.See https://scala-lang.org/files/archive/spec/2.13/03-types.html#singleton-types
Minimized code
REPL session without
-Yexplicit-nulls
Even under
-Yexplicit-nulls
, we have issues:Expectation
Not having
Null <:< T
for arbitraryT
s thatwidenDealias
to a nullable type. Only allow it for singleton types (in dotc terminology,TermRef
s) whose direct underlying type is nullable, as the spec says.Further, under
-Yexplicit-nulls
, IMO we should take the opportunity to tighten the spec to remove the weird clause about the underlying type of singleton types.The text was updated successfully, but these errors were encountered: