As kindly advised by @soronpo, i am posting here a new thread related to Enabling sealed traits across different files with union type desugaring - #5 by morgen-peschke
As discussed with @som-snytt in Multi-file ADTs · scala/scala3 · Discussion #21907 · GitHub, this proposal might be helpfull in another context that involves the compilation flag -source:future
, cf Modularity Improvements
Proposal: Cross-File Sealing for Sealed Traits with Explicit Subtype Declaration
Motivation
Currently, Scala’s sealed
traits require all subtypes to be defined within the same file. This limitation restricts the flexibility of sealed traits, especially in larger projects with modular codebases. This proposal aims to introduce a mechanism for cross-file sealing, allowing subtypes to be defined in separate files while maintaining the benefits of compiler optimization and exhaustive pattern matching.
Proposed Solution
Introduce a new syntax for sealed traits that allows explicit declaration of subtypes using an applyTo
clause. This clause would list the fully qualified names of the classes or objects that are allowed to extend the sealed trait.
Example
import com.example.MyClass1
import com.example.MyClass2
import com.example.MyClass3
sealed trait MyTrait {
// ... trait definition ...
} applyTo(com.example.MyClass1, com.example.MyClass2, com.example.MyClass3)
To improve conciseness, the following syntactic sugar could be used, which is equivalent to the applyTo()
version:
import com.example.MyClass1
import com.example.MyClass2
import com.example.MyClass3
sealed trait MyTrait {
// ... trait definition ...
} (com.example.MyClass1, com.example.MyClass2, com.example.MyClass3)
Explanation
The import statements ensure that the specified subtypes are visible within the scope of the MyTrait definition.
The applyTo clause explicitly declares the allowed subtypes, enabling the compiler to:
Verify that the listed subtypes exist and extend MyTrait.
Perform exhaustive pattern matching checks.
Apply optimizations based on the closed set of subtypes.
Benefits
Cross-File Sealing:
Allows subtypes to be defined in separate files.
Compiler Optimization:
Maintains the benefits of compiler optimization and exhaustive pattern matching.
Clarity and Maintainability:
Provides a clear and explicit declaration of allowed subtypes.
Semantic Consistency: The use of applyTo aligns with the semantic of the apply method, making the syntax more intuitive.
Enforcement of Subtype Restrictions
A critical aspect of this proposal is ensuring that the compiler enforces the subtype restrictions defined in the applyTo
clause. If a class or object defined outside of the listed subtypes attempts to extend the sealed trait, the compiler should generate a compilation error. This enforcement is essential for maintaining the guarantees of exhaustive pattern matching and compiler optimization.
Example
// In a separate file:
class UnauthorizedClass extends MyTrait // Should result in a compilation error
Potential Considerations
Requires changes to the Scala compiler to recognize and process the new syntax.
Modifying the compiler for this feature should not introduce significant risks. Sealed traits have a relatively simple AST (Abstract Syntax Tree) representation. The compiler can leverage existing mechanisms for type checking and analysis, with minor adaptations to handle the explicit subtype declarations. This localized nature of the change minimizes the potential for unintended side effects on other parts of the compiler.
Use Cases
Modeling complex domain entities with variations spread across multiple files.
Creating extensible frameworks with a closed set of extension points.
Enhancing the safety and reliability of pattern matching in large codebases.
Next Steps
I would appreciate feedback from the Scala community and the Scala Team on this proposal. If there is sufficient interest, I am willing to contribute to the implementation of this feature.
Thank you for your consideration.