mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 15:51:07 +01:00
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:
+24
-24
@@ -24,14 +24,14 @@ impl DD as Y {}
|
||||
impl DD as W {}
|
||||
|
||||
// CC requires D to implement Y.
|
||||
class CC(D:! Y) {}
|
||||
class CC(D: Y) {}
|
||||
|
||||
interface Z {}
|
||||
|
||||
// The `D` interface provides `Y` but not `W`, so we need to see that the
|
||||
// parameter to `CC` is `DD` which provides `Y & W`, not just a FacetValue
|
||||
// abstractly providing `Y.
|
||||
impl forall [E:! Y & W] CC(E) as Z {}
|
||||
impl forall [E: Y & W] CC(E) as Z {}
|
||||
|
||||
fn F() {
|
||||
(CC(DD)) as Z;
|
||||
@@ -137,20 +137,20 @@ fn F() {
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %CC.ref: %CC.type = name_ref CC, file.%CC.decl [concrete = constants.%CC.generic]
|
||||
// CHECK:STDOUT: %E.ref: %facet_type = name_ref E, %E.loc19_15.1 [symbolic = %E.loc19_15.2 (constants.%E)]
|
||||
// CHECK:STDOUT: %E.as_type.loc19_29.1: type = facet_access_type %E.ref [symbolic = %E.as_type.loc19_29.2 (constants.%E.as_type)]
|
||||
// CHECK:STDOUT: %Y.facet.loc19_29.1: %Y.type = facet_value %E.as_type.loc19_29.1, (constants.%Y.lookup_impl_witness) [symbolic = %Y.facet.loc19_29.2 (constants.%Y.facet.18f)]
|
||||
// CHECK:STDOUT: %.loc19_29: %Y.type = converted %E.ref, %Y.facet.loc19_29.1 [symbolic = %Y.facet.loc19_29.2 (constants.%Y.facet.18f)]
|
||||
// CHECK:STDOUT: %CC.loc19_29.1: type = class_type @CC, @CC(constants.%Y.facet.18f) [symbolic = %CC.loc19_29.2 (constants.%CC.db5)]
|
||||
// CHECK:STDOUT: %E.as_type.loc19_28.1: type = facet_access_type %E.ref [symbolic = %E.as_type.loc19_28.2 (constants.%E.as_type)]
|
||||
// CHECK:STDOUT: %Y.facet.loc19_28.1: %Y.type = facet_value %E.as_type.loc19_28.1, (constants.%Y.lookup_impl_witness) [symbolic = %Y.facet.loc19_28.2 (constants.%Y.facet.18f)]
|
||||
// CHECK:STDOUT: %.loc19_28: %Y.type = converted %E.ref, %Y.facet.loc19_28.1 [symbolic = %Y.facet.loc19_28.2 (constants.%Y.facet.18f)]
|
||||
// CHECK:STDOUT: %CC.loc19_28.1: type = class_type @CC, @CC(constants.%Y.facet.18f) [symbolic = %CC.loc19_28.2 (constants.%CC.db5)]
|
||||
// CHECK:STDOUT: %Z.ref: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]
|
||||
// CHECK:STDOUT: %.loc19_20.1: type = splice_block %.loc19_20.3 [concrete = constants.%facet_type] {
|
||||
// CHECK:STDOUT: %.loc19_19.1: type = splice_block %.loc19_19.3 [concrete = constants.%facet_type] {
|
||||
// CHECK:STDOUT: %.Self.frozen: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.frozen]
|
||||
// CHECK:STDOUT: %Y.ref: type = name_ref Y, file.%Y.decl [concrete = constants.%Y.type]
|
||||
// CHECK:STDOUT: %W.ref: type = name_ref W, file.%W.decl [concrete = constants.%W.type]
|
||||
// CHECK:STDOUT: %impl.elem0: %.d56 = impl_witness_access constants.%BitAndWith.impl_witness, element0 [concrete = constants.%type.as.BitAndWith.impl.Op]
|
||||
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %Y.ref, %impl.elem0 [concrete = constants.%type.as.BitAndWith.impl.Op.bound]
|
||||
// CHECK:STDOUT: %type.as.BitAndWith.impl.Op.call: init type = call %bound_method(%Y.ref, %W.ref) [concrete = constants.%facet_type]
|
||||
// CHECK:STDOUT: %.loc19_20.2: type = value_of_initializer %type.as.BitAndWith.impl.Op.call [concrete = constants.%facet_type]
|
||||
// CHECK:STDOUT: %.loc19_20.3: type = converted %type.as.BitAndWith.impl.Op.call, %.loc19_20.2 [concrete = constants.%facet_type]
|
||||
// CHECK:STDOUT: %.loc19_19.2: type = value_of_initializer %type.as.BitAndWith.impl.Op.call [concrete = constants.%facet_type]
|
||||
// CHECK:STDOUT: %.loc19_19.3: type = converted %type.as.BitAndWith.impl.Op.call, %.loc19_19.2 [concrete = constants.%facet_type]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %E.loc19_15.1: %facet_type = symbolic_binding E, 0 [symbolic = %E.loc19_15.2 (constants.%E)]
|
||||
// CHECK:STDOUT: }
|
||||
@@ -217,21 +217,21 @@ fn F() {
|
||||
// CHECK:STDOUT: generic impl @CC.as.Z.impl(%E.loc19_15.1: %facet_type) {
|
||||
// CHECK:STDOUT: %E.patt.loc19_15.2: %pattern_type.bd4 = symbolic_binding_pattern E, 0 [symbolic = %E.patt.loc19_15.2 (constants.%E.patt)]
|
||||
// CHECK:STDOUT: %E.loc19_15.2: %facet_type = symbolic_binding E, 0 [symbolic = %E.loc19_15.2 (constants.%E)]
|
||||
// CHECK:STDOUT: %E.as_type.loc19_29.2: type = facet_access_type %E.loc19_15.2 [symbolic = %E.as_type.loc19_29.2 (constants.%E.as_type)]
|
||||
// CHECK:STDOUT: %E.as_type.loc19_28.2: type = facet_access_type %E.loc19_15.2 [symbolic = %E.as_type.loc19_28.2 (constants.%E.as_type)]
|
||||
// CHECK:STDOUT: %Y.lookup_impl_witness: <witness> = lookup_impl_witness %E.loc19_15.2, @Y [symbolic = %Y.lookup_impl_witness (constants.%Y.lookup_impl_witness)]
|
||||
// CHECK:STDOUT: %Y.facet.loc19_29.2: %Y.type = facet_value %E.as_type.loc19_29.2, (%Y.lookup_impl_witness) [symbolic = %Y.facet.loc19_29.2 (constants.%Y.facet.18f)]
|
||||
// CHECK:STDOUT: %CC.loc19_29.2: type = class_type @CC, @CC(%Y.facet.loc19_29.2) [symbolic = %CC.loc19_29.2 (constants.%CC.db5)]
|
||||
// CHECK:STDOUT: %Z.impl_witness.loc19_36.2: <witness> = impl_witness %Z.impl_witness_table, @CC.as.Z.impl(%E.loc19_15.2) [symbolic = %Z.impl_witness.loc19_36.2 (constants.%Z.impl_witness.6a9)]
|
||||
// CHECK:STDOUT: %Y.facet.loc19_28.2: %Y.type = facet_value %E.as_type.loc19_28.2, (%Y.lookup_impl_witness) [symbolic = %Y.facet.loc19_28.2 (constants.%Y.facet.18f)]
|
||||
// CHECK:STDOUT: %CC.loc19_28.2: type = class_type @CC, @CC(%Y.facet.loc19_28.2) [symbolic = %CC.loc19_28.2 (constants.%CC.db5)]
|
||||
// CHECK:STDOUT: %Z.impl_witness.loc19_35.2: <witness> = impl_witness %Z.impl_witness_table, @CC.as.Z.impl(%E.loc19_15.2) [symbolic = %Z.impl_witness.loc19_35.2 (constants.%Z.impl_witness.6a9)]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !definition:
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: impl: %CC.loc19_29.1 as %Z.ref {
|
||||
// CHECK:STDOUT: impl: %CC.loc19_28.1 as %Z.ref {
|
||||
// CHECK:STDOUT: %Z.impl_witness_table = impl_witness_table (), @CC.as.Z.impl [concrete]
|
||||
// CHECK:STDOUT: %Z.impl_witness.loc19_36.1: <witness> = impl_witness %Z.impl_witness_table, @CC.as.Z.impl(constants.%E) [symbolic = %Z.impl_witness.loc19_36.2 (constants.%Z.impl_witness.6a9)]
|
||||
// CHECK:STDOUT: %Z.impl_witness.loc19_35.1: <witness> = impl_witness %Z.impl_witness_table, @CC.as.Z.impl(constants.%E) [symbolic = %Z.impl_witness.loc19_35.2 (constants.%Z.impl_witness.6a9)]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: extend %Z.ref
|
||||
// CHECK:STDOUT: witness = %Z.impl_witness.loc19_36.1
|
||||
// CHECK:STDOUT: witness = %Z.impl_witness.loc19_35.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -306,11 +306,11 @@ fn F() {
|
||||
// CHECK:STDOUT: specific @CC.as.Z.impl(constants.%E) {
|
||||
// CHECK:STDOUT: %E.patt.loc19_15.2 => constants.%E.patt
|
||||
// CHECK:STDOUT: %E.loc19_15.2 => constants.%E
|
||||
// CHECK:STDOUT: %E.as_type.loc19_29.2 => constants.%E.as_type
|
||||
// CHECK:STDOUT: %E.as_type.loc19_28.2 => constants.%E.as_type
|
||||
// CHECK:STDOUT: %Y.lookup_impl_witness => constants.%Y.lookup_impl_witness
|
||||
// CHECK:STDOUT: %Y.facet.loc19_29.2 => constants.%Y.facet.18f
|
||||
// CHECK:STDOUT: %CC.loc19_29.2 => constants.%CC.db5
|
||||
// CHECK:STDOUT: %Z.impl_witness.loc19_36.2 => constants.%Z.impl_witness.6a9
|
||||
// CHECK:STDOUT: %Y.facet.loc19_28.2 => constants.%Y.facet.18f
|
||||
// CHECK:STDOUT: %CC.loc19_28.2 => constants.%CC.db5
|
||||
// CHECK:STDOUT: %Z.impl_witness.loc19_35.2 => constants.%Z.impl_witness.6a9
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: specific @Z.WithSelf(constants.%Z.facet.674) {
|
||||
@@ -325,11 +325,11 @@ fn F() {
|
||||
// CHECK:STDOUT: specific @CC.as.Z.impl(constants.%facet_value) {
|
||||
// CHECK:STDOUT: %E.patt.loc19_15.2 => constants.%E.patt
|
||||
// CHECK:STDOUT: %E.loc19_15.2 => constants.%facet_value
|
||||
// CHECK:STDOUT: %E.as_type.loc19_29.2 => constants.%DD
|
||||
// CHECK:STDOUT: %E.as_type.loc19_28.2 => constants.%DD
|
||||
// CHECK:STDOUT: %Y.lookup_impl_witness => constants.%Y.impl_witness
|
||||
// CHECK:STDOUT: %Y.facet.loc19_29.2 => constants.%Y.facet.2a4
|
||||
// CHECK:STDOUT: %CC.loc19_29.2 => constants.%CC.d62
|
||||
// CHECK:STDOUT: %Z.impl_witness.loc19_36.2 => constants.%Z.impl_witness.b3a
|
||||
// CHECK:STDOUT: %Y.facet.loc19_28.2 => constants.%Y.facet.2a4
|
||||
// CHECK:STDOUT: %CC.loc19_28.2 => constants.%CC.d62
|
||||
// CHECK:STDOUT: %Z.impl_witness.loc19_35.2 => constants.%Z.impl_witness.b3a
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !definition:
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
Reference in New Issue
Block a user