Dart Language Design and Specification

repository·main·Indexed 25 days ago

https://github.com/dart-lang/language

The central hub for the design, specification, and evolution of the Dart programming language. This repository contains feature specifications, implementation plans for accepted changes, and documentation on the language evolution process. It includes detailed technical specifications for features such as super-mixins, mixin declaration syntax, and type inference rules.

Tokens
135.5K
Snippets
262
Records
687
Agent score
80%

What's inside dart-lang/language

  1. Overview of enhanced part files

    main

    Enhanced part files generalize library files, part files, and augmentation files into a consistent system. This feature allows part files to declare their own imports, addressing the limitation where all imports previously had to be declared in the main library file. This is particularly useful for:

    1. Large Libraries: Splitting tightly coupled classes into separate files while maintaining library privacy.
    2. Partial Declarations: Splitting a single class or declaration across multiple files (similar to partial classes in C#).
    3. Code Generation: Providing a structured way for augmentations and macros to add new code, imports, and exports to a library.
  2. Overview of Dart Null Safety Roadmap

    main
    Dart is implementing a sound null tracking type system where types are non-nullable by default. The goal is to provide a system that allows for incremental migration, ensuring that programs can run with well-defined semantics even when mixing migrated (non-nullable) and unmigrated code. Once a program is fully migrated, the type system becomes sound, preventing null errors such as returning null from a non-nullable expression or calling methods on null.
  3. Overview of Shared Memory Multithreading in Dart

    main

    The Shared Memory Multithreading proposal aims to bridge the gap between Dart's isolate model and low-level language capabilities. It addresses two primary goals:

    1. Multicore Utilization: Allowing developers to use multicore capabilities without the limitations of the standard isolate model.
    2. Native Interoperability: Aligning Dart's concurrency model with native platforms (C/C++, Swift, Java/Kotlin). This solves issues when native code needs to call back into Dart from an arbitrary thread or when working with APIs pinned to specific threads (like @MainActor in Swift or UI threads in Android).

    Key concepts introduced include:

    • Shared Fields: Allowing developers to selectively break isolation boundaries by declaring certain static fields to be shared between isolates within an isolate group.
    • Shared Isolates: A new type of isolate that only has access to state shared between all isolates in a group, serving as a bridge for native code callbacks.
    • Unrestricted Multithreading: The proposal moves away from a marker-interface approach (Shareable) toward a model that eventually allows unrestricted 'share everything' multithreading within an isolate group.
  4. Overview of Simpler Parameters proposal

    main

    The 'Simpler Parameters' proposal aims to rationalize Dart's parameter syntax by making calling conventions and optionality orthogonal and consistent.

    Key changes include:

    • Calling Convention: Always specified by a delimited section (positional vs. named).
    • Optionality: Specified on a per-parameter basis using a default value expression. This replaces the required keyword and the [...] section syntax.
    • Expanded Support: Allows functions to have both optional positional and named parameters simultaneously.
  5. Investigation of optional semicolons in Dart

    main
    This document outlines an investigation into making semicolons optional in Dart. The proposed approach involves an explicit opt-in mechanism where users add a marker to a file and use a tool (similar to dartfmt) to remove semicolons and adjust whitespace. This method aims to avoid breaking existing code by not treating newlines as significant by default. However, the investigation concluded that even with a formatting step, the rules required to handle code intuitively are overly complex and prone to ambiguity.
  6. Understand the 2017 Non-nullable Types Proposal

    main

    Note: This is an old proposal from 2017 and has been superseded by a newer, active proposal. This document serves as a historical resource explaining the conceptual foundation for adding non-nullable types to Dart.

    Key concepts from this proposal include:

    • Non-nullable by default: Types are non-nullable unless specified otherwise.
    • Nullable via ?: Appending ? to a type makes it nullable.
    • Union Type Semantics: A nullable type (e.g., String?) is treated as a union of the base type and the Null class (String | Null).
    • Safety: Nullable types do not support the methods of the base type (except those on Object), preventing NoSuchMethodError when a value is null.
  7. Understand the distinction between refutable and irrefutable patterns in Dart

    main

    Dart's pattern design distinguishes between two types of patterns based on the context in which they are used:

    1. Matcher Patterns (Refutable): Used in contexts like switch cases. These patterns can fail to match (be 'refuted'). For example, a pattern might check if a value matches a specific constant.
    2. Binder Patterns (Irrefutable): Used in contexts like variable declarations (e.g., var [x, y] = ...). These patterns are used to extract values and bind them to identifiers. They must be 'irrefutable', meaning they are guaranteed to succeed for the given structure.

    This distinction allows the same syntax (like a bare identifier) to mean different things depending on the context: in a case, it acts as a matcher; in a variable declaration, it acts as a binder.

  8. Understand Dart Type Promotion

    main

    Type promotion allows you to avoid explicit casts when a variable's type is obvious from the surrounding code. For example, if you perform an is String check, Dart 're-types' the variable to String within the scope where that check is true.

    Note: This specific proposal for 'Enhanced Type Promotion' is inactive and has been superseded by the more sophisticated flow analysis included with Dart's null safety. For current behavior, refer to the flow analysis documentation.

    int stringLength(Object o) {
      if (o is String) {
        return o.length; // OK! The variable 'o' is promoted to String
      } else {
        throw "Not a string.";
      }
    }
  9. Understand Bazel package structure vs pub packages

    main

    In a Bazel-based monolithic repository, the concept of a 'package' differs from a standard Dart pub package.

    • A Bazel package is a directory containing a BUILD file. It includes all files in that directory and subdirectories, unless those subdirectories also contain a BUILD file.
    • Mapping pub packages to Bazel:
      • package:<a>.<b>/uri.dart resolves to //a/b/lib/uri.dart.
      • package:<name>/uri.dart (where name has no dots) resolves to //third_party/dart/<name>.

    Unlike pub packages where all files in lib/ are accessible via a dependency, Bazel uses targets within a package to provide granular access control.

  10. Key design considerations for Dart Macros

    main

    The implementation of Dart macros involves several complex technical challenges that affect how developers interact with generated code:

    • Scoping and Hygiene: Ensuring generated symbols do not conflict with existing ones and managing access across the macro application scope, the generated code scope, and the macro definition scope.
    • Ordering and Staging: Determining the execution order of macros (e.g., if one macro adds a field and another serializes all fields) and their relationship to type checking and const evaluation.
    • Usability: Requirements for a good macro experience include the ability to navigate to macro implementations, visualize generated code, debug generated code, trace errors back to the macro source, and use auto-complete on generated APIs.
    • Performance: Ensuring that running arbitrary Dart code during compilation does not degrade IDE responsiveness or the edit-refresh cycle.
    • Security: Mitigating risks from malicious code executed during compilation by potentially limiting the dart: libraries available to macro code (e.g., restricting access to ffi).
  11. Understand the motivation for using class modifiers

    main

    Restricting class capabilities helps prevent several common software engineering issues:

    • Safe API Evolution: Using base or interface prevents users from implementing your class's interface. This means you can add new members to your class without breaking existing users, as they are no longer required to implement the new members.
    • Preventing Unintended Overriding: Using final or base prevents subclasses from overriding critical methods that internal logic relies on (e.g., a method that checks a private balance before performing a transaction).
    • Protecting Private Members: If a class cannot be implemented from outside its library, you can safely assume that any instance of that type (or its subclasses) possesses the private members your library logic expects, avoiding NoSuchMethodException at runtime.
    • Guaranteed Initialization: Preventing implementation ensures that all instances of a type must have passed through the defined constructors, guaranteeing that invariants (like unique ID assignment) are maintained.