Przeglądaj źródła

Require names where we expect binding patterns (#2782)

This also clusters the various `var` tests. This tests similar patterns for a few syntaxes, but `fn f(x: i32, i32) {}` and local variables `var (x: i32, i32);` and `var i32;` were the crashers I found.

In `fn`, the `x: i32,` is helpful to convince the parser that this is valid syntax.

Fixes #2778
Jon Ross-Perkins 3 lat temu
rodzic
commit
c9f0ef9e2c
39 zmienionych plików z 188 dodań i 75 usunięć
  1. 68 51
      explorer/interpreter/type_checker.cpp
  2. 1 1
      explorer/interpreter/type_checker.h
  3. 16 0
      explorer/testdata/function/fail_parameter_type_only.carbon
  4. 18 0
      explorer/testdata/generic_function/fail_type_only.carbon
  5. 1 1
      explorer/testdata/var/global/fail_init_type_mismatch.carbon
  6. 1 1
      explorer/testdata/var/global/fail_instantiate_global_abstract.carbon
  7. 1 1
      explorer/testdata/var/global/fail_invalid_var_expression.carbon
  8. 1 1
      explorer/testdata/var/global/fail_modify_in_constant_expr.carbon
  9. 1 1
      explorer/testdata/var/global/fail_named_self.carbon
  10. 19 0
      explorer/testdata/var/global/fail_nested_binding.carbon
  11. 16 0
      explorer/testdata/var/global/fail_type_only.carbon
  12. 0 0
      explorer/testdata/var/global/implicit_conversion.carbon
  13. 0 0
      explorer/testdata/var/global/init_and_read.carbon
  14. 0 0
      explorer/testdata/var/global/init_from_function.carbon
  15. 0 0
      explorer/testdata/var/global/init_order.carbon
  16. 0 0
      explorer/testdata/var/global/shadowing.carbon
  17. 0 0
      explorer/testdata/var/global/write.carbon
  18. 0 0
      explorer/testdata/var/global/write_from_function.carbon
  19. 2 3
      explorer/testdata/var/local/fail_missing_intro.carbon
  20. 3 3
      explorer/testdata/var/local/fail_named_self_type.carbon
  21. 1 1
      explorer/testdata/var/local/fail_nested_binding_in_type.carbon
  22. 15 0
      explorer/testdata/var/local/fail_nested_type_only.carbon
  23. 15 0
      explorer/testdata/var/local/fail_type_only.carbon
  24. 2 3
      explorer/testdata/var/local/fail_value_as_type.carbon
  25. 0 0
      explorer/testdata/var/local/nested_binding.carbon
  26. 0 0
      explorer/testdata/var/local/placeholder.carbon
  27. 1 2
      explorer/testdata/var/local/use_value.carbon
  28. 1 1
      explorer/testdata/var/returned/fail_duplicate_return_var.carbon
  29. 1 1
      explorer/testdata/var/returned/fail_missing_declaration.carbon
  30. 1 1
      explorer/testdata/var/returned/fail_missing_return.carbon
  31. 1 1
      explorer/testdata/var/returned/fail_returned_var_mismatch_signature.carbon
  32. 1 1
      explorer/testdata/var/returned/fail_returned_var_multi_auto.carbon
  33. 1 1
      explorer/testdata/var/returned/fail_returned_var_type_mismatch.carbon
  34. 0 0
      explorer/testdata/var/returned/multiple_returned_var_control_flow.carbon
  35. 0 0
      explorer/testdata/var/returned/normal_return_control_flow.carbon
  36. 0 0
      explorer/testdata/var/returned/returned_var_auto.carbon
  37. 0 0
      explorer/testdata/var/returned/returned_var_basic.carbon
  38. 0 0
      explorer/testdata/var/returned/returned_var_name_lookup.carbon
  39. 0 0
      explorer/testdata/var/returned/returned_var_omitted_expression.carbon

+ 68 - 51
explorer/interpreter/type_checker.cpp

@@ -4128,9 +4128,9 @@ auto TypeChecker::TypeCheckWhereClause(Nonnull<WhereClause*> clause,
 }
 
 auto TypeChecker::TypeCheckPattern(
-    Nonnull<Pattern*> p, std::optional<Nonnull<const Value*>> expected,
-    ImplScope& impl_scope, ExpressionCategory enclosing_expression_category)
-    -> ErrorOr<Success> {
+    Nonnull<Pattern*> p, bool require_irrefutable,
+    std::optional<Nonnull<const Value*>> expected, ImplScope& impl_scope,
+    ExpressionCategory enclosing_expression_category) -> ErrorOr<Success> {
   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<TypeType>());
@@ -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<const Value*> 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<TupleType>(**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<const Value*> 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<AlternativeValue>(
           &choice_type, *signature,
@@ -4299,9 +4310,9 @@ auto TypeChecker::TypeCheckPattern(
     case PatternKind::VarPattern: {
       auto& var_pattern = cast<VarPattern>(*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<PointerType>(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<PointerType>(&addr_pattern.binding().static_type())) {
@@ -4432,9 +4443,10 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> 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<Statement*> 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<StaticArrayType>(rhs).element_type(),
-                             inner_impl_scope, ExpressionCategory::Reference));
+        CARBON_RETURN_IF_ERROR(TypeCheckPattern(
+            &for_stmt.variable_declaration(), /*require_irrefutable=*/true,
+            &cast<StaticArrayType>(rhs).element_type(), inner_impl_scope,
+            ExpressionCategory::Reference));
         CARBON_RETURN_IF_ERROR(ExpectExactType(
             for_stmt.source_loc(), "`for` pattern",
             &cast<StaticArrayType>(rhs).element_type(),
@@ -4532,8 +4544,9 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> 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<CallableDeclaration*> f,
   std::vector<Nonnull<const ImplBinding*>> impl_bindings;
   // Bring the deduced parameters into scope.
   for (Nonnull<GenericBinding*> 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<ClassDeclaration*> class_decl,
   std::vector<Nonnull<const GenericBinding*>> bindings = scope_info.bindings;
   if (class_decl->type_params().has_value()) {
     Nonnull<TuplePattern*> 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<MixinDeclaration*> 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<MixinDeclaration*> 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<Declaration*> 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<Nonnull<const GenericBinding*>> 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<ImplDeclaration*> impl_decl,
   // Bring the deduced parameters into scope.
   for (Nonnull<GenericBinding*> 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<ChoiceDeclaration*> choice,
   if (choice->type_params().has_value()) {
     Nonnull<TuplePattern*> 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<Declaration*> 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(

+ 1 - 1
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<Pattern*> p,
+  auto TypeCheckPattern(Nonnull<Pattern*> p, bool require_irrefutable,
                         std::optional<Nonnull<const Value*>> expected,
                         ImplScope& impl_scope,
                         ExpressionCategory enclosing_expression_category)

+ 16 - 0
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;
+}

+ 18 - 0
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;
+}

+ 1 - 1
explorer/testdata/global_variable/fail_init_type_mismatch.carbon → 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 {

+ 1 - 1
explorer/testdata/global_variable/fail_instantiate_global_abstract.carbon → 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 {

+ 1 - 1
explorer/testdata/basic_syntax/fail_invalid_var_expression.carbon → 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; }

+ 1 - 1
explorer/testdata/global_variable/fail_modify_in_constant_expr.carbon → 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;
 }

+ 1 - 1
explorer/testdata/global_variable/fail_named_self.carbon → 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 {

+ 19 - 0
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;
+}

+ 16 - 0
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;
+}

+ 0 - 0
explorer/testdata/global_variable/implicit_conversion.carbon → explorer/testdata/var/global/implicit_conversion.carbon


+ 0 - 0
explorer/testdata/global_variable/init_and_read.carbon → explorer/testdata/var/global/init_and_read.carbon


+ 0 - 0
explorer/testdata/global_variable/init_from_function.carbon → explorer/testdata/var/global/init_from_function.carbon


+ 0 - 0
explorer/testdata/global_variable/init_order.carbon → explorer/testdata/var/global/init_order.carbon


+ 0 - 0
explorer/testdata/global_variable/shadowing.carbon → explorer/testdata/var/global/shadowing.carbon


+ 0 - 0
explorer/testdata/global_variable/write.carbon → explorer/testdata/var/global/write.carbon


+ 0 - 0
explorer/testdata/global_variable/write_from_function.carbon → explorer/testdata/var/global/write_from_function.carbon


+ 2 - 3
explorer/testdata/basic_syntax/fail_missing_var.carbon → 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;
 }

+ 3 - 3
explorer/testdata/basic_syntax/fail_var_named_self.carbon → 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;
 }

+ 1 - 1
explorer/testdata/basic_syntax/fail_nested_binding.carbon → 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;
 }

+ 15 - 0
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;
+}

+ 15 - 0
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;
+}

+ 2 - 3
explorer/testdata/basic_syntax/fail_var_type.carbon → 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;
 }

+ 0 - 0
explorer/testdata/basic_syntax/var_tuple.carbon → explorer/testdata/var/local/nested_binding.carbon


+ 0 - 0
explorer/testdata/basic_syntax/placeholder_variable.carbon → explorer/testdata/var/local/placeholder.carbon


+ 1 - 2
explorer/testdata/basic_syntax/next.carbon → 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;
 }

+ 1 - 1
explorer/testdata/returned_var/fail_duplicate_return_var.carbon → 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;

+ 1 - 1
explorer/testdata/returned_var/fail_missing_declaration.carbon → 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;
 }
 

+ 1 - 1
explorer/testdata/returned_var/fail_missing_return.carbon → 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 <expression>` 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 <expression>` is not allowed with a returned var defined in scope: {{.*}}/explorer/testdata/var/returned/fail_missing_return.carbon:[[@LINE-1]]
   return ret;
 }
 

+ 1 - 1
explorer/testdata/returned_var/fail_returned_var_mismatch_signature.carbon → 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;
 }
 

+ 1 - 1
explorer/testdata/returned_var/fail_returned_var_multi_auto.carbon → 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;
 }
 

+ 1 - 1
explorer/testdata/returned_var/fail_returned_var_type_mismatch.carbon → 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;
 }

+ 0 - 0
explorer/testdata/returned_var/multiple_returned_var_control_flow.carbon → explorer/testdata/var/returned/multiple_returned_var_control_flow.carbon


+ 0 - 0
explorer/testdata/returned_var/normal_return_control_flow.carbon → explorer/testdata/var/returned/normal_return_control_flow.carbon


+ 0 - 0
explorer/testdata/returned_var/returned_var_auto.carbon → explorer/testdata/var/returned/returned_var_auto.carbon


+ 0 - 0
explorer/testdata/returned_var/returned_var_basic.carbon → explorer/testdata/var/returned/returned_var_basic.carbon


+ 0 - 0
explorer/testdata/returned_var/returned_var_name_lookup.carbon → explorer/testdata/var/returned/returned_var_name_lookup.carbon


+ 0 - 0
explorer/testdata/returned_var/returned_var_omitted_expression.carbon → explorer/testdata/var/returned/returned_var_omitted_expression.carbon