diff --git a/explorer/interpreter/resolve_names.cpp b/explorer/interpreter/resolve_names.cpp index e4aad27f9bd2..0e2c2e2ee709 100644 --- a/explorer/interpreter/resolve_names.cpp +++ b/explorer/interpreter/resolve_names.cpp @@ -320,19 +320,32 @@ auto NameResolver::ResolveNames(Expression& expression, CARBON_RETURN_IF_ERROR(ResolveNames(*field, enclosing_scope)); } break; - case ExpressionKind::StructLiteral: + case ExpressionKind::StructLiteral: { + std::set member_names; for (FieldInitializer& init : cast(expression).fields()) { CARBON_RETURN_IF_ERROR( ResolveNames(init.expression(), enclosing_scope)); + if (!member_names.insert(init.name()).second) { + return ProgramError(init.expression().source_loc()) + << "Duplicate name `" << init.name() << "` in struct literal"; + } } break; - case ExpressionKind::StructTypeLiteral: + } + case ExpressionKind::StructTypeLiteral: { + std::set member_names; for (FieldInitializer& init : cast(expression).fields()) { CARBON_RETURN_IF_ERROR( ResolveNames(init.expression(), enclosing_scope)); + if (!member_names.insert(init.name()).second) { + return ProgramError(init.expression().source_loc()) + << "Duplicate name `" << init.name() + << "` in struct type literal"; + } } break; + } case ExpressionKind::IdentifierExpression: { auto& identifier = cast(expression); CARBON_ASSIGN_OR_RETURN( diff --git a/explorer/testdata/struct/fail_struct_literal_duplicate_member.carbon b/explorer/testdata/struct/fail_struct_literal_duplicate_member.carbon new file mode 100644 index 000000000000..00d68caf137b --- /dev/null +++ b/explorer/testdata/struct/fail_struct_literal_duplicate_member.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/struct/fail_struct_literal_duplicate_member.carbon:[[@LINE+1]]: Duplicate name `x` in struct literal + var x: auto = {.x = 0, .x = 0}; + return 0; +} diff --git a/explorer/testdata/struct/fail_struct_type_literal_duplicate_member.carbon b/explorer/testdata/struct/fail_struct_type_literal_duplicate_member.carbon new file mode 100644 index 000000000000..c4d105204ec5 --- /dev/null +++ b/explorer/testdata/struct/fail_struct_type_literal_duplicate_member.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/struct/fail_struct_type_literal_duplicate_member.carbon:[[@LINE+1]]: Duplicate name `x` in struct type literal + var y: {.x: i32, .x: i32}; + return 0; +}