Handle parsing of require...impls declarations (#6255)

Check is not implemented yet, but some tests are added.
This commit is contained in:
Dana Jansens
2025-10-23 18:34:52 +00:00
committed by GitHub
parent 4f1f0fc7c2
commit 26381f6eaf
30 changed files with 790 additions and 61 deletions
+2 -2
View File
@@ -54,7 +54,7 @@ auto HandleParseNode(Context& context, Parse::ForallId /*node_id*/) -> bool {
return true;
}
auto HandleParseNode(Context& context, Parse::TypeImplAsId node_id) -> bool {
auto HandleParseNode(Context& context, Parse::ImplTypeAsId node_id) -> bool {
auto [self_node, self_id] = context.node_stack().PopExprWithNodeId();
auto self_type_inst_id = ExprAsType(context, self_node, self_id).inst_id;
context.node_stack().Push(node_id, self_type_inst_id);
@@ -67,7 +67,7 @@ auto HandleParseNode(Context& context, Parse::TypeImplAsId node_id) -> bool {
return true;
}
auto HandleParseNode(Context& context, Parse::DefaultSelfImplAsId node_id)
auto HandleParseNode(Context& context, Parse::ImplDefaultSelfAsId node_id)
-> bool {
auto self_inst_id = SemIR::TypeInstId::None;
+30
View File
@@ -0,0 +1,30 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "toolchain/check/context.h"
#include "toolchain/check/handle.h"
#include "toolchain/parse/node_ids.h"
namespace Carbon::Check {
auto HandleParseNode(Context& context, Parse::RequireIntroducerId node_id)
-> bool {
return context.TODO(node_id, "require");
}
auto HandleParseNode(Context& context, Parse::RequireDefaultSelfImplsId node_id)
-> bool {
return context.TODO(node_id, "require");
}
auto HandleParseNode(Context& context, Parse::RequireTypeImplsId node_id)
-> bool {
return context.TODO(node_id, "require");
}
auto HandleParseNode(Context& context, Parse::RequireDeclId node_id) -> bool {
return context.TODO(node_id, "require");
}
} // namespace Carbon::Check
+2 -2
View File
@@ -433,7 +433,7 @@ static auto ExtendImpl(Context& context, Parse::NodeId extend_node,
const auto& impl = context.impls().Get(impl_id);
if (context.parse_tree().node_kind(self_type_node_id) ==
Parse::NodeKind::TypeImplAs) {
Parse::NodeKind::ImplTypeAs) {
CARBON_DIAGNOSTIC(ExtendImplSelfAs, Error,
"cannot `extend` an `impl` with an explicit self type");
auto diag = context.emitter().Build(extend_node, ExtendImplSelfAs);
@@ -448,7 +448,7 @@ static auto ExtendImpl(Context& context, Parse::NodeId extend_node,
// The explicit self type is the same as the default self type, so suggest
// removing it and recover as if it were not present.
if (auto self_as =
context.parse_tree_and_subtrees().ExtractAs<Parse::TypeImplAs>(
context.parse_tree_and_subtrees().ExtractAs<Parse::ImplTypeAs>(
self_type_node_id)) {
CARBON_DIAGNOSTIC(ExtendImplSelfAsDefault, Note,
"remove the explicit `Self` type here");
+4 -4
View File
@@ -461,17 +461,17 @@ static auto CheckRedeclParamSyntax(Context& context,
// https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p3763.md#redeclarations
auto new_node_kind = context.parse_tree().node_kind(new_node_id);
auto prev_node_kind = context.parse_tree().node_kind(prev_node_id);
if (new_node_kind == Parse::NodeKind::DefaultSelfImplAs &&
if (new_node_kind == Parse::NodeKind::ImplDefaultSelfAs &&
prev_node_kind == Parse::NodeKind::SelfTypeNameExpr &&
context.parse_tree().node_kind(prev_iter[1]) ==
Parse::NodeKind::TypeImplAs) {
Parse::NodeKind::ImplTypeAs) {
++prev_iter;
continue;
}
if (prev_node_kind == Parse::NodeKind::DefaultSelfImplAs &&
if (prev_node_kind == Parse::NodeKind::ImplDefaultSelfAs &&
new_node_kind == Parse::NodeKind::SelfTypeNameExpr &&
context.parse_tree().node_kind(new_iter[1]) ==
Parse::NodeKind::TypeImplAs) {
Parse::NodeKind::ImplTypeAs) {
++new_iter;
continue;
}
+3
View File
@@ -523,6 +523,9 @@ class NodeStack {
case Parse::NodeKind::ParenExprStart:
case Parse::NodeKind::PatternListComma:
case Parse::NodeKind::Placeholder:
case Parse::NodeKind::RequireIntroducer:
case Parse::NodeKind::RequireDefaultSelfImpls:
case Parse::NodeKind::RequireTypeImpls:
case Parse::NodeKind::RequirementAnd:
case Parse::NodeKind::RequirementEqual:
case Parse::NodeKind::RequirementEqualEqual:
+54
View File
@@ -0,0 +1,54 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/require_invalid.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/require_invalid.carbon
// --- fail_todo_require_outside_scope.carbon
library "[[@TEST_NAME]]";
interface Y {}
// CHECK:STDERR: fail_todo_require_outside_scope.carbon:[[@LINE+4]]:1: error: semantics TODO: `require` [SemanticsTodo]
// CHECK:STDERR: require impls Y;
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
require impls Y;
// --- fail_todo_require_in_class.carbon
library "[[@TEST_NAME]]";
interface Y {}
class C {
// TODO: require is not allowed outside of `interface` or `constraint`.
// CHECK:STDERR: fail_todo_require_in_class.carbon:[[@LINE+4]]:3: error: semantics TODO: `require` [SemanticsTodo]
// CHECK:STDERR: require impls Y;
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
require impls Y;
}
// --- fail_require_in_fn.carbon
library "[[@TEST_NAME]]";
interface Y {}
fn F() {
// require is not allowed outside of `interface` or `constraint`.
// CHECK:STDERR: fail_require_in_fn.carbon:[[@LINE+8]]:3: error: expected expression [ExpectedExpr]
// CHECK:STDERR: require impls Y;
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
// CHECK:STDERR: fail_require_in_fn.carbon:[[@LINE+4]]:3: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo]
// CHECK:STDERR: require impls Y;
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
require impls Y;
}
+275
View File
@@ -0,0 +1,275 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interface/require.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interface/require.carbon
// --- fail_todo_implicit_self_impls.carbon
library "[[@TEST_NAME]]";
interface Y {
fn YY();
}
//@dump-sem-ir-begin
interface Z {
// CHECK:STDERR: fail_todo_implicit_self_impls.carbon:[[@LINE+4]]:3: error: semantics TODO: `require` [SemanticsTodo]
// CHECK:STDERR: require impls Y;
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
require impls Y;
}
//@dump-sem-ir-end
fn F(T:! Z) {
T.(Y.YY)();
}
// --- fail_todo_explicit_self_impls.carbon
library "[[@TEST_NAME]]";
interface Y {
fn YY();
}
//@dump-sem-ir-begin
interface Z {
// CHECK:STDERR: fail_todo_explicit_self_impls.carbon:[[@LINE+4]]:3: error: semantics TODO: `require` [SemanticsTodo]
// CHECK:STDERR: require Self impls Y;
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
require Self impls Y;
}
//@dump-sem-ir-end
fn F(T:! Z) {
T.(Y.YY)();
}
// --- fail_todo_implicit_self_no_extend_name_lookup_fails.carbon
library "[[@TEST_NAME]]";
interface Y {
fn YY();
}
interface Z {
// CHECK:STDERR: fail_todo_implicit_self_no_extend_name_lookup_fails.carbon:[[@LINE+4]]:3: error: semantics TODO: `require` [SemanticsTodo]
// CHECK:STDERR: require impls Y;
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
require impls Y;
}
fn F(T:! Z) {
// TODO: This should fail name lookup since Z does not extend Y.
T.YY();
}
// --- fail_todo_explicit_self_no_extend_name_lookup_fails.carbon
library "[[@TEST_NAME]]";
interface Y {
fn YY();
}
interface Z {
// CHECK:STDERR: fail_todo_explicit_self_no_extend_name_lookup_fails.carbon:[[@LINE+4]]:3: error: semantics TODO: `require` [SemanticsTodo]
// CHECK:STDERR: require Self impls Y;
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
require Self impls Y;
}
fn F(T:! Z) {
// TODO: This should fail name lookup since Z does not extend Y.
T.YY();
}
// --- fail_todo_explicit_self_specific_impls.carbon
library "[[@TEST_NAME]]";
interface Y {}
class C(T:! type);
//@dump-sem-ir-begin
interface Z {
// CHECK:STDERR: fail_todo_explicit_self_specific_impls.carbon:[[@LINE+4]]:3: error: semantics TODO: `require` [SemanticsTodo]
// CHECK:STDERR: require C(Self) impls Y;
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
require C(Self) impls Y;
}
//@dump-sem-ir-end
// --- fail_todo_impls_where.carbon
library "[[@TEST_NAME]]";
interface Y { let Y1:! type; }
//@dump-sem-ir-begin
interface Z {
// CHECK:STDERR: fail_todo_impls_where.carbon:[[@LINE+4]]:3: error: semantics TODO: `require` [SemanticsTodo]
// CHECK:STDERR: require impls Y where .Y1 = ();
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
require impls Y where .Y1 = ();
}
//@dump-sem-ir-end
// --- fail_todo_other_impls_with_self.carbon
library "[[@TEST_NAME]]";
interface Y {}
//@dump-sem-ir-begin
interface Z(T:! type) {
// CHECK:STDERR: fail_todo_other_impls_with_self.carbon:[[@LINE+4]]:3: error: semantics TODO: `require` [SemanticsTodo]
// CHECK:STDERR: require T impls Z(Self);
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
require T impls Z(Self);
}
//@dump-sem-ir-end
// --- fail_todo_other_impls_without_self.carbon
library "[[@TEST_NAME]]";
interface Y {}
//@dump-sem-ir-begin
interface Z(T:! type) {
// TODO: Either the type `T` or the facet type `Y` must mention `Self`, but
// they don't.
// CHECK:STDERR: fail_todo_other_impls_without_self.carbon:[[@LINE+4]]:3: error: semantics TODO: `require` [SemanticsTodo]
// CHECK:STDERR: require T impls Y;
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
require T impls Y;
}
//@dump-sem-ir-end
// --- fail_todo_extend.carbon
library "[[@TEST_NAME]]";
interface Y {
fn YY();
}
//@dump-sem-ir-begin
interface Z {
// CHECK:STDERR: fail_todo_extend.carbon:[[@LINE+4]]:10: error: semantics TODO: `require` [SemanticsTodo]
// CHECK:STDERR: extend require impls Y;
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
extend require impls Y;
}
//@dump-sem-ir-end
fn F(T:! Z) {
T.YY();
T.(Y.YY)();
}
// CHECK:STDOUT: --- fail_todo_implicit_self_impls.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @Z {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = <unexpected>.inst6000001D
// CHECK:STDOUT: witness = invalid
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_explicit_self_impls.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @Z {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = <unexpected>.inst5000001D
// CHECK:STDOUT: witness = invalid
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_explicit_self_specific_impls.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @Z {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = <unexpected>.inst68000023
// CHECK:STDOUT: witness = invalid
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_impls_where.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @Z {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = <unexpected>.inst5800001A
// CHECK:STDOUT: witness = invalid
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_other_impls_with_self.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic interface @Z(<unexpected>.inst78000017.loc6_13: type) {
// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)]
// CHECK:STDOUT:
// CHECK:STDOUT: interface {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = <unexpected>.inst78000021
// CHECK:STDOUT: witness = invalid
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Z(constants.%T) {
// CHECK:STDOUT: %T => constants.%T
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_other_impls_without_self.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic interface @Z(<unexpected>.inst44000017.loc6_13: type) {
// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)]
// CHECK:STDOUT:
// CHECK:STDOUT: interface {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = <unexpected>.inst44000021
// CHECK:STDOUT: witness = invalid
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @Z(constants.%T) {
// CHECK:STDOUT: %T => constants.%T
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_extend.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @Z {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = <unexpected>.inst6400001D
// CHECK:STDOUT: witness = invalid
// CHECK:STDOUT: }
// CHECK:STDOUT:
+1 -5
View File
@@ -43,11 +43,7 @@ library "[[@TEST_NAME]]";
interface Z {}
constraint E {
// CHECK:STDERR: fail_todo_unspecified.carbon:[[@LINE+8]]:3: error: unrecognized declaration introducer [UnrecognizedDecl]
// CHECK:STDERR: require impls Z;
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
// CHECK:STDERR: fail_todo_unspecified.carbon:[[@LINE+4]]:3: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo]
// CHECK:STDERR: fail_todo_unspecified.carbon:[[@LINE+4]]:3: error: semantics TODO: `require` [SemanticsTodo]
// CHECK:STDERR: require impls Z;
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
@@ -162,6 +162,7 @@ CARBON_DIAGNOSTIC_KIND(ImplExpectedAfterForall)
CARBON_DIAGNOSTIC_KIND(ImplExpectedAs)
CARBON_DIAGNOSTIC_KIND(ExpectedAssociatedConstantIdentifier)
CARBON_DIAGNOSTIC_KIND(ExpectedAssociatedConstantColonExclaim)
CARBON_DIAGNOSTIC_KIND(RequireExpectedImpls)
// Alias diagnostics.
CARBON_DIAGNOSTIC_KIND(ExpectedAliasInitializer)
@@ -130,6 +130,8 @@ static constexpr auto DeclIntroducers = [] {
StateKind::TypeAfterIntroducerAsInterface);
set(Lex::TokenKind::Namespace, NodeKind::NamespaceStart,
StateKind::Namespace);
set(Lex::TokenKind::Require, NodeKind::RequireIntroducer,
StateKind::RequireAfterIntroducer);
set_contextual(Lex::TokenKind::Let, RegularContext, NodeKind::LetIntroducer,
StateKind::Let);
set_contextual(Lex::TokenKind::Let, ClassContext, NodeKind::LetIntroducer,
@@ -225,6 +227,7 @@ static auto ResolveAmbiguousTokenAsDeclaration(Context& context,
case Lex::TokenKind::Let:
case Lex::TokenKind::Library:
case Lex::TokenKind::Namespace:
case Lex::TokenKind::Require:
case Lex::TokenKind::Var:
#define CARBON_PARSE_NODE_KIND(Name)
#define CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Name) case Lex::TokenKind::Name:
+2 -2
View File
@@ -10,7 +10,7 @@ namespace Carbon::Parse {
static auto ExpectAsOrTypeExpression(Context& context) -> void {
if (context.PositionIs(Lex::TokenKind::As)) {
// as <expression> ...
context.AddLeafNode(NodeKind::DefaultSelfImplAs, context.Consume());
context.AddLeafNode(NodeKind::ImplDefaultSelfAs, context.Consume());
context.PushState(StateKind::Expr);
} else {
// <expression> as <expression>...
@@ -62,7 +62,7 @@ auto HandleImplAfterForall(Context& context) -> void {
auto HandleImplBeforeAs(Context& context) -> void {
auto state = context.PopState();
if (auto as = context.ConsumeIf(Lex::TokenKind::As)) {
context.AddNode(NodeKind::TypeImplAs, *as, state.has_error);
context.AddNode(NodeKind::ImplTypeAs, *as, state.has_error);
context.PushState(StateKind::Expr);
} else {
if (!state.has_error) {
+48
View File
@@ -0,0 +1,48 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "toolchain/parse/context.h"
#include "toolchain/parse/handle.h"
namespace Carbon::Parse {
auto HandleRequireAfterIntroducer(Context& context) -> void {
auto state = context.PopState();
state.kind = StateKind::RequireDecl;
context.PushState(state);
if (context.PositionIs(Lex::TokenKind::Impls)) {
// impls <expression> ...
context.AddLeafNode(NodeKind::RequireDefaultSelfImpls, context.Consume());
context.PushState(StateKind::Expr);
} else {
// <expression> impls <expression>...
context.PushState(StateKind::RequireBeforeImpls);
context.PushStateForExpr(PrecedenceGroup::ForRequirements());
}
}
auto HandleRequireBeforeImpls(Context& context) -> void {
auto state = context.PopState();
if (auto impls = context.ConsumeIf(Lex::TokenKind::Impls)) {
context.AddNode(NodeKind::RequireTypeImpls, *impls, state.has_error);
context.PushState(StateKind::Expr);
} else {
if (!state.has_error) {
CARBON_DIAGNOSTIC(RequireExpectedImpls, Error,
"expected `impls` in `require` declaration");
context.emitter().Emit(*context.position(), RequireExpectedImpls);
}
context.ReturnErrorOnState();
}
}
auto HandleRequireDecl(Context& context) -> void {
auto state = context.PopState();
context.AddNodeExpectingDeclSemi(state, NodeKind::RequireDecl,
Lex::TokenKind::Require,
/*is_def_allowed=*/false);
}
} // namespace Carbon::Parse
+15 -12
View File
@@ -15,18 +15,21 @@ namespace Carbon::Parse {
// #define CARBON_NODE_CATEGORY_FOR_XYZ(Name) ...
// CARBON_NODE_CATEGORY(CARBON_NODE_CATEGORY_FOR_XYZ)
// #undef CARBON_NODE_CATEGORY_FOR_XYZ
#define CARBON_NODE_CATEGORY(X) \
X(Decl) \
X(Expr) \
X(ImplAs) \
X(IntConst) \
X(MemberExpr) \
X(MemberName) \
X(Modifier) \
X(NonExprName) \
X(PackageName) \
X(Pattern) \
X(Requirement) \
#define CARBON_NODE_CATEGORY(X) \
X(Decl) \
X(Expr) \
/* `impl <type> as` or just `impl as` */ \
X(ImplAs) \
X(IntConst) \
X(MemberExpr) \
X(MemberName) \
X(Modifier) \
X(NonExprName) \
X(PackageName) \
X(Pattern) \
/* `require <type> impls` or just `require impls` */ \
X(RequireImpls) \
X(Requirement) \
X(Statement)
// We expect this to grow, so are using a bigger size than needed.
+1
View File
@@ -108,6 +108,7 @@ using AnyModifierId = NodeIdInCategory<NodeCategory::Modifier>;
using AnyPatternId = NodeIdInCategory<NodeCategory::Pattern>;
using AnyStatementId =
NodeIdInCategory<NodeCategory::Statement | NodeCategory::Decl>;
using AnyRequireImplsId = NodeIdInCategory<NodeCategory::RequireImpls>;
using AnyRequirementId = NodeIdInCategory<NodeCategory::Requirement>;
using AnyNonExprNameId = NodeIdInCategory<NodeCategory::NonExprName>;
using AnyPackageNameId = NodeIdInCategory<NodeCategory::PackageName>;
+7 -2
View File
@@ -367,8 +367,13 @@ CARBON_PARSE_NODE_KIND(ImplDefinitionStart)
CARBON_PARSE_NODE_KIND(ImplDefinition)
CARBON_PARSE_NODE_KIND(ImplDecl)
CARBON_PARSE_NODE_KIND(Forall)
CARBON_PARSE_NODE_KIND(TypeImplAs)
CARBON_PARSE_NODE_KIND(DefaultSelfImplAs)
CARBON_PARSE_NODE_KIND(ImplTypeAs)
CARBON_PARSE_NODE_KIND(ImplDefaultSelfAs)
CARBON_PARSE_NODE_KIND(RequireIntroducer)
CARBON_PARSE_NODE_KIND(RequireTypeImpls)
CARBON_PARSE_NODE_KIND(RequireDefaultSelfImpls)
CARBON_PARSE_NODE_KIND(RequireDecl)
CARBON_PARSE_NODE_KIND(NamedConstraintIntroducer)
CARBON_PARSE_NODE_KIND(NamedConstraintDefinitionStart)
+4
View File
@@ -58,6 +58,10 @@ class PrecedenceGroup {
// `impl` and `as`.
static auto ForImplAs() -> PrecedenceGroup;
// Get the precedence level at which to parse the type expression between
// `require` and `impls`.
static auto ForRequireImpls() -> PrecedenceGroup;
// Get the precedence level at which to parse expressions in requirements
// after `where` or `require`.
static auto ForRequirements() -> PrecedenceGroup;
+34 -2
View File
@@ -359,6 +359,10 @@ CARBON_PARSE_STATE(DeclNameAndParamsAfterParams)
// ^~~~~~~
// 1. Package
//
// require ...
// ^~~~~~~
// 1. RequireAfterIntroducer
//
// var ... (variant is Regular)
// ^~~
// 1. VarAsRegular
@@ -1336,7 +1340,7 @@ CARBON_PARSE_STATE(BaseDecl)
// ^~
// 1. Expr
// 2. DeclOrDefinitionAsImpl
// impl type_expression as ...
// impl TypeExpression as ...
// ^
// 1. Expr
// 2. ImplBeforeAs
@@ -1349,7 +1353,7 @@ CARBON_PARSE_STATE(ImplAfterIntroducer)
// impl forall [ ... ] as ...
// ^~
// 1. Expr
// impl forall [ ... ] type_expression as ...
// impl forall [ ... ] TypeExpression as ...
// ^
// 1. Expr
// 2. ImplBeforeAs
@@ -1363,6 +1367,34 @@ CARBON_PARSE_STATE(ImplAfterForall)
// 1. Expr
CARBON_PARSE_STATE(ImplBeforeAs)
// Handles processing of a `require...impls` declaration after the introducer.
//
// require impls ...
// ^~~~~
// 1. Expr
// 2. RequireDecl
// require TypeExpression impls ...
// ^
// 1. Expr
// 2. RequireBeforeImpls
// 3. RequireDecl
CARBON_PARSE_STATE(RequireAfterIntroducer)
// Handles processing of the `impls` in a `require` declaration after the type
// expression.
//
// require TypeExpression impls ...
// ^~~~~
// 1. Expr
CARBON_PARSE_STATE(RequireBeforeImpls)
// Handles processing of a completed `require` declaration.
//
// require TypeExpression impls FacetTypeExpression ;
// ^
// (state done)
CARBON_PARSE_STATE(RequireDecl)
// Handles the start of a `var` or `returned var` in a non-class context.
//
// var ... (variant is Regular)
+3 -3
View File
@@ -86,14 +86,14 @@ fn F() {
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 4},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'A'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'I'},
// CHECK:STDOUT: {kind: 'ImplDefinitionStart', text: '{', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ImplDefinition', text: '}', subtree_size: 6},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'FinalModifier', text: 'final'},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'A'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'I'},
// CHECK:STDOUT: {kind: 'ImplDefinitionStart', text: '{', subtree_size: 6},
// CHECK:STDOUT: {kind: 'ImplDefinition', text: '}', subtree_size: 7},
@@ -139,7 +139,7 @@ fn F() {
// CHECK:STDOUT: {kind: 'BaseDecl', text: ';', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'ExtendModifier', text: 'extend'},
// CHECK:STDOUT: {kind: 'DefaultSelfImplAs', text: 'as'},
// CHECK:STDOUT: {kind: 'ImplDefaultSelfAs', text: 'as'},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'I'},
// CHECK:STDOUT: {kind: 'ImplDecl', text: ';', subtree_size: 5},
// CHECK:STDOUT: {kind: 'NamespaceStart', text: 'namespace'},
+1 -1
View File
@@ -186,7 +186,7 @@ fn TestRecoveryFromSpuriousEquals();
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'T'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'I'},
// CHECK:STDOUT: {kind: 'ImplDefinitionStart', text: '{', subtree_size: 5},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
+1 -1
View File
@@ -17,7 +17,7 @@ impl i32 as Interface {
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Interface'},
// CHECK:STDOUT: {kind: 'ImplDefinitionStart', text: '{', subtree_size: 5},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
+5 -5
View File
@@ -26,23 +26,23 @@ class C {
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'C'},
// CHECK:STDOUT: {kind: 'ClassDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'DefaultSelfImplAs', text: 'as'},
// CHECK:STDOUT: {kind: 'ImplDefaultSelfAs', text: 'as'},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'ForwardDeclared'},
// CHECK:STDOUT: {kind: 'ImplDecl', text: ';', subtree_size: 4},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'C'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'ExplicitType'},
// CHECK:STDOUT: {kind: 'ImplDefinitionStart', text: '{', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ImplDefinition', text: '}', subtree_size: 6},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'SelfTypeNameExpr', text: 'Self'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'ExplicitSelf'},
// CHECK:STDOUT: {kind: 'ImplDecl', text: ';', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'ExtendModifier', text: 'extend'},
// CHECK:STDOUT: {kind: 'DefaultSelfImplAs', text: 'as'},
// CHECK:STDOUT: {kind: 'ImplDefaultSelfAs', text: 'as'},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'ExtendImpl'},
// CHECK:STDOUT: {kind: 'ImplDefinitionStart', text: '{', subtree_size: 5},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
@@ -54,7 +54,7 @@ class C {
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'ExtendModifier', text: 'extend'},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'C'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'InvalidButDiagnosedInCheck'},
// CHECK:STDOUT: {kind: 'ImplDecl', text: ';', subtree_size: 6},
// CHECK:STDOUT: {kind: 'ClassDefinition', text: '}', subtree_size: 36},
+1 -1
View File
@@ -15,7 +15,7 @@ impl bool as Interface;
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'BoolTypeLiteral', text: 'bool'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Interface'},
// CHECK:STDOUT: {kind: 'ImplDecl', text: ';', subtree_size: 5},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
+1 -1
View File
@@ -16,7 +16,7 @@ impl str as Interface {
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'StringTypeLiteral', text: 'str'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Interface'},
// CHECK:STDOUT: {kind: 'ImplDefinitionStart', text: '{', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ImplDefinition', text: '}', subtree_size: 6},
+4 -4
View File
@@ -108,12 +108,12 @@ impl
// CHECK:STDOUT: {kind: 'ImplDecl', text: ';', has_error: yes, subtree_size: 3},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
// CHECK:STDOUT: {kind: 'ImplDecl', text: ';', has_error: yes, subtree_size: 5},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'BoolTypeLiteral', text: 'bool'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'bar'},
// CHECK:STDOUT: {kind: 'ImplDecl', text: ';', has_error: yes, subtree_size: 5},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
@@ -146,7 +146,7 @@ impl
// CHECK:STDOUT: {kind: 'Forall', text: 'forall'},
// CHECK:STDOUT: {kind: 'InvalidParse', text: 'f16', has_error: yes},
// CHECK:STDOUT: {kind: 'FloatTypeLiteral', text: 'f16'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Quux'},
// CHECK:STDOUT: {kind: 'ImplDecl', text: ';', has_error: yes, subtree_size: 7},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
@@ -178,7 +178,7 @@ impl
// CHECK:STDOUT: {kind: 'CompileTimeBindingPattern', text: ':!', subtree_size: 4},
// CHECK:STDOUT: {kind: 'ImplicitParamList', text: ']', subtree_size: 6},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'T'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Interface'},
// CHECK:STDOUT: {kind: 'ImplDecl', text: ';', has_error: yes, subtree_size: 12},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
@@ -50,7 +50,7 @@ fn C.(Self as Interface).F() {}
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 9},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'BoolTypeLiteral', text: 'bool'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Interface'},
// CHECK:STDOUT: {kind: 'ImplDefinitionStart', text: '{', subtree_size: 5},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
@@ -67,7 +67,7 @@ fn C.(Self as Interface).F() {}
// CHECK:STDOUT: {kind: 'ClassDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'SelfTypeNameExpr', text: 'Self'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Interface'},
// CHECK:STDOUT: {kind: 'ImplDefinitionStart', text: '{', subtree_size: 5},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
+2 -2
View File
@@ -25,7 +25,7 @@ impl forall [T:! type, U:! Interface] U as Interface(T) {
// CHECK:STDOUT: {kind: 'CompileTimeBindingPattern', text: ':!', subtree_size: 4},
// CHECK:STDOUT: {kind: 'ImplicitParamList', text: ']', subtree_size: 6},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'T'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Interface'},
// CHECK:STDOUT: {kind: 'ImplDecl', text: ';', subtree_size: 12},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
@@ -42,7 +42,7 @@ impl forall [T:! type, U:! Interface] U as Interface(T) {
// CHECK:STDOUT: {kind: 'CompileTimeBindingPattern', text: ':!', subtree_size: 4},
// CHECK:STDOUT: {kind: 'ImplicitParamList', text: ']', subtree_size: 11},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'U'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Interface'},
// CHECK:STDOUT: {kind: 'CallExprStart', text: '(', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'T'},
@@ -0,0 +1,240 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/generics/interface/require.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/generics/interface/require.carbon
// --- implicit_self_impls.carbon
interface Y {}
interface Z {
require impls Y;
}
// --- explicit_self_impls.carbon
interface Y {}
interface Z {
require Self impls Y;
}
// --- impls_where.carbon
interface Y { let Y1:! type; }
interface Z {
require impls Y where .Y1 = ();
}
// --- other_impls.carbon
interface Y {}
interface Z(T:! type) {
require T impls Y;
}
// --- extend.carbon
interface Y {}
interface Z {
extend require impls Y;
}
// --- fail_missing_impls.carbon
interface Y {}
interface Z {
// CHECK:STDERR: fail_missing_impls.carbon:[[@LINE+4]]:12: error: expected `impls` in `require` declaration [RequireExpectedImpls]
// CHECK:STDERR: require Y;
// CHECK:STDERR: ^
// CHECK:STDERR:
require Y;
}
// --- fail_wrong_keyword.carbon
interface Y {}
interface Z {
// CHECK:STDERR: fail_wrong_keyword.carbon:[[@LINE+4]]:11: error: expected expression [ExpectedExpr]
// CHECK:STDERR: require as Y;
// CHECK:STDERR: ^~
// CHECK:STDERR:
require as Y;
}
// --- fail_as_in_self.carbon
interface Y {}
interface Z {
// CHECK:STDERR: fail_as_in_self.carbon:[[@LINE+4]]:16: error: expected `impls` in `require` declaration [RequireExpectedImpls]
// CHECK:STDERR: require Self as Y impls Y;
// CHECK:STDERR: ^~
// CHECK:STDERR:
require Self as Y impls Y;
}
// CHECK:STDOUT: - filename: implicit_self_impls.carbon
// CHECK:STDOUT: parse_tree: [
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Y'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 4},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Z'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'RequireIntroducer', text: 'require'},
// CHECK:STDOUT: {kind: 'RequireDefaultSelfImpls', text: 'impls'},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Y'},
// CHECK:STDOUT: {kind: 'RequireDecl', text: ';', subtree_size: 4},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 8},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
// CHECK:STDOUT: - filename: explicit_self_impls.carbon
// CHECK:STDOUT: parse_tree: [
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Y'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 4},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Z'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'RequireIntroducer', text: 'require'},
// CHECK:STDOUT: {kind: 'SelfTypeNameExpr', text: 'Self'},
// CHECK:STDOUT: {kind: 'RequireTypeImpls', text: 'impls', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Y'},
// CHECK:STDOUT: {kind: 'RequireDecl', text: ';', subtree_size: 5},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 9},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
// CHECK:STDOUT: - filename: impls_where.carbon
// CHECK:STDOUT: parse_tree: [
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Y'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'AssociatedConstantIntroducer', text: 'let'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Y1'},
// CHECK:STDOUT: {kind: 'TypeTypeLiteral', text: 'type'},
// CHECK:STDOUT: {kind: 'AssociatedConstantNameAndType', text: ':!', subtree_size: 3},
// CHECK:STDOUT: {kind: 'AssociatedConstantDecl', text: ';', subtree_size: 5},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 9},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Z'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'RequireIntroducer', text: 'require'},
// CHECK:STDOUT: {kind: 'RequireDefaultSelfImpls', text: 'impls'},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Y'},
// CHECK:STDOUT: {kind: 'WhereOperand', text: 'where', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Y1'},
// CHECK:STDOUT: {kind: 'DesignatorExpr', text: '.', subtree_size: 2},
// CHECK:STDOUT: {kind: 'TupleLiteralStart', text: '('},
// CHECK:STDOUT: {kind: 'TupleLiteral', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'RequirementEqual', text: '=', subtree_size: 5},
// CHECK:STDOUT: {kind: 'WhereExpr', text: 'where', subtree_size: 8},
// CHECK:STDOUT: {kind: 'RequireDecl', text: ';', subtree_size: 11},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 15},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
// CHECK:STDOUT: - filename: other_impls.carbon
// CHECK:STDOUT: parse_tree: [
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Y'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 4},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'Z'},
// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'T'},
// CHECK:STDOUT: {kind: 'CompileTimeBindingPatternStart', text: ':!', subtree_size: 2},
// CHECK:STDOUT: {kind: 'TypeTypeLiteral', text: 'type'},
// CHECK:STDOUT: {kind: 'CompileTimeBindingPattern', text: ':!', subtree_size: 4},
// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 6},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 9},
// CHECK:STDOUT: {kind: 'RequireIntroducer', text: 'require'},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'T'},
// CHECK:STDOUT: {kind: 'RequireTypeImpls', text: 'impls', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Y'},
// CHECK:STDOUT: {kind: 'RequireDecl', text: ';', subtree_size: 5},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 15},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
// CHECK:STDOUT: - filename: extend.carbon
// CHECK:STDOUT: parse_tree: [
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Y'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 4},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Z'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'RequireIntroducer', text: 'require'},
// CHECK:STDOUT: {kind: 'ExtendModifier', text: 'extend'},
// CHECK:STDOUT: {kind: 'RequireDefaultSelfImpls', text: 'impls'},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Y'},
// CHECK:STDOUT: {kind: 'RequireDecl', text: ';', subtree_size: 5},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 9},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
// CHECK:STDOUT: - filename: fail_missing_impls.carbon
// CHECK:STDOUT: parse_tree: [
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Y'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 4},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Z'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'RequireIntroducer', text: 'require'},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Y'},
// CHECK:STDOUT: {kind: 'RequireDecl', text: ';', has_error: yes, subtree_size: 3},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 7},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
// CHECK:STDOUT: - filename: fail_wrong_keyword.carbon
// CHECK:STDOUT: parse_tree: [
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Y'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 4},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Z'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'RequireIntroducer', text: 'require'},
// CHECK:STDOUT: {kind: 'InvalidParse', text: 'as', has_error: yes},
// CHECK:STDOUT: {kind: 'RequireDecl', text: ';', has_error: yes, subtree_size: 3},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 7},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
// CHECK:STDOUT: - filename: fail_as_in_self.carbon
// CHECK:STDOUT: parse_tree: [
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Y'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 4},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Z'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'RequireIntroducer', text: 'require'},
// CHECK:STDOUT: {kind: 'SelfTypeNameExpr', text: 'Self'},
// CHECK:STDOUT: {kind: 'RequireDecl', text: ';', has_error: yes, subtree_size: 3},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 7},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
+2 -2
View File
@@ -42,7 +42,7 @@ impl package.Name as package.Interface {}
// CHECK:STDOUT: {kind: 'PackageDecl', text: ';', subtree_size: 4},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Interface'},
// CHECK:STDOUT: {kind: 'ImplDefinitionStart', text: '{', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ImplDefinition', text: '}', subtree_size: 6},
@@ -59,7 +59,7 @@ impl package.Name as package.Interface {}
// CHECK:STDOUT: {kind: 'PackageExpr', text: 'package'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Name'},
// CHECK:STDOUT: {kind: 'MemberAccessExpr', text: '.', subtree_size: 3},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 4},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 4},
// CHECK:STDOUT: {kind: 'PackageExpr', text: 'package'},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Interface'},
// CHECK:STDOUT: {kind: 'MemberAccessExpr', text: '.', subtree_size: 3},
+5 -5
View File
@@ -38,7 +38,7 @@ impl f64 as Interface where .T = (type where .Self impls type) {
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 9},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Interface'},
// CHECK:STDOUT: {kind: 'WhereOperand', text: 'where', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'T'},
@@ -51,7 +51,7 @@ impl f64 as Interface where .T = (type where .Self impls type) {
// CHECK:STDOUT: {kind: 'ImplDefinition', text: '}', subtree_size: 13},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'BoolTypeLiteral', text: 'bool'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Interface'},
// CHECK:STDOUT: {kind: 'WhereOperand', text: 'where', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'T'},
@@ -63,7 +63,7 @@ impl f64 as Interface where .T = (type where .Self impls type) {
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'TupleLiteralStart', text: '('},
// CHECK:STDOUT: {kind: 'TupleLiteral', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParenExprStart', text: '('},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Interface'},
// CHECK:STDOUT: {kind: 'WhereOperand', text: 'where', subtree_size: 2},
@@ -79,7 +79,7 @@ impl f64 as Interface where .T = (type where .Self impls type) {
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'StructLiteralStart', text: '{'},
// CHECK:STDOUT: {kind: 'StructLiteral', text: '}', subtree_size: 2},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParenExprStart', text: '('},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Interface'},
// CHECK:STDOUT: {kind: 'WhereOperand', text: 'where', subtree_size: 2},
@@ -100,7 +100,7 @@ impl f64 as Interface where .T = (type where .Self impls type) {
// CHECK:STDOUT: {kind: 'ImplDecl', text: ';', subtree_size: 22},
// CHECK:STDOUT: {kind: 'ImplIntroducer', text: 'impl'},
// CHECK:STDOUT: {kind: 'FloatTypeLiteral', text: 'f64'},
// CHECK:STDOUT: {kind: 'TypeImplAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ImplTypeAs', text: 'as', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Interface'},
// CHECK:STDOUT: {kind: 'WhereOperand', text: 'where', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'T'},
+37 -3
View File
@@ -1446,6 +1446,40 @@ struct InterfaceDefinition {
Lex::CloseCurlyBraceTokenIndex token;
};
// `require`...`impls` statements
// ------------------------------
// `require`
using RequireIntroducer =
LeafNode<NodeKind::RequireIntroducer, Lex::RequireTokenIndex>;
// `impls` with no type before it
using RequireDefaultSelfImpls =
LeafNode<NodeKind::RequireDefaultSelfImpls, Lex::ImplsTokenIndex,
NodeCategory::RequireImpls>;
// `<type> impls`.
struct RequireTypeImpls {
static constexpr auto Kind = NodeKind::RequireTypeImpls.Define(
{.category = NodeCategory::RequireImpls, .child_count = 1});
AnyExprId type_expr;
Lex::ImplsTokenIndex token;
};
// `require T impls I where...`
struct RequireDecl {
static constexpr auto Kind =
NodeKind::RequireDecl.Define({.category = NodeCategory::Decl,
.bracketed_by = RequireIntroducer::Kind});
RequireIntroducerId introducer;
llvm::SmallVector<AnyModifierId> modifiers;
AnyRequireImplsId impls;
AnyExprId facet_type;
Lex::SemiTokenIndex token;
};
// `impl`...`as` declarations and definitions
// ------------------------------------------
@@ -1462,12 +1496,12 @@ struct ImplForall {
};
// `as` with no type before it
using DefaultSelfImplAs = LeafNode<NodeKind::DefaultSelfImplAs,
using ImplDefaultSelfAs = LeafNode<NodeKind::ImplDefaultSelfAs,
Lex::AsTokenIndex, NodeCategory::ImplAs>;
// `<type> as`
struct TypeImplAs {
static constexpr auto Kind = NodeKind::TypeImplAs.Define(
struct ImplTypeAs {
static constexpr auto Kind = NodeKind::ImplTypeAs.Define(
{.category = NodeCategory::ImplAs, .child_count = 1});
AnyExprId type_expr;