-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Compiler version
All 3.x versions
Minimized example
The modelling of ASTs can be improved by exploiting the -Yexplicit-nulls setting, which is enabled in the dotc build.
There are the following major design criteria for AST trees, which should be kept:
- There are untyped trees and typed trees.
- The kind of a tree is represented by a type parameter or abstract type
T. - For typed trees
T = Typeand for untyped treesT = UntypedwhereUntypedis eitherNullorNothing. - Typed trees can be used where untyped trees are required, forgetting the type annotations.
- The
typeOptmethod on trees returns aT, i.e. either bottom type or aType. - The
tpemethod on trees returns aTypeand will fail (ideally at compile time, but currently at runtime) if the tree is untyped.
When dotc was first designed, we fulfilled the criteria by defining type Tree like this:
abstract class Tree[-T >: Null] ...That made sure that typed trees Tree[Type] are a subtype of untyped trees Tree[Null], since Null was a subtype of Type. But with explicit nulls, that's no longer true. So we changed the bottom type from Null to Nothing.
Nevertheless, there's some awkwardness:
First, the tpe method on trees is variance incorrect. It is defined like this:
final def tpe: T @uncheckedVariance = ...Second, we can write
val t: Type = tree.tpewithout problem even if tree is an untyped tree, since its tpe method returns Nothing, which conforms to Type.
It looks like we can get a sound system with better static checking if we model Tree instead like this:
abstract class Tree[+T <: Type | Null]
object untpd:
type Tree = Tree[Type | Null]
object tpe:
type Tree = Tree[Type]It's going to be a big change in the sense of number of lines changed, but it would make things clearer. So I think we should do it before going into an LTS.