diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6529e062f252..8149ca6f8d44 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -135,6 +135,13 @@ repos: hooks: - id: codespell args: ['-I', '.codespell_ignore', '--uri-ignore-words-list', '*'] + # Test data may contain intentional misspellings, as well as short, + # meaningless identifiers that codespell incorrectly identifies as + # typos but that we would want to detect in other contexts. + exclude: | + (?x)^( + .*/testdata/.* + )$ - repo: https://github.com/google/pre-commit-tool-hooks rev: cb78d9293306d9f737c64d9702bbaa88e157caaa # frozen: v1.2.2 hooks: diff --git a/common/fuzzing/carbon.proto b/common/fuzzing/carbon.proto index 123423e27dd2..856c0e30f70b 100644 --- a/common/fuzzing/carbon.proto +++ b/common/fuzzing/carbon.proto @@ -332,6 +332,11 @@ message ImplDeclaration { repeated Declaration members = 4; } +message AliasDeclaration { + optional string name = 1; + optional Expression target = 2; +} + message Declaration { oneof kind { FunctionDeclaration function = 1; @@ -340,6 +345,7 @@ message Declaration { VariableDeclaration variable = 4; InterfaceDeclaration interface = 5; ImplDeclaration impl = 6; + AliasDeclaration alias = 7; } } diff --git a/common/fuzzing/proto_to_carbon.cpp b/common/fuzzing/proto_to_carbon.cpp index f9e0f3db7927..60878aad9633 100644 --- a/common/fuzzing/proto_to_carbon.cpp +++ b/common/fuzzing/proto_to_carbon.cpp @@ -695,6 +695,16 @@ static auto DeclarationToCarbon(const Fuzzing::Declaration& declaration, out << "}"; break; } + + case Fuzzing::Declaration::kAlias: { + const auto& alias = declaration.alias(); + out << "alias "; + IdentifierToCarbon(alias.name(), out); + out << " = "; + ExpressionToCarbon(alias.target(), out); + out << ";"; + break; + } } } diff --git a/explorer/ast/ast_rtti.txt b/explorer/ast/ast_rtti.txt index a56801a550cf..80c5f73e6de3 100644 --- a/explorer/ast/ast_rtti.txt +++ b/explorer/ast/ast_rtti.txt @@ -19,6 +19,7 @@ abstract class Declaration : AstNode; class VariableDeclaration : Declaration; class InterfaceDeclaration : Declaration; class ImplDeclaration : Declaration; + class AliasDeclaration : Declaration; class ImplBinding : AstNode; class AlternativeSignature : AstNode; abstract class Statement : AstNode; diff --git a/explorer/ast/declaration.cpp b/explorer/ast/declaration.cpp index 292c74d48499..d6d3ea59ef48 100644 --- a/explorer/ast/declaration.cpp +++ b/explorer/ast/declaration.cpp @@ -78,6 +78,13 @@ void Declaration::Print(llvm::raw_ostream& out) const { out << "Self"; break; } + + case DeclarationKind::AliasDeclaration: { + const auto& alias = cast(*this); + PrintID(out); + out << " = " << alias.target() << ";\n"; + break; + } } } @@ -127,6 +134,12 @@ void Declaration::PrintID(llvm::raw_ostream& out) const { out << "Self"; break; } + + case DeclarationKind::AliasDeclaration: { + const auto& alias = cast(*this); + out << "alias " << alias.name(); + break; + } } } @@ -146,6 +159,9 @@ auto GetName(const Declaration& declaration) -> std::optional { return std::nullopt; case DeclarationKind::SelfDeclaration: return cast(declaration).name(); + case DeclarationKind::AliasDeclaration: { + return cast(declaration).name(); + } } } diff --git a/explorer/ast/declaration.h b/explorer/ast/declaration.h index 0503735fbf84..52338c872bc0 100644 --- a/explorer/ast/declaration.h +++ b/explorer/ast/declaration.h @@ -417,6 +417,30 @@ class ImplDeclaration : public Declaration { std::vector> impl_bindings_; }; +class AliasDeclaration : public Declaration { + public: + using ImplementsCarbonValueNode = void; + + explicit AliasDeclaration(SourceLocation source_loc, const std::string& name, + Nonnull target) + : Declaration(AstNodeKind::AliasDeclaration, source_loc), + name_(name), + target_(target) {} + + static auto classof(const AstNode* node) -> bool { + return InheritsFromAliasDeclaration(node->kind()); + } + + auto name() const -> const std::string { return name_; } + auto target() const -> const Expression& { return *target_; } + auto target() -> Expression& { return *target_; } + auto value_category() const -> ValueCategory { return ValueCategory::Let; } + + private: + std::string name_; + Nonnull target_; +}; + // Return the name of a declaration, if it has one. auto GetName(const Declaration&) -> std::optional; diff --git a/explorer/fuzzing/ast_to_proto.cpp b/explorer/fuzzing/ast_to_proto.cpp index bea126644786..9953b0c1dc63 100644 --- a/explorer/fuzzing/ast_to_proto.cpp +++ b/explorer/fuzzing/ast_to_proto.cpp @@ -563,6 +563,14 @@ static auto DeclarationToProto(const Declaration& declaration) case DeclarationKind::SelfDeclaration: { CARBON_FATAL() << "Unreachable SelfDeclaration in DeclarationToProto()."; } + + case DeclarationKind::AliasDeclaration: { + const auto& alias = cast(declaration); + auto* alias_proto = declaration_proto.mutable_alias(); + alias_proto->set_name(alias.name()); + *alias_proto->mutable_target() = ExpressionToProto(alias.target()); + break; + } } return declaration_proto; } diff --git a/explorer/interpreter/interpreter.cpp b/explorer/interpreter/interpreter.cpp index 313cd72c83cb..e8102be80bf1 100644 --- a/explorer/interpreter/interpreter.cpp +++ b/explorer/interpreter/interpreter.cpp @@ -1400,6 +1400,7 @@ auto Interpreter::StepDeclaration() -> ErrorOr { case DeclarationKind::InterfaceDeclaration: case DeclarationKind::ImplDeclaration: case DeclarationKind::SelfDeclaration: + case DeclarationKind::AliasDeclaration: // These declarations have no run-time effects. return todo_.FinishAction(); } diff --git a/explorer/interpreter/resolve_control_flow.cpp b/explorer/interpreter/resolve_control_flow.cpp index 235ad58a32eb..43486bb20f76 100644 --- a/explorer/interpreter/resolve_control_flow.cpp +++ b/explorer/interpreter/resolve_control_flow.cpp @@ -154,6 +154,7 @@ auto ResolveControlFlow(Nonnull declaration) -> ErrorOr { case DeclarationKind::ChoiceDeclaration: case DeclarationKind::VariableDeclaration: case DeclarationKind::SelfDeclaration: + case DeclarationKind::AliasDeclaration: // do nothing break; } diff --git a/explorer/interpreter/resolve_names.cpp b/explorer/interpreter/resolve_names.cpp index 02753ba08d37..d80ab54a8687 100644 --- a/explorer/interpreter/resolve_names.cpp +++ b/explorer/interpreter/resolve_names.cpp @@ -64,6 +64,11 @@ static auto AddExposedNames(const Declaration& declaration, CARBON_RETURN_IF_ERROR(enclosing_scope.Add("Self", &self)); break; } + case DeclarationKind::AliasDeclaration: { + auto& alias = cast(declaration); + CARBON_RETURN_IF_ERROR(enclosing_scope.Add(alias.name(), &alias)); + break; + } } return Success(); } @@ -446,6 +451,12 @@ static auto ResolveNames(Declaration& declaration, StaticScope& enclosing_scope) case DeclarationKind::SelfDeclaration: { CARBON_FATAL() << "Unreachable: resolving names for `Self` declaration"; } + + case DeclarationKind::AliasDeclaration: { + CARBON_RETURN_IF_ERROR(ResolveNames( + cast(declaration).target(), enclosing_scope)); + break; + } } return Success(); } diff --git a/explorer/interpreter/type_checker.cpp b/explorer/interpreter/type_checker.cpp index 8523f3c5a72a..b52ba8c5232f 100644 --- a/explorer/interpreter/type_checker.cpp +++ b/explorer/interpreter/type_checker.cpp @@ -2409,6 +2409,72 @@ auto TypeChecker::TypeCheckChoiceDeclaration( return Success(); } +static bool IsValidTypeForAliasTarget(Nonnull type) { + switch (type->kind()) { + case Value::Kind::IntValue: + case Value::Kind::FunctionValue: + case Value::Kind::BoundMethodValue: + case Value::Kind::PointerValue: + case Value::Kind::LValue: + case Value::Kind::BoolValue: + case Value::Kind::StructValue: + case Value::Kind::NominalClassValue: + case Value::Kind::AlternativeValue: + case Value::Kind::TupleValue: + case Value::Kind::Witness: + case Value::Kind::ParameterizedEntityName: + case Value::Kind::MemberName: + case Value::Kind::BindingPlaceholderValue: + case Value::Kind::AlternativeConstructorValue: + case Value::Kind::ContinuationValue: + case Value::Kind::StringValue: + CARBON_FATAL() << "type of alias target is not a type"; + + case Value::Kind::AutoType: + case Value::Kind::VariableType: + CARBON_FATAL() << "pattern type in alias target"; + + case Value::Kind::IntType: + case Value::Kind::BoolType: + case Value::Kind::PointerType: + case Value::Kind::StaticArrayType: + case Value::Kind::StructType: + case Value::Kind::NominalClassType: + case Value::Kind::ChoiceType: + case Value::Kind::ContinuationType: + case Value::Kind::StringType: + return false; + + case Value::Kind::FunctionType: + case Value::Kind::InterfaceType: + case Value::Kind::TypeType: + case Value::Kind::TypeOfClassType: + case Value::Kind::TypeOfInterfaceType: + case Value::Kind::TypeOfChoiceType: + case Value::Kind::TypeOfParameterizedEntityName: + case Value::Kind::TypeOfMemberName: + return true; + } +} + +auto TypeChecker::DeclareAliasDeclaration(Nonnull alias, + const ImplScope& enclosing_scope) + -> ErrorOr { + CARBON_RETURN_IF_ERROR(TypeCheckExp(&alias->target(), enclosing_scope)); + + if (!IsValidTypeForAliasTarget(&alias->target().static_type())) { + return CompilationError(alias->source_loc()) + << "invalid target for alias declaration"; + } + + CARBON_ASSIGN_OR_RETURN(Nonnull target, + InterpExp(&alias->target(), arena_, trace_stream_)); + + SetConstantValue(alias, target); + alias->set_static_type(&alias->target().static_type()); + return Success(); +} + auto TypeChecker::TypeCheck(AST& ast) -> ErrorOr { ImplScope impl_scope; for (Nonnull declaration : ast.declarations) { @@ -2472,6 +2538,9 @@ auto TypeChecker::TypeCheckDeclaration(Nonnull d, case DeclarationKind::SelfDeclaration: { CARBON_FATAL() << "Unreachable TypeChecker `Self` declaration"; } + case DeclarationKind::AliasDeclaration: { + return Success(); + } } return Success(); } @@ -2534,6 +2603,12 @@ auto TypeChecker::DeclareDeclaration(Nonnull d, case DeclarationKind::SelfDeclaration: { CARBON_FATAL() << "Unreachable TypeChecker declare `Self` declaration"; } + + case DeclarationKind::AliasDeclaration: { + auto& alias = cast(*d); + CARBON_RETURN_IF_ERROR(DeclareAliasDeclaration(&alias, enclosing_scope)); + break; + } } return Success(); } diff --git a/explorer/interpreter/type_checker.h b/explorer/interpreter/type_checker.h index 9c959bd956bf..92b4d258adf0 100644 --- a/explorer/interpreter/type_checker.h +++ b/explorer/interpreter/type_checker.h @@ -106,6 +106,9 @@ class TypeChecker { auto DeclareChoiceDeclaration(Nonnull choice, const ImplScope& enclosing_scope) -> ErrorOr; + auto DeclareAliasDeclaration(Nonnull alias, + const ImplScope& enclosing_scope) + -> ErrorOr; // Find all of the GenericBindings in the given pattern. void CollectGenericBindingsInPattern( diff --git a/explorer/syntax/lexer.lpp b/explorer/syntax/lexer.lpp index 12db8d242804..a699273fd3e6 100644 --- a/explorer/syntax/lexer.lpp +++ b/explorer/syntax/lexer.lpp @@ -33,6 +33,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception %s AFTER_OPERAND /* table-begin */ +ALIAS "alias" AMPERSAND "&" AND "and" API "api" @@ -137,6 +138,7 @@ string_literal \"([^\\\"\n\v\f\r]|\\.)*\" %} /* table-begin */ +{ALIAS} { return SIMPLE_TOKEN(ALIAS); } {AMPERSAND} { return SIMPLE_TOKEN(AMPERSAND); } {AND} { return SIMPLE_TOKEN(AND); } {API} { return SIMPLE_TOKEN(API); } diff --git a/explorer/syntax/parser.ypp b/explorer/syntax/parser.ypp index 84ab2685670b..2dbf6a9ed693 100644 --- a/explorer/syntax/parser.ypp +++ b/explorer/syntax/parser.ypp @@ -106,6 +106,7 @@ %type api_or_impl %type > declaration %type > function_declaration +%type > alias_declaration %type >> declaration_list %type > statement %type > if_statement @@ -173,6 +174,7 @@ %token // Most tokens have their spelling defined in lexer.lpp. // table-begin + ALIAS AMPERSAND AND API @@ -864,6 +866,9 @@ variable_declaration: identifier COLON pattern std::nullopt); } ; +alias_declaration: ALIAS identifier EQUAL expression SEMICOLON + { $$ = arena->New(context.source_loc(), $2, $4); } +; alternative: identifier tuple { $$ = arena->New(context.source_loc(), $1, $2); } @@ -945,6 +950,8 @@ declaration: YYERROR; } } +| alias_declaration + { $$ = $1; } ; impl_kind: // Internal diff --git a/explorer/testdata/alias/class_alias.carbon b/explorer/testdata/alias/class_alias.carbon new file mode 100644 index 000000000000..624b6921767a --- /dev/null +++ b/explorer/testdata/alias/class_alias.carbon @@ -0,0 +1,40 @@ +// 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 +// +// RUN: %{explorer} %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s +// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s +// AUTOUPDATE: %{explorer} %s +// CHECK: result: 123 + +package ExplorerTest api; + +interface Addable { + fn Add[me: Self](k: i32) -> Self; +} +impl i32 as Addable { + fn Add[me: Self](k: i32) -> Self { return me + k; } +} + +class Class { var n: i32; } +class GenericClass(T:! Addable) { + var m: T; + fn Get[me: Self](n: i32) -> T { return me.m.Add(n); } +} + +alias ClassAlias = Class; +alias GenericClassAlias = GenericClass; +alias ClassSpecializationAlias = GenericClassAlias(i32); + +fn Main() -> i32 { + var a: Class = {.n = 1}; + var b: ClassAlias = a; + + var c: GenericClass(i32) = {.m = 2}; + var d: GenericClassAlias(i32) = c; + var e: ClassSpecializationAlias = c; + // TODO: Switch to using Print here once it supports printing integers. + return 100 * b.n + 10 * d.Get(0) + e.Get(1); +} diff --git a/explorer/testdata/alias/fail_alias_expression.carbon b/explorer/testdata/alias/fail_alias_expression.carbon new file mode 100644 index 000000000000..b37a1e0aa9fd --- /dev/null +++ b/explorer/testdata/alias/fail_alias_expression.carbon @@ -0,0 +1,16 @@ +// 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 +// +// RUN: %{not} %{explorer} %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s +// RUN: %{not} %{explorer} --parser_debug --trace_file=- %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s +// AUTOUPDATE: %{explorer} %s + +package ExplorerTest api; + +// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/alias/fail_alias_expression.carbon:[[@LINE+1]]: invalid target for alias declaration +alias A = 5; + +fn Main() -> i32 { return 0; } diff --git a/explorer/testdata/alias/fail_alias_var.carbon b/explorer/testdata/alias/fail_alias_var.carbon new file mode 100644 index 000000000000..8eb64544c6f5 --- /dev/null +++ b/explorer/testdata/alias/fail_alias_var.carbon @@ -0,0 +1,18 @@ +// 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 +// +// RUN: %{not} %{explorer} %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s +// RUN: %{not} %{explorer} --parser_debug --trace_file=- %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s +// AUTOUPDATE: %{explorer} %s + +package ExplorerTest api; + +var v: i32; +// FIXME: This should probably be valid if we allow global variables at all. +// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/alias/fail_alias_var.carbon:[[@LINE+1]]: invalid target for alias declaration +alias A = v; + +fn Main() -> i32 { return 0; } diff --git a/explorer/testdata/alias/function_alias.carbon b/explorer/testdata/alias/function_alias.carbon new file mode 100644 index 000000000000..b05b478eea39 --- /dev/null +++ b/explorer/testdata/alias/function_alias.carbon @@ -0,0 +1,24 @@ +// 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 +// +// RUN: %{explorer} %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s +// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s +// AUTOUPDATE: %{explorer} %s +// CHECK: result: 7 + +package ExplorerTest api; + +alias TypeAlias = i32; + +fn Function(a: i32, b: TypeAlias) -> i32 { return a + b; } +fn GenericFunction[T:! Type](x: T) -> T { return x; } + +alias FunctionAlias = Function; +alias GenericFunctionAlias = GenericFunction; + +fn Main() -> i32 { + return FunctionAlias(1, 2) + GenericFunctionAlias(4); +} diff --git a/explorer/testdata/alias/interface_alias.carbon b/explorer/testdata/alias/interface_alias.carbon new file mode 100644 index 000000000000..8cb3708bffa8 --- /dev/null +++ b/explorer/testdata/alias/interface_alias.carbon @@ -0,0 +1,62 @@ +// 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 +// +// RUN: %{explorer} %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s +// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s +// AUTOUPDATE: %{explorer} %s +// CHECK: result: 12345 + +package ExplorerTest api; + +class Class { var a: i32; } +class GenericClass(T:! Type) { var a: T; } +interface Interface { fn Make() -> Self; } +interface GenericInterface(T:! Type) { fn Make() -> (Self, T); } + +alias ClassAlias = Class; +alias GenericClassAlias = GenericClass; +alias ClassSpecializationAlias = GenericClassAlias(i32); +alias InterfaceAlias = Interface; +alias GenericInterfaceAlias = GenericInterface; +alias InterfaceSpecializationAlias = GenericInterfaceAlias(i32); + +impl ClassAlias as InterfaceAlias { + fn Make() -> Self { return {.a = 1}; } +} +impl ClassSpecializationAlias as InterfaceSpecializationAlias { + fn Make() -> (Self, i32) { return ({.a = 2}, 3); } +} +alias S = {.a: i32}; +impl GenericClassAlias(S) as GenericInterfaceAlias(S) { + fn Make() -> (Self, {.a: i32}) { return ({.a = {.a = 4}}, {.a = 5}); } +} + +fn CheckImplementsInterface[T:! Interface](x: T) -> T { + return T.Make(); +} +fn CheckImplementsGenericInterface_i32 + [T:! GenericInterface(i32)](x: T) -> (T, i32) { + return T.Make(); +} +fn CheckImplementsGenericInterface_struct + [T:! GenericInterface(S)](x: T) -> (T, S) { + return T.Make(); +} + +fn Main() -> i32 { + var a: Class = {.a = 0}; + a = CheckImplementsInterface(a); + + var b: GenericClass(i32) = {.a = 0}; + var (b2: GenericClass(i32), n: i32) = + CheckImplementsGenericInterface_i32(b); + + var c: GenericClass({.a: i32}) = {.a = {.a = 0}}; + var (c2: GenericClass({.a: i32}), s: S) = + CheckImplementsGenericInterface_struct(c); + + return 10000 * a.a + 1000 * b2.a + 100 * n + 10 * c2.a.a + s.a; +} diff --git a/explorer/testdata/alias/member_name_alias.carbon b/explorer/testdata/alias/member_name_alias.carbon new file mode 100644 index 000000000000..2dce696eeb9f --- /dev/null +++ b/explorer/testdata/alias/member_name_alias.carbon @@ -0,0 +1,82 @@ +// 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 +// +// RUN: %{explorer} %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s +// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s +// AUTOUPDATE: %{explorer} %s +// CHECK: result: 0 + +package ExplorerTest api; + +interface I { + fn F() -> i32; + fn M[me: Self]() -> i32; +} +class A { + var n: i32; + impl as I { + fn F() -> i32 { return 1; } + fn M[me: Self]() -> i32 { return 2; } + } + fn G[me: Self]() -> i32 { return 3; } +} +impl i32 as I { + fn F() -> i32 { return 4; } + fn M[me: Self]() -> i32 { return 5; } +} + +alias IF = I.F; +alias IM = I.M; +alias AIF = A.(IF); +alias AIM = A.(IM); +alias AG = A.G; +alias i32IF = i32.(IF); +alias i32IM = i32.(IM); + +fn Main() -> i32 { + var a: A = {.n = 0}; + // FIXME: Use != once we support it. + if (not (A.(IF)() == 1)) { + return 1; + } + if (not (a.(IF)() == 1)) { + return 2; + } + if (not (a.(IM)() == 2)) { + return 3; + } + if (not (a.(A.(IM))() == 2)) { + return 4; + } + if (not (AIF() == 1)) { + return 5; + } + if (not (a.(AIM)() == 2)) { + return 6; + } + if (not (a.(AG)() == 3)) { + return 7; + } + if (not (i32.(IF)() == 4)) { + return 8; + } + if (not (0.(IF)() == 4)) { + return 9; + } + if (not (0.(IM)() == 5)) { + return 10; + } + if (not (0.(i32.(IM))() == 5)) { + return 11; + } + if (not (i32IF() == 4)) { + return 12; + } + if (not (0.(i32IM)() == 5)) { + return 13; + } + return 0; +} diff --git a/explorer/testdata/alias/struct_alias.carbon b/explorer/testdata/alias/struct_alias.carbon new file mode 100644 index 000000000000..b36060a80334 --- /dev/null +++ b/explorer/testdata/alias/struct_alias.carbon @@ -0,0 +1,22 @@ +// 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 +// +// RUN: %{explorer} %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s +// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s +// AUTOUPDATE: %{explorer} %s +// CHECK: result: 2121 + +package ExplorerTest api; + +alias AB = {.a: i32, .b: i32}; +alias BA = {.b: i32, .a: i32}; + +fn Main() -> i32 { + var ab: AB = {.b = 1, .a = 2}; + var ba: BA = ab; + // TODO: Switch to using Print here once it supports printing integers. + return 1000 * ab.a + 100 * ab.b + 10 * ba.a + ba.b; +} diff --git a/explorer/testdata/alias/type_alias.carbon b/explorer/testdata/alias/type_alias.carbon new file mode 100644 index 000000000000..712e2606fb10 --- /dev/null +++ b/explorer/testdata/alias/type_alias.carbon @@ -0,0 +1,22 @@ +// 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 +// +// RUN: %{explorer} %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s +// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s +// AUTOUPDATE: %{explorer} %s +// CHECK: result: 4 + +package ExplorerTest api; + +alias TypeAlias = i32; + +fn Main() -> TypeAlias { + var n: TypeAlias = 1; + var m: i32 = n; + var p: i32* = &n; + var q: TypeAlias* = &m; + return *p + *q + m + n; +}