diff --git a/explorer/ast/expression.h b/explorer/ast/expression.h index 3355a0d65528..58706481bb4a 100644 --- a/explorer/ast/expression.h +++ b/explorer/ast/expression.h @@ -897,12 +897,12 @@ class RewriteWhereClause : public WhereClause { // // The first operand is rewritten to a generic binding, for example // `.Self:! AddableWith(i32)`, which may be used in the clauses. -class WhereExpression : public Expression { +class WhereExpression : public RewritableMixin { public: explicit WhereExpression(SourceLocation source_loc, Nonnull self_binding, std::vector> clauses) - : Expression(AstNodeKind::WhereExpression, source_loc), + : RewritableMixin(AstNodeKind::WhereExpression, source_loc), self_binding_(self_binding), clauses_(std::move(clauses)) {} diff --git a/explorer/interpreter/interpreter.cpp b/explorer/interpreter/interpreter.cpp index 8840f308c976..721869535eef 100644 --- a/explorer/interpreter/interpreter.cpp +++ b/explorer/interpreter/interpreter.cpp @@ -228,9 +228,6 @@ auto Interpreter::EvalPrim(Operator op, Nonnull static_type, return heap_.Read(cast(*args[0]).address(), source_loc); case Operator::AddressOf: return arena_->New(cast(*args[0]).address()); - case Operator::BitwiseAnd: - // If & wasn't rewritten, it's being used to form a constraint. - return &cast(static_type)->constraint_type(); case Operator::As: case Operator::Eq: case Operator::NotEq: @@ -238,6 +235,7 @@ auto Interpreter::EvalPrim(Operator op, Nonnull static_type, case Operator::LessEq: case Operator::Greater: case Operator::GreaterEq: + case Operator::BitwiseAnd: case Operator::BitwiseOr: case Operator::BitwiseXor: case Operator::BitShiftLeft: @@ -697,11 +695,7 @@ auto Interpreter::Convert(Nonnull value, case Value::Kind::ContinuationValue: case Value::Kind::StringType: case Value::Kind::StringValue: - case Value::Kind::TypeOfClassType: case Value::Kind::TypeOfMixinPseudoType: - case Value::Kind::TypeOfInterfaceType: - case Value::Kind::TypeOfConstraintType: - case Value::Kind::TypeOfChoiceType: case Value::Kind::TypeOfParameterizedEntityName: case Value::Kind::TypeOfMemberName: case Value::Kind::StaticArrayType: @@ -1467,8 +1461,9 @@ auto Interpreter::StepExp() -> ErrorOr { break; } case ExpressionKind::WhereExpression: { - return todo_.FinishAction( - &cast(exp.static_type()).constraint_type()); + auto rewrite = cast(exp).rewritten_form(); + CARBON_CHECK(rewrite) << "where expression should be rewritten"; + return todo_.ReplaceWith(std::make_unique(*rewrite)); } case ExpressionKind::UnimplementedExpression: CARBON_FATAL() << "Unimplemented: " << exp; diff --git a/explorer/interpreter/type_checker.cpp b/explorer/interpreter/type_checker.cpp index 447fb77f85fb..f738f6c00cb3 100644 --- a/explorer/interpreter/type_checker.cpp +++ b/explorer/interpreter/type_checker.cpp @@ -127,11 +127,7 @@ static auto IsTypeOfType(Nonnull value) -> bool { case Value::Kind::TypeType: case Value::Kind::InterfaceType: case Value::Kind::ConstraintType: - case Value::Kind::TypeOfClassType: case Value::Kind::TypeOfMixinPseudoType: - case Value::Kind::TypeOfInterfaceType: - case Value::Kind::TypeOfConstraintType: - case Value::Kind::TypeOfChoiceType: // A value of one of these types is itself always a type. return true; } @@ -182,10 +178,6 @@ static auto IsType(Nonnull value, bool concrete = false) -> bool { case Value::Kind::ContinuationType: case Value::Kind::VariableType: case Value::Kind::StringType: - case Value::Kind::TypeOfClassType: - case Value::Kind::TypeOfInterfaceType: - case Value::Kind::TypeOfConstraintType: - case Value::Kind::TypeOfChoiceType: case Value::Kind::StaticArrayType: return true; case Value::Kind::AutoType: @@ -267,10 +259,6 @@ static auto ExpectCompleteType(SourceLocation source_loc, case Value::Kind::BoolType: case Value::Kind::StringType: case Value::Kind::PointerType: - case Value::Kind::TypeOfClassType: - case Value::Kind::TypeOfInterfaceType: - case Value::Kind::TypeOfConstraintType: - case Value::Kind::TypeOfChoiceType: case Value::Kind::TypeType: case Value::Kind::FunctionType: case Value::Kind::StructType: @@ -503,10 +491,6 @@ auto TypeChecker::IsImplicitlyConvertible( break; case Value::Kind::InterfaceType: case Value::Kind::ConstraintType: - case Value::Kind::TypeOfClassType: - case Value::Kind::TypeOfChoiceType: - case Value::Kind::TypeOfInterfaceType: - case Value::Kind::TypeOfConstraintType: // TODO: These types should presumably also convert to constraint types. if (isa(destination)) { return true; @@ -609,8 +593,7 @@ auto TypeChecker::BuildBuiltinMethodCall(const ImplScope& impl_scope, // Build an expression to perform the call `source.(interface.method)(args)`. Nonnull iface_expr = arena_->New( - source_loc, iface_type, arena_->New(iface_type), - ValueCategory::Let); + source_loc, iface_type, arena_->New(), ValueCategory::Let); Nonnull iface_member = arena_->New( source_loc, iface_expr, method.name); Nonnull method_access = @@ -916,10 +899,6 @@ auto TypeChecker::ArgumentDeduction::Deduce(Nonnull param, case Value::Kind::BoolType: case Value::Kind::TypeType: case Value::Kind::StringType: - case Value::Kind::TypeOfClassType: - case Value::Kind::TypeOfInterfaceType: - case Value::Kind::TypeOfConstraintType: - case Value::Kind::TypeOfChoiceType: case Value::Kind::TypeOfParameterizedEntityName: case Value::Kind::TypeOfMemberName: { return handle_non_deduced_type(); @@ -1626,11 +1605,7 @@ auto TypeChecker::Substitute(const Bindings& bindings, case Value::Kind::StringType: case Value::Kind::MixinPseudoType: return type; - case Value::Kind::TypeOfClassType: case Value::Kind::TypeOfMixinPseudoType: - case Value::Kind::TypeOfInterfaceType: - case Value::Kind::TypeOfConstraintType: - case Value::Kind::TypeOfChoiceType: case Value::Kind::TypeOfParameterizedEntityName: case Value::Kind::TypeOfMemberName: // TODO: We should substitute into the value and produce a new type of @@ -2285,11 +2260,7 @@ auto TypeChecker::TypeCheckExp(Nonnull e, } return Success(); } - case Value::Kind::TypeType: - case Value::Kind::TypeOfChoiceType: - case Value::Kind::TypeOfClassType: - case Value::Kind::TypeOfConstraintType: - case Value::Kind::TypeOfInterfaceType: { + case Value::Kind::TypeType: { // This is member access into an unconstrained type. Evaluate it and // perform lookup in the result. CARBON_ASSIGN_OR_RETURN( @@ -2657,31 +2628,27 @@ auto TypeChecker::TypeCheckExp(Nonnull e, // `&` between type-of-types performs constraint combination. // TODO: Should this be done via an intrinsic? if (IsTypeOfType(ts[0]) && IsTypeOfType(ts[1])) { - std::optional> constraints[2]; - for (int i : {0, 1}) { - // TODO: This should be done based on the values, not their - // types. - if (auto* iface_type_type = - dyn_cast(ts[i])) { - CARBON_ASSIGN_OR_RETURN( - constraints[i], - MakeConstraintForInterface( - e->source_loc(), &iface_type_type->interface_type())); - } else if (auto* constraint_type_type = - dyn_cast(ts[i])) { - constraints[i] = &constraint_type_type->constraint_type(); - } else { - return ProgramError(op.arguments()[i]->source_loc()) - << "argument to " << ToString(op.op()) - << " should be a constraint, found `" << *ts[i] << "`"; - } - } + CARBON_ASSIGN_OR_RETURN( + Nonnull lhs, + InterpExp(op.arguments()[0], arena_, trace_stream_)); + CARBON_ASSIGN_OR_RETURN( + Nonnull rhs, + InterpExp(op.arguments()[1], arena_, trace_stream_)); + CARBON_ASSIGN_OR_RETURN( + Nonnull lhs_constraint, + ConvertToConstraintType(op.arguments()[0]->source_loc(), + "first operand of `&`", lhs)); + CARBON_ASSIGN_OR_RETURN( + Nonnull rhs_constraint, + ConvertToConstraintType(op.arguments()[1]->source_loc(), + "second operand of `&`", rhs)); CARBON_ASSIGN_OR_RETURN( Nonnull result, CombineConstraints(e->source_loc(), - {*constraints[0], *constraints[1]})); - op.set_static_type(arena_->New(result)); - op.set_value_category(ValueCategory::Let); + {lhs_constraint, rhs_constraint})); + op.set_rewritten_form(arena_->New( + op.source_loc(), result, arena_->New(), + ValueCategory::Let)); return Success(); } return handle_binary_operator(Builtins::BitAndWith); @@ -2831,44 +2798,17 @@ auto TypeChecker::TypeCheckExp(Nonnull e, CARBON_RETURN_IF_ERROR(DeduceCallBindings( call, ¶m_name.params().static_type(), generic_parameters, /*deduced_bindings=*/llvm::None, impl_bindings, impl_scope)); - Nonnull bindings = &call.bindings(); - const Declaration& decl = param_name.declaration(); - switch (decl.kind()) { - case DeclarationKind::ClassDeclaration: { - Nonnull inst_class_type = - arena_->New(&cast(decl), - bindings); - call.set_static_type( - arena_->New(inst_class_type)); - call.set_value_category(ValueCategory::Let); - break; - } - case DeclarationKind::InterfaceDeclaration: { - Nonnull inst_iface_type = - arena_->New(&cast(decl), - bindings); - call.set_static_type( - arena_->New(inst_iface_type)); - call.set_value_category(ValueCategory::Let); - break; - } - case DeclarationKind::ChoiceDeclaration: { - Nonnull ct = arena_->New( - cast(&decl), bindings); - Nonnull inst_choice_type = - arena_->New(ct); - call.set_static_type(inst_choice_type); - call.set_value_category(ValueCategory::Let); - break; - } - default: - CARBON_FATAL() - << "unknown type of ParameterizedEntityName for " << decl; - } + // Currently the only kinds of parameterized entities we support are + // types. + CARBON_CHECK( + isa( + param_name.declaration())) + << "unknown type of ParameterizedEntityName for " << param_name; + call.set_static_type(arena_->New()); + call.set_value_category(ValueCategory::Let); return Success(); } - case Value::Kind::TypeOfChoiceType: default: { return ProgramError(e->source_loc()) << "in call `" << *e @@ -3209,9 +3149,9 @@ auto TypeChecker::TypeCheckExp(Nonnull e, } } - where.set_static_type( - arena_->New(std::move(builder).Build(arena_))); - where.set_value_category(ValueCategory::Let); + where.set_rewritten_form(arena_->New( + where.source_loc(), std::move(builder).Build(arena_), + arena_->New(), ValueCategory::Let)); return Success(); } case ExpressionKind::UnimplementedExpression: @@ -3309,8 +3249,7 @@ auto TypeChecker::TypeCheckWhereClause(Nonnull clause, auto& is_clause = cast(*clause); CARBON_RETURN_IF_ERROR(TypeCheckTypeExp(&is_clause.type(), impl_scope)); CARBON_RETURN_IF_ERROR(TypeCheckExp(&is_clause.constraint(), impl_scope)); - if (!isa( - is_clause.constraint().static_type())) { + if (!isa(is_clause.constraint().static_type())) { return ProgramError(is_clause.constraint().source_loc()) << "expression after `is` does not resolve to a constraint, " << "found " << is_clause.constraint().static_type(); @@ -4036,7 +3975,7 @@ auto TypeChecker::DeclareClassDeclaration(Nonnull class_decl, // should have the value `MyType(T, U)`. Nonnull self_type = arena_->New( class_decl, Bindings::SymbolicIdentity(arena_, bindings)); - self->set_static_type(arena_->New(self_type)); + self->set_static_type(arena_->New()); self->set_constant_value(self_type); // The declarations of the members may refer to the class, so we must set the @@ -4252,7 +4191,7 @@ auto TypeChecker::DeclareInterfaceDeclaration( iface_decl, Bindings::SymbolicIdentity(arena_, bindings)); } else { iface_type = arena_->New(iface_decl); - iface_decl->set_static_type(arena_->New(iface_type)); + iface_decl->set_static_type(arena_->New()); iface_decl->set_constant_value(iface_type); } @@ -4712,7 +4651,7 @@ auto TypeChecker::DeclareChoiceDeclaration(Nonnull choice, auto ct = arena_->New( choice, Bindings::SymbolicIdentity(arena_, bindings)); - choice->set_static_type(arena_->New(ct)); + choice->set_static_type(arena_->New()); choice->set_constant_value(ct); return Success(); } @@ -4773,10 +4712,6 @@ static bool IsValidTypeForAliasTarget(Nonnull type) { case Value::Kind::InterfaceType: case Value::Kind::ConstraintType: case Value::Kind::TypeType: - case Value::Kind::TypeOfClassType: - case Value::Kind::TypeOfInterfaceType: - case Value::Kind::TypeOfConstraintType: - case Value::Kind::TypeOfChoiceType: case Value::Kind::TypeOfParameterizedEntityName: case Value::Kind::TypeOfMemberName: return true; diff --git a/explorer/interpreter/value.cpp b/explorer/interpreter/value.cpp index 438f98328d87..bc016b0e00ee 100644 --- a/explorer/interpreter/value.cpp +++ b/explorer/interpreter/value.cpp @@ -530,9 +530,6 @@ void Value::Print(llvm::raw_ostream& out) const { out.write_escaped(cast(*this).value()); out << "\""; break; - case Value::Kind::TypeOfClassType: - out << "typeof(" << cast(*this).class_type() << ")"; - break; case Value::Kind::TypeOfMixinPseudoType: out << "typeof(" << cast(*this) @@ -541,22 +538,6 @@ void Value::Print(llvm::raw_ostream& out) const { .name() << ")"; break; - case Value::Kind::TypeOfInterfaceType: - out << "typeof(" - << cast(*this) - .interface_type() - .declaration() - .name() - << ")"; - break; - case Value::Kind::TypeOfConstraintType: - out << "typeof(" << cast(*this).constraint_type() - << ")"; - break; - case Value::Kind::TypeOfChoiceType: - out << "typeof(" << cast(*this).choice_type().name() - << ")"; - break; case Value::Kind::TypeOfParameterizedEntityName: out << "parameterized entity name " << cast(*this).name(); @@ -743,21 +724,6 @@ auto TypeEqual(Nonnull t1, Nonnull t2, case Value::Kind::VariableType: return &cast(*t1).binding() == &cast(*t2).binding(); - case Value::Kind::TypeOfClassType: - return TypeEqual(&cast(*t1).class_type(), - &cast(*t2).class_type(), equality_ctx); - case Value::Kind::TypeOfInterfaceType: - return TypeEqual(&cast(*t1).interface_type(), - &cast(*t2).interface_type(), - equality_ctx); - case Value::Kind::TypeOfConstraintType: - return TypeEqual(&cast(*t1).constraint_type(), - &cast(*t2).constraint_type(), - equality_ctx); - case Value::Kind::TypeOfChoiceType: - return TypeEqual(&cast(*t1).choice_type(), - &cast(*t2).choice_type(), - equality_ctx); case Value::Kind::StaticArrayType: { const auto& array1 = cast(*t1); const auto& array2 = cast(*t2); @@ -904,11 +870,7 @@ auto ValueStructurallyEqual( case Value::Kind::ContinuationType: case Value::Kind::VariableType: case Value::Kind::StringType: - case Value::Kind::TypeOfClassType: case Value::Kind::TypeOfMixinPseudoType: - case Value::Kind::TypeOfInterfaceType: - case Value::Kind::TypeOfConstraintType: - case Value::Kind::TypeOfChoiceType: case Value::Kind::TypeOfParameterizedEntityName: case Value::Kind::TypeOfMemberName: case Value::Kind::StaticArrayType: diff --git a/explorer/interpreter/value.h b/explorer/interpreter/value.h index 5df5e3e29e06..69c5e4d1d935 100644 --- a/explorer/interpreter/value.h +++ b/explorer/interpreter/value.h @@ -76,11 +76,7 @@ class Value { ContinuationValue, // A first-class continuation value. StringType, StringValue, - TypeOfClassType, TypeOfMixinPseudoType, - TypeOfInterfaceType, - TypeOfConstraintType, - TypeOfChoiceType, TypeOfParameterizedEntityName, TypeOfMemberName, StaticArrayType, @@ -640,10 +636,7 @@ class NominalClassType : public Value { auto type_args() const -> const BindingMap& { return bindings_->args(); } - // Witnesses for each of the class's impl bindings. These will not in general - // be set for class types that are only intended to be used within - // type-checking and not at runtime, such as in the static_type() of an - // expression or the type in a TypeOfClassType. + // Witnesses for each of the class's impl bindings. auto witnesses() const -> const ImplWitnessMap& { return bindings_->witnesses(); } @@ -1218,25 +1211,6 @@ class StringValue : public Value { std::string value_; }; -// The type of an expression whose value is a class type. Currently there is no -// way to explicitly name such a type in Carbon code, but we are tentatively -// using `typeof(ClassName)` as the debug-printing format, in anticipation of -// something like that becoming valid Carbon syntax. -class TypeOfClassType : public Value { - public: - explicit TypeOfClassType(Nonnull class_type) - : Value(Kind::TypeOfClassType), class_type_(class_type) {} - - static auto classof(const Value* value) -> bool { - return value->kind() == Kind::TypeOfClassType; - } - - auto class_type() const -> const NominalClassType& { return *class_type_; } - - private: - Nonnull class_type_; -}; - class TypeOfMixinPseudoType : public Value { public: explicit TypeOfMixinPseudoType(Nonnull class_type) @@ -1252,57 +1226,6 @@ class TypeOfMixinPseudoType : public Value { Nonnull mixin_type_; }; -class TypeOfInterfaceType : public Value { - public: - explicit TypeOfInterfaceType(Nonnull iface_type) - : Value(Kind::TypeOfInterfaceType), iface_type_(iface_type) {} - - static auto classof(const Value* value) -> bool { - return value->kind() == Kind::TypeOfInterfaceType; - } - - auto interface_type() const -> const InterfaceType& { return *iface_type_; } - - private: - Nonnull iface_type_; -}; - -class TypeOfConstraintType : public Value { - public: - explicit TypeOfConstraintType(Nonnull constraint_type) - : Value(Kind::TypeOfConstraintType), constraint_type_(constraint_type) {} - - static auto classof(const Value* value) -> bool { - return value->kind() == Kind::TypeOfConstraintType; - } - - auto constraint_type() const -> const ConstraintType& { - return *constraint_type_; - } - - private: - Nonnull constraint_type_; -}; - -// The type of an expression whose value is a choice type. Currently there is no -// way to explicitly name such a type in Carbon code, but we are tentatively -// using `typeof(ChoiceName)` as the debug-printing format, in anticipation of -// something like that becoming valid Carbon syntax. -class TypeOfChoiceType : public Value { - public: - explicit TypeOfChoiceType(Nonnull choice_type) - : Value(Kind::TypeOfChoiceType), choice_type_(choice_type) {} - - static auto classof(const Value* value) -> bool { - return value->kind() == Kind::TypeOfChoiceType; - } - - auto choice_type() const -> const ChoiceType& { return *choice_type_; } - - private: - Nonnull choice_type_; -}; - // The type of an expression whose value is the name of a parameterized entity. // Such an expression can only be used as the operand of a call expression that // provides arguments for the parameters. diff --git a/explorer/testdata/choice/type_of_type.carbon b/explorer/testdata/choice/type_of_type.carbon new file mode 100644 index 000000000000..dfb103de7d0d --- /dev/null +++ b/explorer/testdata/choice/type_of_type.carbon @@ -0,0 +1,19 @@ +// 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 +// RUN: %{explorer-run} +// RUN: %{explorer-run-trace} +// CHECK:STDOUT: result: 0 + +package ExplorerTest api; + +choice C {} + +fn Main() -> i32 { + var a: auto = C; + // OK: Type of `C` is `Type`. + a = i32; + return 0; +} diff --git a/explorer/testdata/class/empty_class.carbon b/explorer/testdata/class/empty_class.carbon index 883e893b8ebb..39373084c43f 100644 --- a/explorer/testdata/class/empty_class.carbon +++ b/explorer/testdata/class/empty_class.carbon @@ -12,8 +12,8 @@ package ExplorerTest api; class A { fn F[me: Self]() -> i32 { return 0; } } fn Main() -> i32 { - // {} is a bit strange; its type is {}. Make sure we can properly convert a - // value of type {} to type TypeOfClassType. + // {} is a bit strange: its type is {}. Make sure we can properly convert a + // value of type {} to class type. var a: A = {}; return a.F(); } diff --git a/explorer/testdata/class/type_of_type.carbon b/explorer/testdata/class/type_of_type.carbon new file mode 100644 index 000000000000..54a27c83a043 --- /dev/null +++ b/explorer/testdata/class/type_of_type.carbon @@ -0,0 +1,19 @@ +// 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 +// RUN: %{explorer-run} +// RUN: %{explorer-run-trace} +// CHECK:STDOUT: result: 0 + +package ExplorerTest api; + +class C {} + +fn Main() -> i32 { + var a: auto = C; + // OK: Type of `C` is `Type`. + a = i32; + return 0; +} diff --git a/explorer/testdata/constraint/type_of_type.carbon b/explorer/testdata/constraint/type_of_type.carbon new file mode 100644 index 000000000000..a1c4f44cda07 --- /dev/null +++ b/explorer/testdata/constraint/type_of_type.carbon @@ -0,0 +1,19 @@ +// 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 +// RUN: %{explorer-run} +// RUN: %{explorer-run-trace} +// CHECK:STDOUT: result: 0 + +package ExplorerTest api; + +interface I {} + +fn Main() -> i32 { + var a: auto = I where .Self == i32; + // OK: Type of `I where ...` is `Type`. + a = i32; + return 0; +} diff --git a/explorer/testdata/generic_class/fail_instantiate_non_generic.carbon b/explorer/testdata/generic_class/fail_instantiate_non_generic.carbon index 7c90eb53edb0..84a3feecf7ca 100644 --- a/explorer/testdata/generic_class/fail_instantiate_non_generic.carbon +++ b/explorer/testdata/generic_class/fail_instantiate_non_generic.carbon @@ -17,7 +17,7 @@ class Point { } fn Main() -> i32 { - // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/generic_class/fail_instantiate_non_generic.carbon:[[@LINE+1]]: in call `Point(i32)`, expected callee to be a function, found `typeof(class Point)` + // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/generic_class/fail_instantiate_non_generic.carbon:[[@LINE+1]]: in call `Point(i32)`, expected callee to be a function, found `Type` var p: Point(i32) = Point.Origin(); return 0; } diff --git a/explorer/testdata/generic_class/fail_self_with_arg.carbon b/explorer/testdata/generic_class/fail_self_with_arg.carbon index ea8d60801bb4..9dfb791211f9 100644 --- a/explorer/testdata/generic_class/fail_self_with_arg.carbon +++ b/explorer/testdata/generic_class/fail_self_with_arg.carbon @@ -11,7 +11,7 @@ package ExplorerTest api; class Point(T:! Type) { // Error: wrote `Self(T)` instead of `Self`. - // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/generic_class/fail_self_with_arg.carbon:[[@LINE+1]]: in call `Self(T)`, expected callee to be a function, found `typeof(class Point(T = T))` + // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/generic_class/fail_self_with_arg.carbon:[[@LINE+1]]: in call `Self(T)`, expected callee to be a function, found `Type` fn Origin(zero: T) -> Self(T) { return {.x = zero, .y = zero}; } diff --git a/explorer/testdata/generic_class/fail_two_arg_lists.carbon b/explorer/testdata/generic_class/fail_two_arg_lists.carbon index 0b23bc8062dc..ad55183f8fab 100644 --- a/explorer/testdata/generic_class/fail_two_arg_lists.carbon +++ b/explorer/testdata/generic_class/fail_two_arg_lists.carbon @@ -9,7 +9,7 @@ package ExplorerTest api; class Point(T:! Type) { - // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/generic_class/fail_two_arg_lists.carbon:[[@LINE+1]]: in call `Point(T)(T)`, expected callee to be a function, found `typeof(class Point(T = T))` + // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/generic_class/fail_two_arg_lists.carbon:[[@LINE+1]]: in call `Point(T)(T)`, expected callee to be a function, found `Type` fn Origin(zero: T) -> Point(T)(T) { return {.x = zero, .y = zero}; } diff --git a/explorer/testdata/interface/type_of_type.carbon b/explorer/testdata/interface/type_of_type.carbon new file mode 100644 index 000000000000..843a88d16e65 --- /dev/null +++ b/explorer/testdata/interface/type_of_type.carbon @@ -0,0 +1,19 @@ +// 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 +// RUN: %{explorer-run} +// RUN: %{explorer-run-trace} +// CHECK:STDOUT: result: 0 + +package ExplorerTest api; + +interface I {} + +fn Main() -> i32 { + var a: auto = I; + // OK: Type of `I` is `Type`. + a = i32; + return 0; +} diff --git a/explorer/testdata/operators/combine.carbon b/explorer/testdata/operators/combine.carbon new file mode 100644 index 000000000000..d2406cedfc2f --- /dev/null +++ b/explorer/testdata/operators/combine.carbon @@ -0,0 +1,17 @@ +// 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 +// RUN: %{explorer-run} +// RUN: %{explorer-run-trace} +// CHECK:STDOUT: result: 0 + +package ExplorerTest api; + +fn F[T:! Type & Type](x: T) {} + +fn Main() -> i32 { + F(0); + return 0; +} diff --git a/explorer/testdata/operators/fail_combine_lhs.carbon b/explorer/testdata/operators/fail_combine_lhs.carbon new file mode 100644 index 000000000000..3bc71a9c3a1d --- /dev/null +++ b/explorer/testdata/operators/fail_combine_lhs.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 +// +// AUTOUPDATE +// RUN: %{not} %{explorer-run} +// RUN: %{not} %{explorer-run-trace} + +package ExplorerTest api; + +// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/operators/fail_combine_lhs.carbon:[[@LINE+1]]: expected a constraint in first operand of `&`, found i32 +fn F[T:! i32 & Type](); + +fn Main() -> i32 { + return 0; +} diff --git a/explorer/testdata/operators/fail_combine_rhs.carbon b/explorer/testdata/operators/fail_combine_rhs.carbon new file mode 100644 index 000000000000..57f7e1793ad8 --- /dev/null +++ b/explorer/testdata/operators/fail_combine_rhs.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 +// +// AUTOUPDATE +// RUN: %{not} %{explorer-run} +// RUN: %{not} %{explorer-run-trace} + +package ExplorerTest api; + +class C {} + +// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/operators/fail_combine_rhs.carbon:[[@LINE+1]]: expected a constraint in second operand of `&`, found class C +fn F[T:! Type & C](); + +fn Main() -> i32 { + return 0; +}