From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by sourceware.org (Postfix) with ESMTPS id AE8C43857434 for ; Tue, 30 Jan 2024 12:12:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org AE8C43857434 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=embecosm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org AE8C43857434 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::435 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706616781; cv=none; b=iQpF1Jyica0M8xvEHkrCYV6rtaOkN4LRkTzQ92zQQ7hRwnoyJ1ehsnKU/QJPuIh98UROokhue12NzxzxUlYgyhW/191H3LfXg+CUvTI8da9Oy3gbuZwwC6aE3//TKS4z6Nc0gaT6WHoTjopLvwd+PwFX6rtDykoQpEyUQfoYDGw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706616781; c=relaxed/simple; bh=RzmgAQKgltTr23Dl3fY6lYrdyCZmq54zIkyGctm19yM=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=wYpAxOFfBE1/eHnE9F14NLKVVa5WBopvBpML8YeOJ4Z2wIEG3Tk0+WKeOpWLsJYvDPqauCSYjgTCIaiAugy4bEYJv9220MTyHP463KSQsd93g4aHCXsOKmjc9JnnovvlTmAId3qZsRTElbsvzkfi7sTcUsZ8W+GErIpLbHvIq9E= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-wr1-x435.google.com with SMTP id ffacd0b85a97d-33ae7681d03so1637705f8f.1 for ; Tue, 30 Jan 2024 04:12:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; t=1706616719; x=1707221519; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to; bh=FnzcZnqzwBWuKXiP4x5Vhxld3d3kFDfelIyKnfZd6B8=; b=J+bTFMgEHlXXiWjX7shXRmbYul5x9lF+U/rFMJ8iBUEAvT2dLTCMYngTRdxaEYq4RX 5SlqJi8prf6M1HbtcxTKyZDkIjJg69ACKgZLy90OJDyzj4MZM68mbVvywpQGOEr42Vo9 81/W2JRkLXNjSsOPiVnGCJcc8gD9C1b/FTP033GEYhUZje2Rccv9d5FfVO1G6CAttjyC i6yeDKq4aVOOUEGRgHmRz2iRwEzEjmC+0g6oEp6AiQfdSGqOo1jcCOYqNeultwz6odpb ARACm8NaWIIiXjznuQNdWUe5y6wt8ZmWb8Irx7ggYzGoKisUBbNpHuSJFa/dyc6C5BIz efIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706616719; x=1707221519; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=FnzcZnqzwBWuKXiP4x5Vhxld3d3kFDfelIyKnfZd6B8=; b=Y7azN/lKtcULS3BRPs8Exm2GlbTw3agzzgpCIvFlVON0dSEjM3tU8Dc1lCtqlZup6P uXWUaVnGfSyeMAEBIGMs9u/c4vBYI/Y+N0jTpSSKh3pqpi/Tjz/K+X5mkkEk9SiO4j3X 8+ewGMVsGvBb1t5aA/oQ6NFmG4js/Ht4Bz90/QDE1OfbiPGzZmF8aOVsH3N8QEd0fz6J l688vH9iZAPL7H4dKlpezXQJg8ZHbVb/o5obj4Mnhq7NJbyRO+dUHTGJ/Gqf0l6+ICn+ +MWfM55TbSZfF/cBfrf5dZanjDg+Mrqzldcv6XrlLfrBa3sJneb3E4g/PPrhxZyU8W3b FhSQ== X-Gm-Message-State: AOJu0YxG743S0tktY3HP96o4W7UnzeWY3ZZaHxeC351Ge6Ivtz0qn8Df 4QI/9WbUGb5WIPvK4pKRnxK8iJqc4igvc7zgmJW1Nux6/4ePLUeD7D4YCKA36g== X-Google-Smtp-Source: AGHT+IEKgkAb+coDxrGoaIs3Z0ISYEgDxYRXhe/oITBJYLnEdQmVDr8HKlNKdiYDyCw4nlYyu5vOrg== X-Received: by 2002:adf:a446:0:b0:33a:e6f2:4a48 with SMTP id e6-20020adfa446000000b0033ae6f24a48mr5956172wra.64.1706616719544; Tue, 30 Jan 2024 04:11:59 -0800 (PST) Received: from platypus.localdomain ([62.23.166.218]) by smtp.gmail.com with ESMTPSA id f9-20020a056000036900b00339307d9d31sm10569894wrf.112.2024.01.30.04.11.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 04:11:59 -0800 (PST) From: arthur.cohen@embecosm.com To: gcc-patches@gcc.gnu.org Cc: gcc-rust@gcc.gnu.org, Robert Goss Subject: [COMMITTED 099/101] gccrs: Add improved error when no fields in initializer Date: Tue, 30 Jan 2024 13:07:55 +0100 Message-ID: <20240130121026.807464-102-arthur.cohen@embecosm.com> X-Mailer: git-send-email 2.42.1 In-Reply-To: <20240130121026.807464-2-arthur.cohen@embecosm.com> References: <20240130121026.807464-2-arthur.cohen@embecosm.com> Reply-To: arthur.cohen@embecosm.com MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-14.2 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: From: Robert Goss If a struct type with a variant that has fields is initialized with some fields the expression HIR StructExprStructFields is checked that all the fields are assigned. However, if no fields are initialized the HIR StructExprStruct is generated. This doesn't check if the struct is a unit during typechekc and only fails at the compile stage with a ICE. Add a check at the typecheck stage that makes sure the struct does not have a variant with fields and give an error message based on the rustc one. We have also updated the message given in the case where one field was present to list the missing fields and match more closely the new message. gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit) Add additional check * typecheck/rust-hir-type-check-struct-field.h: A helper method to make error added * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::resolve) Update message gcc/testsuite/ChangeLog: * rust/compile/missing_constructor_fields.rs: Added case with no initializers Signed-off-by: Robert Goss --- .../typecheck/rust-hir-type-check-expr.cc | 18 +++++++ .../rust-hir-type-check-struct-field.h | 9 ++++ .../typecheck/rust-hir-type-check-struct.cc | 48 +++++++++++++++++-- .../compile/missing_constructor_fields.rs | 6 ++- 4 files changed, 76 insertions(+), 5 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 030e5f1b63c..43d183f7a59 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -1017,6 +1017,24 @@ TypeCheckExpr::visit (HIR::StructExprStruct &struct_expr) return; } + TyTy::ADTType *adt = static_cast (struct_path_ty); + for (auto variant : adt->get_variants ()) + { + if (!variant->get_fields ().empty ()) + { + std::vector field_names; + for (auto &field : variant->get_fields ()) + field_names.push_back (field->get_name ()); + Error missing_fields_error + = TypeCheckStructExpr::make_missing_field_error ( + struct_expr.get_locus (), field_names, + struct_path_ty->get_name ()); + // We might want to return or handle these in the future emit for now. + missing_fields_error.emit (); + return; + } + } + infered = struct_path_ty; } diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h index 31d2896d0bb..792eebf3ff5 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h +++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h @@ -25,6 +25,9 @@ #include "rust-tyty.h" namespace Rust { + +struct Error; + namespace Resolver { class TypeCheckStructExpr : public TypeCheckBase @@ -32,6 +35,12 @@ class TypeCheckStructExpr : public TypeCheckBase public: static TyTy::BaseType *Resolve (HIR::StructExprStructFields *expr); + // Helper for making any errors + static Error + make_missing_field_error (location_t locus, + const std::vector &missing_field_names, + const std::string &struct_name); + protected: void resolve (HIR::StructExprStructFields &struct_expr); diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc index 56aa3d869a4..d2977ac8ea8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc @@ -142,7 +142,16 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) } // check the arguments are all assigned and fix up the ordering - if (fields_assigned.size () != variant->num_fields ()) + std::vector missing_field_names; + for (auto &field : variant->get_fields ()) + { + auto it = fields_assigned.find (field->get_name ()); + if (it == fields_assigned.end ()) + { + missing_field_names.push_back (field->get_name ()); + } + } + if (!missing_field_names.empty ()) { if (struct_def->is_union ()) { @@ -156,8 +165,12 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) } else if (!struct_expr.has_struct_base ()) { - rust_error_at (struct_expr.get_locus (), ErrorCode::E0063, - "constructor is missing fields"); + Error missing_fields_error + = make_missing_field_error (struct_expr.get_locus (), + missing_field_names, + struct_path_ty->get_name ()); + // We might want to return or handle these in the future emit for now. + missing_fields_error.emit (); return; } else @@ -392,5 +405,34 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) return true; } +Error +TypeCheckStructExpr::make_missing_field_error ( + location_t locus, const std::vector &missing_field_names, + const std::string &struct_name) +{ + // Message plurality depends on size + if (missing_field_names.size () == 1) + { + return Error (locus, ErrorCode::E0063, + "missing field %s in initializer of %qs", + missing_field_names[0].c_str (), struct_name.c_str ()); + } + // Make comma separated string for display + std::stringstream display_field_names; + bool first = true; + for (auto &name : missing_field_names) + { + if (!first) + { + display_field_names << ", "; + } + first = false; + display_field_names << name; + } + return Error (locus, ErrorCode::E0063, + "missing fields %s in initializer of %qs", + display_field_names.str ().c_str (), struct_name.c_str ()); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/testsuite/rust/compile/missing_constructor_fields.rs b/gcc/testsuite/rust/compile/missing_constructor_fields.rs index 9d492101fbd..6e3965b5687 100644 --- a/gcc/testsuite/rust/compile/missing_constructor_fields.rs +++ b/gcc/testsuite/rust/compile/missing_constructor_fields.rs @@ -6,5 +6,7 @@ struct Foo { } fn main() { - let x = Foo { x: 0 , y:1 }; // { dg-error "constructor is missing fields" } -} \ No newline at end of file + let z = Foo { x: 0 , y:1 }; // { dg-error "missing field z in initializer of 'Foo'" } + let xz = Foo { y:1 }; // { dg-error "missing fields x, z in initializer of 'Foo'" } + let xyz = Foo { }; // { dg-error "missing fields x, y, z in initializer of 'Foo'" } +} -- 2.42.1