diff --git a/common/fuzzing/proto_to_carbon.cpp b/common/fuzzing/proto_to_carbon.cpp index df1b4f254449..139f4802e886 100644 --- a/common/fuzzing/proto_to_carbon.cpp +++ b/common/fuzzing/proto_to_carbon.cpp @@ -383,8 +383,11 @@ static auto ExpressionToCarbon(const Fuzzing::Expression& expression, expression.array_type_literal(); out << "["; ExpressionToCarbon(array_literal.element_type(), out); - out << "; "; - ExpressionToCarbon(array_literal.size(), out); + out << ";"; + if (array_literal.has_size()) { + out << " "; + ExpressionToCarbon(array_literal.size(), out); + } out << "]"; break; } diff --git a/explorer/ast/expression.cpp b/explorer/ast/expression.cpp index 61a44b599a7e..a7f64374378a 100644 --- a/explorer/ast/expression.cpp +++ b/explorer/ast/expression.cpp @@ -287,8 +287,11 @@ void Expression::Print(llvm::raw_ostream& out) const { } case ExpressionKind::ArrayTypeLiteral: { const auto& array_literal = cast(*this); - out << "[" << array_literal.element_type_expression() << "; " - << array_literal.size_expression() << "]"; + out << "[" << array_literal.element_type_expression() << ";"; + if (array_literal.has_size_expression()) { + out << " " << array_literal.size_expression(); + } + out << "]"; break; } case ExpressionKind::IdentifierExpression: diff --git a/explorer/ast/expression.h b/explorer/ast/expression.h index cac6ab2588db..fe37ec06c461 100644 --- a/explorer/ast/expression.h +++ b/explorer/ast/expression.h @@ -1217,9 +1217,9 @@ class ArrayTypeLiteral : public ConstantValueLiteral { public: // Constructs an array type literal which uses the given expressions to // represent the element type and size. - explicit ArrayTypeLiteral(SourceLocation source_loc, - Nonnull element_type_expression, - Nonnull size_expression) + explicit ArrayTypeLiteral( + SourceLocation source_loc, Nonnull element_type_expression, + std::optional> size_expression = std::nullopt) : ConstantValueLiteral(AstNodeKind::ArrayTypeLiteral, source_loc), element_type_expression_(element_type_expression), size_expression_(size_expression) {} @@ -1241,14 +1241,22 @@ class ArrayTypeLiteral : public ConstantValueLiteral { return *element_type_expression_; } + auto has_size_expression() const -> bool { + return size_expression_.has_value(); + } + auto size_expression() const -> const Expression& { - return *size_expression_; + CARBON_CHECK(size_expression_.has_value()); + return **size_expression_; + } + auto size_expression() -> Expression& { + CARBON_CHECK(size_expression_.has_value()); + return **size_expression_; } - auto size_expression() -> Expression& { return *size_expression_; } private: Nonnull element_type_expression_; - Nonnull size_expression_; + std::optional> size_expression_; }; // Converts paren_contents to an Expression, interpreting the parentheses as diff --git a/explorer/ast/value.cpp b/explorer/ast/value.cpp index 04fa25514555..f4bf04a1aae9 100644 --- a/explorer/ast/value.cpp +++ b/explorer/ast/value.cpp @@ -703,8 +703,11 @@ void Value::Print(llvm::raw_ostream& out) const { } case Value::Kind::StaticArrayType: { const auto& array_type = cast(*this); - out << "[" << array_type.element_type() << "; " << array_type.size() - << "]"; + out << "[" << array_type.element_type() << ";"; + if (array_type.has_size()) { + out << " " << array_type.size(); + } + out << "]"; break; } } diff --git a/explorer/ast/value.h b/explorer/ast/value.h index ae22aaf7f442..e8798b43ed7e 100644 --- a/explorer/ast/value.h +++ b/explorer/ast/value.h @@ -1578,7 +1578,8 @@ class StaticArrayType : public Value { public: // Constructs a statically-sized array type with the given element type and // size. - StaticArrayType(Nonnull element_type, size_t size) + StaticArrayType(Nonnull element_type, + std::optional size) : Value(Kind::StaticArrayType), element_type_(element_type), size_(size) {} @@ -1593,11 +1594,15 @@ class StaticArrayType : public Value { } auto element_type() const -> const Value& { return *element_type_; } - auto size() const -> size_t { return size_; } + auto size() const -> size_t { + CARBON_CHECK(has_size()); + return *size_; + } + auto has_size() const -> bool { return size_.has_value(); } private: Nonnull element_type_; - size_t size_; + std::optional size_; }; template diff --git a/explorer/fuzzing/ast_to_proto.cpp b/explorer/fuzzing/ast_to_proto.cpp index d9b9aff29a7e..e3d51f05f8fb 100644 --- a/explorer/fuzzing/ast_to_proto.cpp +++ b/explorer/fuzzing/ast_to_proto.cpp @@ -354,8 +354,10 @@ static auto ExpressionToProto(const Expression& expression) expression_proto.mutable_array_type_literal(); *array_literal_proto->mutable_element_type() = ExpressionToProto(array_literal.element_type_expression()); - *array_literal_proto->mutable_size() = - ExpressionToProto(array_literal.size_expression()); + if (array_literal.has_size_expression()) { + *array_literal_proto->mutable_size() = + ExpressionToProto(array_literal.size_expression()); + } break; } } diff --git a/explorer/interpreter/interpreter.cpp b/explorer/interpreter/interpreter.cpp index b42062987052..69a0b2d4b12a 100644 --- a/explorer/interpreter/interpreter.cpp +++ b/explorer/interpreter/interpreter.cpp @@ -412,6 +412,20 @@ auto PatternMatch(Nonnull p, Nonnull v, // `auto` matches any type, without binding any new names. We rely // on the typechecker to ensure that `v` is a type. return true; + case Value::Kind::StaticArrayType: { + switch (v->kind()) { + case Value::Kind::TupleType: + case Value::Kind::TupleValue: { + return true; + } + case Value::Kind::StaticArrayType: { + const auto& v_arr = cast(*v); + return v_arr.has_size(); + } + default: + return false; + } + } default: return ValueEqual(p, v, std::nullopt); } @@ -838,6 +852,7 @@ auto Interpreter::Convert(Nonnull value, break; case Value::Kind::StaticArrayType: { const auto& array_type = cast(*destination_type); + CARBON_CHECK(array_type.has_size()); destination_element_types.resize(array_type.size(), &array_type.element_type()); break; @@ -2121,6 +2136,7 @@ auto Interpreter::StepStmt() -> ErrorOr { v, Convert(act.results()[0], dest_type, stmt.source_loc())); } else if (dest_type->kind() == Value::Kind::StaticArrayType) { const auto& array = cast(dest_type); + CARBON_CHECK(array->has_size()); const auto& element_type = array->element_type(); const auto size = array->size(); @@ -2289,6 +2305,7 @@ auto Interpreter::StepDeclaration() -> ErrorOr { } } else if (var_type->kind() == Value::Kind::StaticArrayType) { const auto& array = cast(var_type); + CARBON_CHECK(array->has_size()); const auto& element_type = array->element_type(); const auto size = array->size(); diff --git a/explorer/interpreter/resolve_names.cpp b/explorer/interpreter/resolve_names.cpp index f5b2ccaf06f5..de63d3716dac 100644 --- a/explorer/interpreter/resolve_names.cpp +++ b/explorer/interpreter/resolve_names.cpp @@ -412,8 +412,10 @@ auto NameResolver::ResolveNames(Expression& expression, auto& array_literal = cast(expression); CARBON_RETURN_IF_ERROR(ResolveNames( array_literal.element_type_expression(), enclosing_scope)); - CARBON_RETURN_IF_ERROR( - ResolveNames(array_literal.size_expression(), enclosing_scope)); + if (array_literal.has_size_expression()) { + CARBON_RETURN_IF_ERROR( + ResolveNames(array_literal.size_expression(), enclosing_scope)); + } break; } case ExpressionKind::BoolTypeLiteral: diff --git a/explorer/interpreter/type_checker.cpp b/explorer/interpreter/type_checker.cpp index c631c58aee09..9544f86e65b5 100644 --- a/explorer/interpreter/type_checker.cpp +++ b/explorer/interpreter/type_checker.cpp @@ -320,7 +320,7 @@ static auto ExpectConcreteType(SourceLocation source_loc, // Returns whether *value represents the type of a Carbon value, as // opposed to a type pattern or a non-type value. -static auto TypeContainsAuto(Nonnull type) -> bool { +static auto TypeIsDeduceable(Nonnull type) -> bool { CARBON_CHECK(IsType(type)) << "expected a type, but found " << *type; switch (type->kind()) { @@ -375,13 +375,15 @@ static auto TypeContainsAuto(Nonnull type) -> bool { return llvm::any_of( llvm::map_range(cast(type)->fields(), [](const NamedValue& v) { return v.value; }), - TypeContainsAuto); + TypeIsDeduceable); case Value::Kind::TupleType: - return llvm::any_of(cast(type)->elements(), TypeContainsAuto); + return llvm::any_of(cast(type)->elements(), TypeIsDeduceable); case Value::Kind::PointerType: - return TypeContainsAuto(&cast(type)->pointee_type()); + return TypeIsDeduceable(&cast(type)->pointee_type()); case Value::Kind::StaticArrayType: - return TypeContainsAuto(&cast(type)->element_type()); + const auto* array_type = cast(type); + return !array_type->has_size() || + TypeIsDeduceable(&array_type->element_type()); } } @@ -395,8 +397,60 @@ static auto IsPlaceholderType(Nonnull type) -> bool { // Returns whether `value` is a concrete type, which would be valid as the // static type of an expression. This is currently any type other than `auto`. -static auto IsConcreteType(Nonnull value) -> bool { - return IsType(value) && !TypeContainsAuto(value); +static auto IsNonDeduceableType(Nonnull value) -> bool { + return IsType(value) && !TypeIsDeduceable(value); +} + +static auto ExpectResolvedBindingType(const BindingPattern& binding, + Nonnull type) + -> ErrorOr { + switch (type->kind()) { + case Value::Kind::AutoType: { + auto error = ProgramError(binding.source_loc()); + error << "cannot deduce `auto` type for "; + if (type != &binding.type().value()) { + error << *type << " in "; + } + return error << binding; + } + case Value::Kind::StructType: { + const auto fields = cast(type)->fields(); + for (const auto& field : fields) { + if (auto result = ExpectResolvedBindingType(binding, field.value); + !result.ok()) { + return result; + } + } + return Success(); + } + case Value::Kind::TupleType: { + const auto elems = cast(type)->elements(); + for (const auto* elem : elems) { + if (auto result = ExpectResolvedBindingType(binding, elem); + !result.ok()) { + return result; + } + } + return Success(); + } + case Value::Kind::PointerType: + return ExpectResolvedBindingType( + binding, &cast(type)->pointee_type()); + case Value::Kind::StaticArrayType: { + const auto* array_type = cast(type); + if (!array_type->has_size()) { + auto error = ProgramError(binding.source_loc()); + error << "cannot deduce size for "; + if (type != &binding.type().value()) { + error << *array_type << " in "; + } + return error << binding; + } + return ExpectResolvedBindingType(binding, &array_type->element_type()); + } + default: + return Success(); + } } // Returns whether the given value is template-dependent, that is, if it @@ -535,8 +589,8 @@ auto TypeChecker::IsImplicitlyConvertible( // Check for an exact match or for an implicit conversion. // TODO: `impl` definitions of `ImplicitAs` should be provided to cover these // conversions. - CARBON_CHECK(IsConcreteType(source)); - CARBON_CHECK(IsConcreteType(destination)); + CARBON_CHECK(IsNonDeduceableType(source)); + CARBON_CHECK(IsNonDeduceableType(destination)); if (IsSameType(source, destination, impl_scope)) { return true; } @@ -3983,22 +4037,26 @@ auto TypeChecker::TypeCheckExp(Nonnull e, Nonnull element_type, TypeCheckTypeExp(&array_literal.element_type_expression(), impl_scope)); - CARBON_RETURN_IF_ERROR( - TypeCheckExp(&array_literal.size_expression(), impl_scope)); - CARBON_RETURN_IF_ERROR(ExpectExactType( - array_literal.size_expression().source_loc(), "array size", - arena_->New(), - &array_literal.size_expression().static_type(), impl_scope)); - CARBON_ASSIGN_OR_RETURN(Nonnull size_value, - InterpExp(&array_literal.size_expression())); - if (cast(size_value)->value() < 0) { - return ProgramError(array_literal.size_expression().source_loc()) - << "Array size cannot be negative"; + std::optional array_size; + if (array_literal.has_size_expression()) { + CARBON_RETURN_IF_ERROR( + TypeCheckExp(&array_literal.size_expression(), impl_scope)); + CARBON_RETURN_IF_ERROR(ExpectExactType( + array_literal.size_expression().source_loc(), "array size", + arena_->New(), + &array_literal.size_expression().static_type(), impl_scope)); + CARBON_ASSIGN_OR_RETURN(Nonnull size_value, + InterpExp(&array_literal.size_expression())); + if (cast(size_value)->value() < 0) { + return ProgramError(array_literal.size_expression().source_loc()) + << "Array size cannot be negative"; + } + array_size = cast(size_value)->value(); } array_literal.set_static_type(arena_->New()); array_literal.set_expression_category(ExpressionCategory::Value); - array_literal.set_constant_value(arena_->New( - element_type, cast(size_value)->value())); + array_literal.set_constant_value( + arena_->New(element_type, array_size)); return Success(); } } @@ -4066,11 +4124,11 @@ auto TypeChecker::TypeCheckTypeExp(Nonnull type_expression, CARBON_CHECK(IsType(type)) << "type expression did not produce a type, got " << *type; if (concrete) { - if (TypeContainsAuto(type)) { + if (TypeIsDeduceable(type)) { return ProgramError(type_expression->source_loc()) << "`auto` is not permitted in this context"; } - CARBON_CHECK(IsConcreteType(type)) + CARBON_CHECK(IsNonDeduceableType(type)) << "unknown kind of non-concrete type " << *type; } CARBON_CHECK(!IsPlaceholderType(type)) @@ -4130,6 +4188,24 @@ auto TypeChecker::TypeCheckWhereClause(Nonnull clause, } } +// Returns the list size for type deduction. +static auto GetSize(Nonnull from) -> size_t { + switch (from->kind()) { + case Value::Kind::TupleType: + case Value::Kind::TupleValue: { + const auto& from_tup = cast(*from); + return from_tup.elements().size(); + } + case Value::Kind::StaticArrayType: { + const auto& from_arr = cast(*from); + CARBON_CHECK(from_arr.has_size()); + return from_arr.size(); + } + default: + return 0; + } +} + auto TypeChecker::TypeCheckPattern( Nonnull p, PatternRequirements requirements, std::optional> expected, ImplScope& impl_scope, @@ -4192,7 +4268,7 @@ auto TypeChecker::TypeCheckPattern( if (expected) { // TODO: Per proposal #2188, we should be performing conversions at // this level rather than on the overall initializer. - if (!IsConcreteType(type)) { + if (!IsNonDeduceableType(type)) { BindingMap generic_args; if (!PatternMatch(type, *expected, binding.type().source_loc(), std::nullopt, generic_args, trace_stream_, @@ -4201,14 +4277,23 @@ auto TypeChecker::TypeCheckPattern( << "type pattern '" << *type << "' does not match actual type '" << **expected << "'"; } - type = *expected; + + if (type->kind() == Value::Kind::StaticArrayType) { + const auto& arr = cast(*type); + CARBON_CHECK(!arr.has_size()); + const size_t size = GetSize(*expected); + type = arena_->New(&arr.element_type(), size); + } else { + type = *expected; + } } - } else if (TypeContainsAuto(type)) { - return ProgramError(binding.source_loc()) - << "cannot deduce `auto` type for " << binding; + } else { + CARBON_RETURN_IF_ERROR(ExpectResolvedBindingType(binding, type)); } - CARBON_CHECK(IsConcreteType(type)) << "did not resolve " << binding - << " to concrete type, got " << *type; + + CARBON_CHECK(IsNonDeduceableType(type)) + << "did not resolve " << binding << " to concrete type, got " + << *type; CARBON_CHECK(!IsPlaceholderType(type)) << "should be no way to write a placeholder type"; binding.set_static_type(type); @@ -4638,8 +4723,8 @@ auto TypeChecker::TypeCheckStmt(Nonnull s, return_term.set_static_type(&ret.value_node().static_type()); } else { // TODO: Consider using `ExpectExactType` here. - CARBON_CHECK(IsConcreteType(&return_term.static_type())); - CARBON_CHECK(IsConcreteType(&ret.value_node().static_type())); + CARBON_CHECK(IsNonDeduceableType(&return_term.static_type())); + CARBON_CHECK(IsNonDeduceableType(&ret.value_node().static_type())); if (!IsSameType(&return_term.static_type(), &ret.value_node().static_type(), impl_scope)) { return ProgramError(ret.value_node().base().source_loc()) @@ -4825,7 +4910,7 @@ auto TypeChecker::DeclareCallableDeclaration(Nonnull f, ExpectReturnOnAllPaths(f->body(), f->source_loc())); } } - CARBON_CHECK(IsConcreteType(&f->return_term().static_type())); + CARBON_CHECK(IsNonDeduceableType(&f->return_term().static_type())); f->set_static_type(arena_->New( &f->param_pattern().static_type(), std::move(generic_parameters), diff --git a/explorer/syntax/parser.ypp b/explorer/syntax/parser.ypp index 126dca659ee0..fbb4653a473e 100644 --- a/explorer/syntax/parser.ypp +++ b/explorer/syntax/parser.ypp @@ -421,6 +421,11 @@ primary_expression: $$ = arena->New(context.source_loc(), $[type_expression], $[size_expression]); } +| LEFT_SQUARE_BRACKET expression[type_expression] SEMICOLON RIGHT_SQUARE_BRACKET + { + $$ = arena->New(context.source_loc(), + $[type_expression]); + } ; postfix_expression: primary_expression diff --git a/explorer/testdata/array/deduce_size_from_array.carbon b/explorer/testdata/array/deduce_size_from_array.carbon new file mode 100644 index 000000000000..a633b93c87ce --- /dev/null +++ b/explorer/testdata/array/deduce_size_from_array.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 +// CHECK:STDOUT: result: 0 + +package ExplorerTest api; + +fn Main() -> i32 { + var arr: [i32; 2] = (0, 1); + var x: [i32;] = arr; + var index: i32 = 1; + x[index] = 0; + return x[0] + x[1]; +} diff --git a/explorer/testdata/array/deduce_size_from_array_destructured.carbon b/explorer/testdata/array/deduce_size_from_array_destructured.carbon new file mode 100644 index 000000000000..a0271c9f6fb5 --- /dev/null +++ b/explorer/testdata/array/deduce_size_from_array_destructured.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 +// CHECK:STDOUT: result: 0 + +package ExplorerTest api; + +fn Main() -> i32 { + var arr: [i32; 2] = (0, 1); + var (x: auto, y: [i32;]) = (1, arr); + var index: i32 = 1; + y[index] = 0; + return y[0] + y[1]; +} diff --git a/explorer/testdata/array/deduce_size_from_tuple.carbon b/explorer/testdata/array/deduce_size_from_tuple.carbon new file mode 100644 index 000000000000..49b0c71c1a35 --- /dev/null +++ b/explorer/testdata/array/deduce_size_from_tuple.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 +// CHECK:STDOUT: result: 0 + +package ExplorerTest api; + +fn Main() -> i32 { + var x: [i32;] = (0, 1); + var index: i32 = 1; + x[index] = 0; + return x[0] + x[1]; +} diff --git a/explorer/testdata/array/deduce_size_from_tuple_destructured.carbon b/explorer/testdata/array/deduce_size_from_tuple_destructured.carbon new file mode 100644 index 000000000000..d99c8f53d2b0 --- /dev/null +++ b/explorer/testdata/array/deduce_size_from_tuple_destructured.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 +// CHECK:STDOUT: result: 0 + +package ExplorerTest api; + +fn Main() -> i32 { + var (x: auto, y: [i32;]) = (42, (0, 1)); + var index: i32 = 1; + y[index] = 0; + return y[0] + y[1]; +} diff --git a/explorer/testdata/array/deduce_zero_size_from_array.carbon b/explorer/testdata/array/deduce_zero_size_from_array.carbon new file mode 100644 index 000000000000..ddaba323920c --- /dev/null +++ b/explorer/testdata/array/deduce_zero_size_from_array.carbon @@ -0,0 +1,14 @@ +// 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 +// CHECK:STDOUT: result: 0 + +package ExplorerTest api; + +fn Main() -> i32 { + var a: [i32;0] = (); + var b: [i32;] = a; + return 0; +} diff --git a/explorer/testdata/array/deduce_zero_size_from_empty_tuple.carbon b/explorer/testdata/array/deduce_zero_size_from_empty_tuple.carbon new file mode 100644 index 000000000000..dacedd79e935 --- /dev/null +++ b/explorer/testdata/array/deduce_zero_size_from_empty_tuple.carbon @@ -0,0 +1,13 @@ +// 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 +// CHECK:STDOUT: result: 0 + +package ExplorerTest api; + +fn Main() -> i32 { + var a: [i32;] = (); + return 0; +} diff --git a/explorer/testdata/array/fail_index_deduced_size_from_array.carbon b/explorer/testdata/array/fail_index_deduced_size_from_array.carbon new file mode 100644 index 000000000000..24293e1848d6 --- /dev/null +++ b/explorer/testdata/array/fail_index_deduced_size_from_array.carbon @@ -0,0 +1,14 @@ +// 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 + +package ExplorerTest api; + +fn Main() -> i32 { + var arr: [i32; 2] = (0, 1); + var x: [i32;] = arr; + // CHECK:STDERR: RUNTIME ERROR: fail_index_deduced_size_from_array.carbon:[[@LINE+1]]: index 2 out of range in (0, 1) + return x[2]; +} diff --git a/explorer/testdata/array/fail_index_deduced_size_from_tuple.carbon b/explorer/testdata/array/fail_index_deduced_size_from_tuple.carbon new file mode 100644 index 000000000000..1676f9d3b8b3 --- /dev/null +++ b/explorer/testdata/array/fail_index_deduced_size_from_tuple.carbon @@ -0,0 +1,13 @@ +// 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 + +package ExplorerTest api; + +fn Main() -> i32 { + var x: [i32;] = (0, 1); + // CHECK:STDERR: RUNTIME ERROR: fail_index_deduced_size_from_tuple.carbon:[[@LINE+1]]: index 2 out of range in (0, 1) + return x[2]; +} diff --git a/explorer/testdata/array/fail_to_deduce_nested_array_size_in_tuple_no_expression_to_deduce_from.carbon b/explorer/testdata/array/fail_to_deduce_nested_array_size_in_tuple_no_expression_to_deduce_from.carbon new file mode 100644 index 000000000000..e538e063032e --- /dev/null +++ b/explorer/testdata/array/fail_to_deduce_nested_array_size_in_tuple_no_expression_to_deduce_from.carbon @@ -0,0 +1,13 @@ +// 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 + +package ExplorerTest api; + +fn Main() -> i32 { + // CHECK:STDERR: COMPILATION ERROR: fail_to_deduce_nested_array_size_in_tuple_no_expression_to_deduce_from.carbon:[[@LINE+1]]: cannot deduce size for [i32;] in x: (i32, [i32;]) + var x: (i32, [i32;]); + return x[0]; +} diff --git a/explorer/testdata/array/fail_to_deduce_size_from_int.carbon b/explorer/testdata/array/fail_to_deduce_size_from_int.carbon new file mode 100644 index 000000000000..2626c26dd741 --- /dev/null +++ b/explorer/testdata/array/fail_to_deduce_size_from_int.carbon @@ -0,0 +1,13 @@ +// 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 + +package ExplorerTest api; + +fn Main() -> i32 { + // CHECK:STDERR: COMPILATION ERROR: fail_to_deduce_size_from_int.carbon:[[@LINE+1]]: type pattern '[i32;]' does not match actual type 'i32' + var x: [i32;] = 42; + return x[0]; +} diff --git a/explorer/testdata/array/fail_to_deduce_size_no_expression_to_deduce_from.carbon b/explorer/testdata/array/fail_to_deduce_size_no_expression_to_deduce_from.carbon new file mode 100644 index 000000000000..9dff82336063 --- /dev/null +++ b/explorer/testdata/array/fail_to_deduce_size_no_expression_to_deduce_from.carbon @@ -0,0 +1,13 @@ +// 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 + +package ExplorerTest api; + +fn Main() -> i32 { + // CHECK:STDERR: COMPILATION ERROR: fail_to_deduce_size_no_expression_to_deduce_from.carbon:[[@LINE+1]]: cannot deduce size for x: [i32;] + var x: [i32;]; + return x[0]; +}