diff --git a/explorer/interpreter/type_checker.cpp b/explorer/interpreter/type_checker.cpp index e6f0d1ebcdcd..a3bc2955b541 100644 --- a/explorer/interpreter/type_checker.cpp +++ b/explorer/interpreter/type_checker.cpp @@ -4128,9 +4128,9 @@ auto TypeChecker::TypeCheckWhereClause(Nonnull clause, } auto TypeChecker::TypeCheckPattern( - Nonnull p, std::optional> expected, - ImplScope& impl_scope, ExpressionCategory enclosing_expression_category) - -> ErrorOr { + Nonnull p, bool require_irrefutable, + std::optional> expected, ImplScope& impl_scope, + ExpressionCategory enclosing_expression_category) -> ErrorOr { if (trace_stream_->is_enabled()) { *trace_stream_ << "checking " << p->kind() << " " << *p; if (expected) { @@ -4138,6 +4138,17 @@ auto TypeChecker::TypeCheckPattern( } *trace_stream_ << "\n"; } + if (require_irrefutable) { + switch (p->kind()) { + case PatternKind::AutoPattern: + case PatternKind::ExpressionPattern: + return ProgramError(p->source_loc()) + << "An irrefutable pattern is required, but `" << *p + << "` is refutable."; + default: + break; + } + } switch (p->kind()) { case PatternKind::AutoPattern: { p->set_static_type(arena_->New()); @@ -4152,9 +4163,9 @@ auto TypeChecker::TypeCheckPattern( return ProgramError(binding.type().source_loc()) << "the type of a binding pattern cannot contain bindings"; } - CARBON_RETURN_IF_ERROR(TypeCheckPattern(&binding.type(), expected, - impl_scope, - enclosing_expression_category)); + CARBON_RETURN_IF_ERROR(TypeCheckPattern( + &binding.type(), /*require_irrefutable=*/false, expected, impl_scope, + enclosing_expression_category)); Nonnull type = &binding.type().value(); // Convert to a type. // TODO: Convert the pattern before interpreting it rather than doing @@ -4232,8 +4243,8 @@ auto TypeChecker::TypeCheckPattern( if (expected) { expected_field_type = cast(**expected).elements()[i]; } - CARBON_RETURN_IF_ERROR(TypeCheckPattern(field, expected_field_type, - impl_scope, + CARBON_RETURN_IF_ERROR(TypeCheckPattern(field, require_irrefutable, + expected_field_type, impl_scope, enclosing_expression_category)); if (trace_stream_->is_enabled()) { *trace_stream_ << "finished checking tuple pattern field " << *field @@ -4277,9 +4288,9 @@ auto TypeChecker::TypeCheckPattern( Nonnull parameter_type, Substitute(choice_type.bindings(), *(*signature)->parameters_static_type())); - CARBON_RETURN_IF_ERROR(TypeCheckPattern(&alternative.arguments(), - parameter_type, impl_scope, - enclosing_expression_category)); + CARBON_RETURN_IF_ERROR(TypeCheckPattern( + &alternative.arguments(), require_irrefutable, parameter_type, + impl_scope, enclosing_expression_category)); alternative.set_static_type(&choice_type); alternative.set_value(arena_->New( &choice_type, *signature, @@ -4299,9 +4310,9 @@ auto TypeChecker::TypeCheckPattern( case PatternKind::VarPattern: { auto& var_pattern = cast(*p); - CARBON_RETURN_IF_ERROR( - TypeCheckPattern(&var_pattern.pattern(), expected, impl_scope, - var_pattern.expression_category())); + CARBON_RETURN_IF_ERROR(TypeCheckPattern( + &var_pattern.pattern(), require_irrefutable, expected, impl_scope, + var_pattern.expression_category())); var_pattern.set_static_type(&var_pattern.pattern().static_type()); var_pattern.set_value(&var_pattern.pattern().value()); return Success(); @@ -4312,9 +4323,9 @@ auto TypeChecker::TypeCheckPattern( if (expected) { expected_ptr = arena_->New(expected.value()); } - CARBON_RETURN_IF_ERROR(TypeCheckPattern(&addr_pattern.binding(), - expected_ptr, impl_scope, - enclosing_expression_category)); + CARBON_RETURN_IF_ERROR(TypeCheckPattern( + &addr_pattern.binding(), require_irrefutable, expected_ptr, + impl_scope, enclosing_expression_category)); if (const auto* inner_binding_type = dyn_cast(&addr_pattern.binding().static_type())) { @@ -4432,9 +4443,10 @@ auto TypeChecker::TypeCheckStmt(Nonnull s, ImplScope clause_scope(&impl_scope); // TODO: Should user-defined conversions be permitted in `match` // statements? When would we run them? See #1283. - CARBON_RETURN_IF_ERROR(TypeCheckPattern( - &clause.pattern(), &match.expression().static_type(), clause_scope, - ExpressionCategory::Value)); + CARBON_RETURN_IF_ERROR( + TypeCheckPattern(&clause.pattern(), /*require_irrefutable=*/false, + &match.expression().static_type(), clause_scope, + ExpressionCategory::Value)); if (expected_type.has_value()) { // TODO: For now, we require all patterns to have the same type. If // that's not the same type as the scrutinee, we will convert the @@ -4485,10 +4497,10 @@ auto TypeChecker::TypeCheckStmt(Nonnull s, const Value& rhs = for_stmt.loop_target().static_type(); if (rhs.kind() == Value::Kind::StaticArrayType) { - CARBON_RETURN_IF_ERROR( - TypeCheckPattern(&for_stmt.variable_declaration(), - &cast(rhs).element_type(), - inner_impl_scope, ExpressionCategory::Reference)); + CARBON_RETURN_IF_ERROR(TypeCheckPattern( + &for_stmt.variable_declaration(), /*require_irrefutable=*/true, + &cast(rhs).element_type(), inner_impl_scope, + ExpressionCategory::Reference)); CARBON_RETURN_IF_ERROR(ExpectExactType( for_stmt.source_loc(), "`for` pattern", &cast(rhs).element_type(), @@ -4532,8 +4544,9 @@ auto TypeChecker::TypeCheckStmt(Nonnull s, var.init().source_loc(), &var.init().static_type())); init_type = &var.init().static_type(); } - CARBON_RETURN_IF_ERROR(TypeCheckPattern( - &var.pattern(), init_type, var_scope, var.expression_category())); + CARBON_RETURN_IF_ERROR( + TypeCheckPattern(&var.pattern(), /*require_irrefutable=*/true, + init_type, var_scope, var.expression_category())); CARBON_RETURN_IF_ERROR(ExpectCompleteType( var.source_loc(), "type of variable", &var.pattern().static_type())); CARBON_RETURN_IF_ERROR( @@ -4739,23 +4752,24 @@ auto TypeChecker::DeclareCallableDeclaration(Nonnull f, std::vector> impl_bindings; // Bring the deduced parameters into scope. for (Nonnull deduced : f->deduced_parameters()) { - CARBON_RETURN_IF_ERROR(TypeCheckPattern( - deduced, std::nullopt, function_scope, ExpressionCategory::Value)); + CARBON_RETURN_IF_ERROR( + TypeCheckPattern(deduced, /*require_irrefutable=*/true, std::nullopt, + function_scope, ExpressionCategory::Value)); CollectAndNumberGenericBindingsInPattern(deduced, all_bindings); CollectImplBindingsInPattern(deduced, impl_bindings); } // Type check the receiver pattern. if (f->is_method()) { - CARBON_RETURN_IF_ERROR(TypeCheckPattern(&f->self_pattern(), std::nullopt, - function_scope, - ExpressionCategory::Value)); + CARBON_RETURN_IF_ERROR(TypeCheckPattern( + &f->self_pattern(), /*require_irrefutable=*/true, std::nullopt, + function_scope, ExpressionCategory::Value)); CollectAndNumberGenericBindingsInPattern(&f->self_pattern(), all_bindings); CollectImplBindingsInPattern(&f->self_pattern(), impl_bindings); } // Type check the parameter pattern. - CARBON_RETURN_IF_ERROR(TypeCheckPattern(&f->param_pattern(), std::nullopt, - function_scope, - ExpressionCategory::Value)); + CARBON_RETURN_IF_ERROR(TypeCheckPattern( + &f->param_pattern(), /*require_irrefutable=*/true, std::nullopt, + function_scope, ExpressionCategory::Value)); CollectImplBindingsInPattern(&f->param_pattern(), impl_bindings); // All bindings we've seen so far in this scope are our deduced bindings. @@ -4915,8 +4929,9 @@ auto TypeChecker::DeclareClassDeclaration(Nonnull class_decl, std::vector> bindings = scope_info.bindings; if (class_decl->type_params().has_value()) { Nonnull type_params = *class_decl->type_params(); - CARBON_RETURN_IF_ERROR(TypeCheckPattern( - type_params, std::nullopt, class_scope, ExpressionCategory::Value)); + CARBON_RETURN_IF_ERROR( + TypeCheckPattern(type_params, /*require_irrefutable=*/true, + std::nullopt, class_scope, ExpressionCategory::Value)); CollectAndNumberGenericBindingsInPattern(type_params, bindings); if (trace_stream_->is_enabled()) { *trace_stream_ << class_scope; @@ -5084,9 +5099,9 @@ auto TypeChecker::DeclareMixinDeclaration(Nonnull mixin_decl, ImplScope mixin_scope(scope_info.innermost_scope); if (mixin_decl->params().has_value()) { - CARBON_RETURN_IF_ERROR(TypeCheckPattern(*mixin_decl->params(), std::nullopt, - mixin_scope, - ExpressionCategory::Value)); + CARBON_RETURN_IF_ERROR( + TypeCheckPattern(*mixin_decl->params(), /*require_irrefutable=*/true, + std::nullopt, mixin_scope, ExpressionCategory::Value)); if (trace_stream_->is_enabled()) { *trace_stream_ << mixin_scope; } @@ -5104,9 +5119,9 @@ auto TypeChecker::DeclareMixinDeclaration(Nonnull mixin_decl, } // Process the Self parameter. - CARBON_RETURN_IF_ERROR(TypeCheckPattern(mixin_decl->self(), std::nullopt, - mixin_scope, - ExpressionCategory::Value)); + CARBON_RETURN_IF_ERROR( + TypeCheckPattern(mixin_decl->self(), /*require_irrefutable=*/true, + std::nullopt, mixin_scope, ExpressionCategory::Value)); ScopeInfo mixin_scope_info = ScopeInfo::ForNonClassScope(&mixin_scope); for (Nonnull m : mixin_decl->members()) { @@ -5214,9 +5229,9 @@ auto TypeChecker::DeclareConstraintTypeDeclaration( // Type-check the parameters and find the set of bindings that are in scope. std::vector> bindings = scope_info.bindings; if (constraint_decl->params().has_value()) { - CARBON_RETURN_IF_ERROR(TypeCheckPattern(*constraint_decl->params(), - std::nullopt, constraint_scope, - ExpressionCategory::Value)); + CARBON_RETURN_IF_ERROR(TypeCheckPattern( + *constraint_decl->params(), /*require_irrefutable=*/true, std::nullopt, + constraint_scope, ExpressionCategory::Value)); if (trace_stream_->is_enabled()) { *trace_stream_ << constraint_scope; } @@ -5589,8 +5604,9 @@ auto TypeChecker::DeclareImplDeclaration(Nonnull impl_decl, // Bring the deduced parameters into scope. for (Nonnull deduced : impl_decl->deduced_parameters()) { generic_bindings.push_back(deduced); - CARBON_RETURN_IF_ERROR(TypeCheckPattern(deduced, std::nullopt, impl_scope, - ExpressionCategory::Value)); + CARBON_RETURN_IF_ERROR( + TypeCheckPattern(deduced, /*require_irrefutable=*/true, std::nullopt, + impl_scope, ExpressionCategory::Value)); CollectImplBindingsInPattern(deduced, impl_bindings); } impl_decl->set_impl_bindings(impl_bindings); @@ -5784,7 +5800,8 @@ auto TypeChecker::DeclareChoiceDeclaration(Nonnull choice, if (choice->type_params().has_value()) { Nonnull type_params = *choice->type_params(); CARBON_RETURN_IF_ERROR(TypeCheckPattern( - type_params, std::nullopt, choice_scope, ExpressionCategory::Value)); + type_params, /*require_irrefutable=*/false, std::nullopt, choice_scope, + ExpressionCategory::Value)); CollectAndNumberGenericBindingsInPattern(type_params, bindings); if (trace_stream_->is_enabled()) { *trace_stream_ << choice_scope; @@ -6107,9 +6124,9 @@ auto TypeChecker::DeclareDeclaration(Nonnull d, return ProgramError(var.binding().type().source_loc()) << "Expected expression for variable type"; } - CARBON_RETURN_IF_ERROR(TypeCheckPattern(&var.binding(), std::nullopt, - *scope_info.innermost_scope, - var.expression_category())); + CARBON_RETURN_IF_ERROR(TypeCheckPattern( + &var.binding(), /*require_irrefutable=*/true, std::nullopt, + *scope_info.innermost_scope, var.expression_category())); CARBON_RETURN_IF_ERROR(ExpectCompleteType( var.source_loc(), "type of variable", &var.binding().static_type())); CARBON_RETURN_IF_ERROR( diff --git a/explorer/interpreter/type_checker.h b/explorer/interpreter/type_checker.h index 718f5ac7213a..8d7f2014fdaa 100644 --- a/explorer/interpreter/type_checker.h +++ b/explorer/interpreter/type_checker.h @@ -196,7 +196,7 @@ class TypeChecker { // Implicit conversions from `expected` to the pattern's type are permitted. // // `impl_scope` is extended with all implementations implied by the pattern. - auto TypeCheckPattern(Nonnull p, + auto TypeCheckPattern(Nonnull p, bool require_irrefutable, std::optional> expected, ImplScope& impl_scope, ExpressionCategory enclosing_expression_category) diff --git a/explorer/testdata/function/fail_parameter_type_only.carbon b/explorer/testdata/function/fail_parameter_type_only.carbon new file mode 100644 index 000000000000..abd26bd8b6e0 --- /dev/null +++ b/explorer/testdata/function/fail_parameter_type_only.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/function/fail_parameter_type_only.carbon:[[@LINE+1]]: An irrefutable pattern is required, but `i32` is refutable. +fn f(x: i32, i32) {} + +fn Main() -> i32 { + return 0; +} diff --git a/explorer/testdata/generic_function/fail_type_only.carbon b/explorer/testdata/generic_function/fail_type_only.carbon new file mode 100644 index 000000000000..3515d2f38805 --- /dev/null +++ b/explorer/testdata/generic_function/fail_type_only.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: SYNTAX ERROR: {{.*}}/explorer/testdata/generic_function/fail_type_only.carbon:[[@LINE+1]]: syntax error, unexpected RIGHT_SQUARE_BRACKET, expecting COLON +fn f[x:! i32, addr C]() {} + +fn Main() -> i32 { + return 0; +} diff --git a/explorer/testdata/global_variable/fail_init_type_mismatch.carbon b/explorer/testdata/var/global/fail_init_type_mismatch.carbon similarity index 67% rename from explorer/testdata/global_variable/fail_init_type_mismatch.carbon rename to explorer/testdata/var/global/fail_init_type_mismatch.carbon index da26b55f5cfe..216d52dd4938 100644 --- a/explorer/testdata/global_variable/fail_init_type_mismatch.carbon +++ b/explorer/testdata/var/global/fail_init_type_mismatch.carbon @@ -10,7 +10,7 @@ package ExplorerTest api; // Test type checking of global variable. Error expected. -// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/global_variable/fail_init_type_mismatch.carbon:[[@LINE+1]]: type error in initializer of variable: 'bool' is not implicitly convertible to 'i32' +// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/var/global/fail_init_type_mismatch.carbon:[[@LINE+1]]: type error in initializer of variable: 'bool' is not implicitly convertible to 'i32' var flag: i32 = true; fn Main() -> i32 { diff --git a/explorer/testdata/global_variable/fail_instantiate_global_abstract.carbon b/explorer/testdata/var/global/fail_instantiate_global_abstract.carbon similarity index 69% rename from explorer/testdata/global_variable/fail_instantiate_global_abstract.carbon rename to explorer/testdata/var/global/fail_instantiate_global_abstract.carbon index c10f031cebb2..682cf9eb00ef 100644 --- a/explorer/testdata/global_variable/fail_instantiate_global_abstract.carbon +++ b/explorer/testdata/var/global/fail_instantiate_global_abstract.carbon @@ -11,7 +11,7 @@ package ExplorerTest api; abstract class B { } -// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/global_variable/fail_instantiate_global_abstract.carbon:[[@LINE+1]]: Cannot instantiate abstract class B +// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/var/global/fail_instantiate_global_abstract.carbon:[[@LINE+1]]: Cannot instantiate abstract class B var b: B = {}; fn Main() -> i32 { diff --git a/explorer/testdata/basic_syntax/fail_invalid_var_expression.carbon b/explorer/testdata/var/global/fail_invalid_var_expression.carbon similarity index 68% rename from explorer/testdata/basic_syntax/fail_invalid_var_expression.carbon rename to explorer/testdata/var/global/fail_invalid_var_expression.carbon index f0959a326566..af74ff4fb282 100644 --- a/explorer/testdata/basic_syntax/fail_invalid_var_expression.carbon +++ b/explorer/testdata/var/global/fail_invalid_var_expression.carbon @@ -8,7 +8,7 @@ package ExplorerTest api; -// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_invalid_var_expression.carbon:[[@LINE+1]]: Expected expression for variable type +// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/var/global/fail_invalid_var_expression.carbon:[[@LINE+1]]: Expected expression for variable type var a: auto; fn Main() -> i32 { return 0; } diff --git a/explorer/testdata/global_variable/fail_modify_in_constant_expr.carbon b/explorer/testdata/var/global/fail_modify_in_constant_expr.carbon similarity index 78% rename from explorer/testdata/global_variable/fail_modify_in_constant_expr.carbon rename to explorer/testdata/var/global/fail_modify_in_constant_expr.carbon index 05d6921c38f7..158b6dd51720 100644 --- a/explorer/testdata/global_variable/fail_modify_in_constant_expr.carbon +++ b/explorer/testdata/var/global/fail_modify_in_constant_expr.carbon @@ -13,7 +13,7 @@ var n: i32 = 0; fn F() -> type { // TODO: This isn't a very good description of the problem, which is that // compile-time evaluation doesn't have a mutable `n` value available. - // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/global_variable/fail_modify_in_constant_expr.carbon:[[@LINE+1]]: could not find `n: i32` + // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/var/global/fail_modify_in_constant_expr.carbon:[[@LINE+1]]: could not find `n: i32` n = 1; return i32; } diff --git a/explorer/testdata/global_variable/fail_named_self.carbon b/explorer/testdata/var/global/fail_named_self.carbon similarity index 72% rename from explorer/testdata/global_variable/fail_named_self.carbon rename to explorer/testdata/var/global/fail_named_self.carbon index 20052ad51ea2..611273ecec2e 100644 --- a/explorer/testdata/global_variable/fail_named_self.carbon +++ b/explorer/testdata/var/global/fail_named_self.carbon @@ -9,7 +9,7 @@ package ExplorerTest api; // Error: global variable may not be named with keyword `Self`. -// CHECK:STDERR: SYNTAX ERROR: {{.*}}/explorer/testdata/global_variable/fail_named_self.carbon:[[@LINE+1]]: syntax error, unexpected SELF, expecting identifier +// CHECK:STDERR: SYNTAX ERROR: {{.*}}/explorer/testdata/var/global/fail_named_self.carbon:[[@LINE+1]]: syntax error, unexpected SELF, expecting identifier var Self: i32 = 0; fn Main() -> i32 { diff --git a/explorer/testdata/var/global/fail_nested_binding.carbon b/explorer/testdata/var/global/fail_nested_binding.carbon new file mode 100644 index 000000000000..345bf69d4fb8 --- /dev/null +++ b/explorer/testdata/var/global/fail_nested_binding.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: %{not} %{explorer-run} +// RUN: %{not} %{explorer-run-trace} + +package ExplorerTest api; + +// If support for this is added, it'll be necessary to verify that either the +// implementation is shared with locals or that tests are copied over for edge +// cases. +// CHECK:STDERR: SYNTAX ERROR: {{.*}}/explorer/testdata/var/global/fail_nested_binding.carbon:[[@LINE+1]]: syntax error, unexpected LEFT_PARENTHESIS, expecting identifier +var (x: i32,); + +fn Main() -> i32 { + return 0; +} diff --git a/explorer/testdata/var/global/fail_type_only.carbon b/explorer/testdata/var/global/fail_type_only.carbon new file mode 100644 index 000000000000..c66377ae1efb --- /dev/null +++ b/explorer/testdata/var/global/fail_type_only.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: SYNTAX ERROR: {{.*}}/explorer/testdata/var/global/fail_type_only.carbon:[[@LINE+1]]: syntax error, unexpected sized_type_literal, expecting identifier +var i32; + +fn Main() -> i32 { + return 0; +} diff --git a/explorer/testdata/global_variable/implicit_conversion.carbon b/explorer/testdata/var/global/implicit_conversion.carbon similarity index 100% rename from explorer/testdata/global_variable/implicit_conversion.carbon rename to explorer/testdata/var/global/implicit_conversion.carbon diff --git a/explorer/testdata/global_variable/init_and_read.carbon b/explorer/testdata/var/global/init_and_read.carbon similarity index 100% rename from explorer/testdata/global_variable/init_and_read.carbon rename to explorer/testdata/var/global/init_and_read.carbon diff --git a/explorer/testdata/global_variable/init_from_function.carbon b/explorer/testdata/var/global/init_from_function.carbon similarity index 100% rename from explorer/testdata/global_variable/init_from_function.carbon rename to explorer/testdata/var/global/init_from_function.carbon diff --git a/explorer/testdata/global_variable/init_order.carbon b/explorer/testdata/var/global/init_order.carbon similarity index 100% rename from explorer/testdata/global_variable/init_order.carbon rename to explorer/testdata/var/global/init_order.carbon diff --git a/explorer/testdata/global_variable/shadowing.carbon b/explorer/testdata/var/global/shadowing.carbon similarity index 100% rename from explorer/testdata/global_variable/shadowing.carbon rename to explorer/testdata/var/global/shadowing.carbon diff --git a/explorer/testdata/global_variable/write.carbon b/explorer/testdata/var/global/write.carbon similarity index 100% rename from explorer/testdata/global_variable/write.carbon rename to explorer/testdata/var/global/write.carbon diff --git a/explorer/testdata/global_variable/write_from_function.carbon b/explorer/testdata/var/global/write_from_function.carbon similarity index 100% rename from explorer/testdata/global_variable/write_from_function.carbon rename to explorer/testdata/var/global/write_from_function.carbon diff --git a/explorer/testdata/basic_syntax/fail_missing_var.carbon b/explorer/testdata/var/local/fail_missing_intro.carbon similarity index 67% rename from explorer/testdata/basic_syntax/fail_missing_var.carbon rename to explorer/testdata/var/local/fail_missing_intro.carbon index 722b7002ead3..9cf433c65b0f 100644 --- a/explorer/testdata/basic_syntax/fail_missing_var.carbon +++ b/explorer/testdata/var/local/fail_missing_intro.carbon @@ -9,8 +9,7 @@ package ExplorerTest api; fn Main() -> i32 { - // error - // CHECK:STDERR: SYNTAX ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_missing_var.carbon:[[@LINE+1]]: syntax error, unexpected COLON - x : i32; + // CHECK:STDERR: SYNTAX ERROR: {{.*}}/explorer/testdata/var/local/fail_missing_intro.carbon:[[@LINE+1]]: syntax error, unexpected COLON + x: i32; return 1; } diff --git a/explorer/testdata/basic_syntax/fail_var_named_self.carbon b/explorer/testdata/var/local/fail_named_self_type.carbon similarity index 71% rename from explorer/testdata/basic_syntax/fail_var_named_self.carbon rename to explorer/testdata/var/local/fail_named_self_type.carbon index 849afab2526e..8134c9abfa46 100644 --- a/explorer/testdata/basic_syntax/fail_var_named_self.carbon +++ b/explorer/testdata/var/local/fail_named_self_type.carbon @@ -12,7 +12,7 @@ fn Main() -> i32 { // Error: can't use keyword `Self` as the name of a variable. // TODO: Current error message is unclear, better would be to say // something like: unexpected `Self`, expecting identifier - // CHECK:STDERR: SYNTAX ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_var_named_self.carbon:[[@LINE+1]]: syntax error, unexpected COLON, expecting EQUAL or SEMICOLON - var Self : i32 = 0; - return Self; + // CHECK:STDERR: SYNTAX ERROR: {{.*}}/explorer/testdata/var/local/fail_named_self_type.carbon:[[@LINE+1]]: syntax error, unexpected COLON, expecting EQUAL or SEMICOLON + var Self: i32 = 0; + return 0; } diff --git a/explorer/testdata/basic_syntax/fail_nested_binding.carbon b/explorer/testdata/var/local/fail_nested_binding_in_type.carbon similarity index 67% rename from explorer/testdata/basic_syntax/fail_nested_binding.carbon rename to explorer/testdata/var/local/fail_nested_binding_in_type.carbon index 5c075f34cffb..f31d364a9160 100644 --- a/explorer/testdata/basic_syntax/fail_nested_binding.carbon +++ b/explorer/testdata/var/local/fail_nested_binding_in_type.carbon @@ -9,7 +9,7 @@ package ExplorerTest api; fn Main() -> i32 { - // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_nested_binding.carbon:[[@LINE+1]]: the type of a binding pattern cannot contain bindings + // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/var/local/fail_nested_binding_in_type.carbon:[[@LINE+1]]: the type of a binding pattern cannot contain bindings var x: (T: type) = 1; return 1; } diff --git a/explorer/testdata/var/local/fail_nested_type_only.carbon b/explorer/testdata/var/local/fail_nested_type_only.carbon new file mode 100644 index 000000000000..048b7a0ac91b --- /dev/null +++ b/explorer/testdata/var/local/fail_nested_type_only.carbon @@ -0,0 +1,15 @@ +// 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; + +fn Main() -> i32 { + // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/var/local/fail_nested_type_only.carbon:[[@LINE+1]]: An irrefutable pattern is required, but `i32` is refutable. + var (x: i32, i32); + return 0; +} diff --git a/explorer/testdata/var/local/fail_type_only.carbon b/explorer/testdata/var/local/fail_type_only.carbon new file mode 100644 index 000000000000..f084437bc94a --- /dev/null +++ b/explorer/testdata/var/local/fail_type_only.carbon @@ -0,0 +1,15 @@ +// 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; + +fn Main() -> i32 { + // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/var/local/fail_type_only.carbon:[[@LINE+1]]: An irrefutable pattern is required, but `i32` is refutable. + var i32; + return 0; +} diff --git a/explorer/testdata/basic_syntax/fail_var_type.carbon b/explorer/testdata/var/local/fail_value_as_type.carbon similarity index 64% rename from explorer/testdata/basic_syntax/fail_var_type.carbon rename to explorer/testdata/var/local/fail_value_as_type.carbon index fdcdd142d9d2..7104afae82ab 100644 --- a/explorer/testdata/basic_syntax/fail_var_type.carbon +++ b/explorer/testdata/var/local/fail_value_as_type.carbon @@ -8,10 +8,9 @@ package ExplorerTest api; -fn Main () -> i32 -{ +fn Main() -> i32 { // 42 cannot be used as the type of a variable. - // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/basic_syntax/fail_var_type.carbon:[[@LINE+1]]: type error in type of name binding: 'i32' is not implicitly convertible to 'type' + // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/var/local/fail_value_as_type.carbon:[[@LINE+1]]: type error in type of name binding: 'i32' is not implicitly convertible to 'type' var x: 42 = 0; return x; } diff --git a/explorer/testdata/basic_syntax/var_tuple.carbon b/explorer/testdata/var/local/nested_binding.carbon similarity index 100% rename from explorer/testdata/basic_syntax/var_tuple.carbon rename to explorer/testdata/var/local/nested_binding.carbon diff --git a/explorer/testdata/basic_syntax/placeholder_variable.carbon b/explorer/testdata/var/local/placeholder.carbon similarity index 100% rename from explorer/testdata/basic_syntax/placeholder_variable.carbon rename to explorer/testdata/var/local/placeholder.carbon diff --git a/explorer/testdata/basic_syntax/next.carbon b/explorer/testdata/var/local/use_value.carbon similarity index 94% rename from explorer/testdata/basic_syntax/next.carbon rename to explorer/testdata/var/local/use_value.carbon index 5d95d9d82c92..922bd724e9f8 100644 --- a/explorer/testdata/basic_syntax/next.carbon +++ b/explorer/testdata/var/local/use_value.carbon @@ -9,8 +9,7 @@ package ExplorerTest api; -fn Main () -> i32 -{ +fn Main() -> i32 { var x: i32 = 0; return x; } diff --git a/explorer/testdata/returned_var/fail_duplicate_return_var.carbon b/explorer/testdata/var/returned/fail_duplicate_return_var.carbon similarity index 82% rename from explorer/testdata/returned_var/fail_duplicate_return_var.carbon rename to explorer/testdata/var/returned/fail_duplicate_return_var.carbon index 88eb8a79a7c4..bb0d7f7cd762 100644 --- a/explorer/testdata/returned_var/fail_duplicate_return_var.carbon +++ b/explorer/testdata/var/returned/fail_duplicate_return_var.carbon @@ -11,7 +11,7 @@ package ExplorerTest api; fn AddInt(a: i32, b: i32) -> i32 { returned var ret: i32 = a + b; if (a == b) { - // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/returned_var/fail_duplicate_return_var.carbon:[[@LINE+1]]: Duplicate definition of returned var also found at {{.*}}/explorer/testdata/returned_var/fail_duplicate_return_var.carbon:[[@LINE-2]] + // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/var/returned/fail_duplicate_return_var.carbon:[[@LINE+1]]: Duplicate definition of returned var also found at {{.*}}/explorer/testdata/var/returned/fail_duplicate_return_var.carbon:[[@LINE-2]] returned var ret2: i32 = a + b; } return var; diff --git a/explorer/testdata/returned_var/fail_missing_declaration.carbon b/explorer/testdata/var/returned/fail_missing_declaration.carbon similarity index 79% rename from explorer/testdata/returned_var/fail_missing_declaration.carbon rename to explorer/testdata/var/returned/fail_missing_declaration.carbon index 55b1677ae5bc..451f4a43fdae 100644 --- a/explorer/testdata/returned_var/fail_missing_declaration.carbon +++ b/explorer/testdata/var/returned/fail_missing_declaration.carbon @@ -10,7 +10,7 @@ package ExplorerTest api; fn AddInt(a: i32, b: i32) -> i32 { var ret: i32 = a + b; - // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/returned_var/fail_missing_declaration.carbon:[[@LINE+1]]: `return var` is not allowed without a returned var defined in scope. + // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/var/returned/fail_missing_declaration.carbon:[[@LINE+1]]: `return var` is not allowed without a returned var defined in scope. return var; } diff --git a/explorer/testdata/returned_var/fail_missing_return.carbon b/explorer/testdata/var/returned/fail_missing_return.carbon similarity index 72% rename from explorer/testdata/returned_var/fail_missing_return.carbon rename to explorer/testdata/var/returned/fail_missing_return.carbon index 00016a896251..dd557bb9dbf0 100644 --- a/explorer/testdata/returned_var/fail_missing_return.carbon +++ b/explorer/testdata/var/returned/fail_missing_return.carbon @@ -10,7 +10,7 @@ package ExplorerTest api; fn AddInt(a: i32, b: i32) -> i32 { returned var ret: i32 = a + b; - // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/returned_var/fail_missing_return.carbon:[[@LINE+1]]: `return ` is not allowed with a returned var defined in scope: {{.*}}/explorer/testdata/returned_var/fail_missing_return.carbon:[[@LINE-1]] + // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/var/returned/fail_missing_return.carbon:[[@LINE+1]]: `return ` is not allowed with a returned var defined in scope: {{.*}}/explorer/testdata/var/returned/fail_missing_return.carbon:[[@LINE-1]] return ret; } diff --git a/explorer/testdata/returned_var/fail_returned_var_mismatch_signature.carbon b/explorer/testdata/var/returned/fail_returned_var_mismatch_signature.carbon similarity index 79% rename from explorer/testdata/returned_var/fail_returned_var_mismatch_signature.carbon rename to explorer/testdata/var/returned/fail_returned_var_mismatch_signature.carbon index 1fc944eb2070..8edc9a70534d 100644 --- a/explorer/testdata/returned_var/fail_returned_var_mismatch_signature.carbon +++ b/explorer/testdata/var/returned/fail_returned_var_mismatch_signature.carbon @@ -10,7 +10,7 @@ package ExplorerTest api; fn Foo() { returned var x: () = (); - // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/returned_var/fail_returned_var_mismatch_signature.carbon:[[@LINE+1]]: return var; should not provide a return value, to match the function's signature. + // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/var/returned/fail_returned_var_mismatch_signature.carbon:[[@LINE+1]]: return var; should not provide a return value, to match the function's signature. return var; } diff --git a/explorer/testdata/returned_var/fail_returned_var_multi_auto.carbon b/explorer/testdata/var/returned/fail_returned_var_multi_auto.carbon similarity index 81% rename from explorer/testdata/returned_var/fail_returned_var_multi_auto.carbon rename to explorer/testdata/var/returned/fail_returned_var_multi_auto.carbon index 4e69e1dae958..6d560bb3ec37 100644 --- a/explorer/testdata/returned_var/fail_returned_var_multi_auto.carbon +++ b/explorer/testdata/var/returned/fail_returned_var_multi_auto.carbon @@ -15,7 +15,7 @@ fn Foo(a: i32, b: i32) -> auto { return var; } ret = a - b; - // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/returned_var/fail_returned_var_multi_auto.carbon:[[@LINE+1]]: Only one return is allowed in a function with an `auto` return type. + // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/var/returned/fail_returned_var_multi_auto.carbon:[[@LINE+1]]: Only one return is allowed in a function with an `auto` return type. return var; } diff --git a/explorer/testdata/returned_var/fail_returned_var_type_mismatch.carbon b/explorer/testdata/var/returned/fail_returned_var_type_mismatch.carbon similarity index 79% rename from explorer/testdata/returned_var/fail_returned_var_type_mismatch.carbon rename to explorer/testdata/var/returned/fail_returned_var_type_mismatch.carbon index 2f0baa8c89b4..b31fc2cc7816 100644 --- a/explorer/testdata/returned_var/fail_returned_var_type_mismatch.carbon +++ b/explorer/testdata/var/returned/fail_returned_var_type_mismatch.carbon @@ -9,7 +9,7 @@ package ExplorerTest api; fn AddInt(a: i32, b: i32) -> i32 { - // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/returned_var/fail_returned_var_type_mismatch.carbon:[[@LINE+1]]: type of returned var `bool` does not match return type `i32` + // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/var/returned/fail_returned_var_type_mismatch.carbon:[[@LINE+1]]: type of returned var `bool` does not match return type `i32` returned var ret: bool = true; return var; } diff --git a/explorer/testdata/returned_var/multiple_returned_var_control_flow.carbon b/explorer/testdata/var/returned/multiple_returned_var_control_flow.carbon similarity index 100% rename from explorer/testdata/returned_var/multiple_returned_var_control_flow.carbon rename to explorer/testdata/var/returned/multiple_returned_var_control_flow.carbon diff --git a/explorer/testdata/returned_var/normal_return_control_flow.carbon b/explorer/testdata/var/returned/normal_return_control_flow.carbon similarity index 100% rename from explorer/testdata/returned_var/normal_return_control_flow.carbon rename to explorer/testdata/var/returned/normal_return_control_flow.carbon diff --git a/explorer/testdata/returned_var/returned_var_auto.carbon b/explorer/testdata/var/returned/returned_var_auto.carbon similarity index 100% rename from explorer/testdata/returned_var/returned_var_auto.carbon rename to explorer/testdata/var/returned/returned_var_auto.carbon diff --git a/explorer/testdata/returned_var/returned_var_basic.carbon b/explorer/testdata/var/returned/returned_var_basic.carbon similarity index 100% rename from explorer/testdata/returned_var/returned_var_basic.carbon rename to explorer/testdata/var/returned/returned_var_basic.carbon diff --git a/explorer/testdata/returned_var/returned_var_name_lookup.carbon b/explorer/testdata/var/returned/returned_var_name_lookup.carbon similarity index 100% rename from explorer/testdata/returned_var/returned_var_name_lookup.carbon rename to explorer/testdata/var/returned/returned_var_name_lookup.carbon diff --git a/explorer/testdata/returned_var/returned_var_omitted_expression.carbon b/explorer/testdata/var/returned/returned_var_omitted_expression.carbon similarity index 100% rename from explorer/testdata/returned_var/returned_var_omitted_expression.carbon rename to explorer/testdata/var/returned/returned_var_omitted_expression.carbon