In a Dart pubspec.yaml, how does the `environment: sdk:` lower bound select the language version, and what does `// @dart = x.y` change?
answer
- lower bound, not installed SDK
- major.minor only
- raise the bound to unlock features
- @dart comment before any code
- missing sdk constraint is an error
basics
~20 sA package's default language version is the major.minor of its SDK constraint's lower bound, not the SDK you have installed. A // @dart = x.y comment at the top of one library overrides that for that file only.
solid answer
~40 s`environment: sdk: ^3.8.0` does two things. As a constraint, it says which SDKs can use the package, and pub picks dependency versions whose own SDK constraints fit. As a language selector, its **lower bound** sets the package's default **language version**: 3.8 here. Code is compiled with 3.8 semantics even on a 3.13 SDK, so dot shorthands (3.10) or primary constructors (3.13) are errors until you raise the bound. A single library can opt into another version with `// @dart = 3.6`, a `//` comment placed before any code, usually to keep one file on an older version during a migration. The SDK constraint is mandatory: without it `dart pub get` fails.
code
yaml · 6 linesname: ledger
environment:
# Language version 3.13 for every library in this package
sdk: ^3.13.0
# Checked only under the flutter tool
flutter: '>=3.47.0'go deeper
Know that environment sdk is required and that its lower bound, not your installed SDK, decides which language features you can use.
Explain the two jobs of the SDK constraint and the rules for a per-file // @dart override.
Plan lower-bound bumps as reviewed changes, weighing new features and formatter changes against dropping consumers on older SDKs.
Set an org-wide SDK floor policy so shared packages move language versions together without stranding apps on older toolchains.
## One SDK, many language versions A single Dart SDK supports several **language versions** at once: its own and every earlier version within the same major line that it still supports. The compiler decides which version each library targets and interprets it with that version's rules. This is how Dart ships changes that would break existing code (null safety was the famous one) without breaking packages that have not migrated. Language versions are **major.minor**. A patch release never changes the language, so SDK 3.13.4 speaks language 3.13. ## The `environment` block ```yaml environment: sdk: ^3.8.0 ``` The SDK constraint does two separate jobs: 1. **Compatibility.** It says which SDK releases can use the package. Pub uses it when solving: it looks for the newest version of each dependency whose own SDK constraint accepts the SDK you are running. 2. **Language selection.** The **lower bound** of the constraint (here 3.8) becomes the package's **default language version** for every library in it. The second job surprises people. Upgrading Flutter to one bundling Dart 3.13 does **not** give your code 3.13 features. With `sdk: ^3.8.0`, 3.10's dot shorthands or 3.13's primary constructors are compile errors until you raise the lower bound, as the changelog for each feature says ("set your package's SDK constraint lower bound to 3.13 or greater"). The same mechanism drives `dart format`, which picks its style based on each file's language version. | pubspec lower bound | Language version | Can use dot shorthands (3.10)? | |---|---|---| | `^3.8.0` | 3.8 | no | | `^3.10.0` | 3.10 | yes | | `^3.13.0` | 3.13 | yes, plus primary constructors | ## Rules and history for the constraint - **Mandatory.** A pubspec with no SDK constraint makes `dart pub get` fail with a "no lower-bound SDK constraint" message. - **Caret allowed since 2.19.** Earlier SDKs required a full range such as `'>=2.12.0 <3.0.0'`. - **The old `<3.0.0` ceiling.** Dart 3 reads a constraint with a lower bound of 2.12 or higher and an upper bound of `<3.0.0` as `<4.0.0`, so null-safe packages kept working. - **Flutter constraints.** An `environment: flutter:` entry constrains the Flutter SDK; pub checks it only when running under the `flutter` tool. From language version 3.9 its upper bound is respected in the root package; older docs describe only the lower bound being enforced. ## Per-library override: `// @dart` By default every library in a package uses the package's language version. One library can select a different one with a special comment: ```dart // Legacy parser, kept on 3.6 until the formatter change is reviewed. // @dart = 3.6 import 'dart:convert'; ``` The rules are strict: - it must be a `//` comment, not `///` or `/* */`; - it must appear **before any Dart code**, though other comments may precede it; - the value is **major.minor** only. Its classic use was the null-safety migration, when files moved one at a time. Today it is mainly a temporary pin for a file you are not ready to move to a newer version's rules. ## Raising the bound safely 1. Raise the lower bound deliberately, as a reviewed change, because it also drops support for older SDKs. 2. Run `dart analyze` and the formatter; some language versions change inference or formatting. 3. For a published package, remember that the new lower bound excludes consumers on older SDKs.
- A Flutter team upgraded to an SDK bundling Dart 3.13, but `class Point(var int x, var int y);` still fails to compile. Why?Primary constructors need language version 3.13, and the language version comes from the pubspec's SDK lower bound, not the installed SDK. With `sdk: ^3.8.0` the code is compiled as 3.8. Raising the lower bound to `^3.13.0` enables the feature.
- In Dart, where must a `// @dart = 3.6` comment go for it to take effect?In a `//` comment before any Dart code in the library, such as imports or declarations; other comments may come before it. A `///` doc comment or a block comment does not count, and the version is written as major.minor only.
saying these in an interview costs you the question
- The installed SDK version decides which language features compile
- The upper bound of the SDK constraint sets the language version
- // @dart can appear anywhere in the file
- A patch release like 3.13.4 adds language features
- Omitting the SDK constraint means any SDK is accepted