Replace :! binding syntax with phase keywords and contextual defaults (#7479)

Implement the toolchain side of proposal #7254, removing the `:!`
binding
syntax for generic and template parameters in favor of the keywords
`generic`,
`template`, and `runtime` plus contextual defaults for phase.

For valid programs this is semantics-preserving: each binding resolves
to the
same phase, and produces the same SemIR, as it did under `:!`/`:`. The
parser
derives a binding's phase from its syntactic context plus any explicit
phase
keyword; new diagnostics and error recovery for misused keywords are
described
below.

Implementation details for each component:

- Lexer: remove the `:!` (`ColonExclaim`) token, move its virtual
parse-node
  budget onto `:`, and add the `generic` and `runtime` keywords.
- Parser: thread a `BindingContext` (`ExplicitParam`, `DeducedParam`, or
`CompileTimeEntityParam`) from declaration introducers down through
parameter
lists to each binding pattern, using a one-token lookahead to
distinguish a
name-qualifier parameter list from a declaration's own final list.
Parameters
of a compile-time entity (`class`, `interface`, `constraint`, `choice`,
`alias`, `export`, `namespace`) and deduced `[]` parameters default to
checked
generic; explicit function parameters and local bindings default to
runtime.
`HandleBindingPattern` resolves the phase from that context plus the
keyword: a
`generic` keyword needs no node of its own (the phase is carried by the
  binding's node kind), while a `runtime` keyword is preserved as a
`RuntimeBindingName` node so `check` can name it in a diagnostic. A
phase
keyword that is merely redundant with the contextual default is
diagnosed
  here, without invalidating the parse tree.
- Check: a phase keyword that is invalid for its context (for example
`runtime`
on a checked-generic parameter) is diagnosed here, and recovers by
building an
error binding that still introduces the name so that later uses of it do
not
  produce cascading errors.

The removed `:!` syntax is now rejected as an ordinary parse error.

The `form`/`:?`/`->?` ("extended types") portion of proposal #7254 is
left for a
separate change.

Assisted-by: Claude Code
This commit is contained in:
Chandler Carruth
2026-07-11 01:22:44 +00:00
committed by GitHub
parent bf106c3b4b
commit 8be274cf60
482 changed files with 16917 additions and 16226 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
choice SomeChoice(T:! type) {
choice SomeChoice(T: type) {
Val1,
Val2(a: i32, b: array(T, 5), t: T),
Val3
+1 -1
View File
@@ -4,7 +4,7 @@
// This is a comment.
// Comment with whitespace.
// class C; fn F[T:! A](a: T) -> i32 { return 86; }
// class C; fn F[T: A](a: T) -> i32 { return 86; }
//@dump-sem-ir-begin
//@dump-sem-ir-end
//@dump-sem-ir-
@@ -5,14 +5,14 @@
fn F;
fn F1();
fn Func(a: i32, b: A);
fn Generic[T:! type, U:! I](a: T, b: U) -> U;
fn Generic[T: type, U: I](a: T, b: U) -> U;
fn Lambda(a: i32) -> i32 => return a + 5;
fn
MultiLine[
A:! type,
B:! C1,
C:! C2
A: type,
B: C1,
C: C2
](a: A(B, C),
b: B,
c: i32);
@@ -23,17 +23,17 @@ a: A;
a: A = (b as A);
a: i32;
a: array(A, 5);
a:! type;
a:! T = b;
generic a: type;
generic a: T = b;
a: A in some_list;
var a: T;
let b: T;
binding: T;
binding:! T;
generic binding: T;
var
multiline: T;
fn F(ref a: A, const ref b:! B);
fn F(ref a: A, const ref b: B);
fn F() -> T;
fn F() -> T.U { return val; }
fn F() -> i32 => return val;
+1 -1
View File
@@ -6,7 +6,7 @@
package Carbon api;
interface HasValueParam(T:! type, V:! T) {
interface HasValueParam(T: type, V: T) {
fn Go(self) -> T;
}
+3 -3
View File
@@ -3,14 +3,14 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
class C1;
class C2(T1:! type, T2:! C1) {}
class C2(T1: type, T2: C1) {}
class C3 {
extend base: C1;
}
class
(C4(
(T1:! type),
T2:!
(T1: type),
T2:
(A.(B(E, F(G)).C)
.D))) ;
+2 -2
View File
@@ -607,7 +607,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT.
</dict>
<dict>
<key>match</key>
<string>\b(and|as|impls|in|like|not|or|partial|ref|template|where)\b</string>
<string>\b(and|as|generic|impls|in|like|not|or|partial|ref|runtime|template|where)\b</string>
<key>name</key>
<string>keyword.control.carbon</string>
</dict>
@@ -797,7 +797,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT.
</dict>
<dict>
<key>begin</key>
<string>:!?</string>
<string>:</string>
<key>comment</key>
<string>Matches types in bindings.</string>
<key>end</key>
+2 -2
View File
@@ -226,7 +226,7 @@
},
{
"comment": "Matches types in bindings.",
"begin": ":!?",
"begin": ":",
"end": "(?=([;{=]|->|in|where))",
"patterns": [
{ "include": "#common" },
@@ -346,7 +346,7 @@
},
{
"name": "keyword.control.carbon",
"match": "\\b(and|as|impls|in|like|not|or|partial|ref|template|where)\\b"
"match": "\\b(and|as|generic|impls|in|like|not|or|partial|ref|runtime|template|where)\\b"
}
]
},