mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
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
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 {
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Vendored
+2
-3
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
Vendored
+1
-2
@@ -9,8 +9,7 @@
|
||||
|
||||
package ExplorerTest api;
|
||||
|
||||
fn Main () -> i32
|
||||
{
|
||||
fn Main() -> i32 {
|
||||
var x: i32 = 0;
|
||||
return x;
|
||||
}
|
||||
+1
-1
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user