From patchwork Tue Feb 21 12:01:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arthur Cohen X-Patchwork-Id: 60033 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp1839475wrn; Tue, 21 Feb 2023 04:43:15 -0800 (PST) X-Google-Smtp-Source: AK7set+9+egUjj0VPbZsvRya/HvAPpLiSNaTHjT9Fo4nVAqe66eYYT5pHrCDbQCQw1I3iI2fgo9y X-Received: by 2002:a50:ee01:0:b0:4ae:eb0f:892e with SMTP id g1-20020a50ee01000000b004aeeb0f892emr4473625eds.20.1676983395135; Tue, 21 Feb 2023 04:43:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1676983395; cv=none; d=google.com; s=arc-20160816; b=UPKwyqaGIPA0eZPIkjSgjLybbVYdXSLtuGtYAZw4YsPfuckoPL7394UWXzvgeRPAdg XE4hiufdXkwk2eobPrKN222yUrA8HbbUak7rVx4/t8tV/N6WgWpkkH/1dLAKPkvTDtJG wIrup0Kqho3Dw7TyCN3cjnhi99Rybpnvt+NzEfYadgCgxavrUu0gzrTI5ol9LPY+7QoX C835gid+dSK5MW3/qOkZtgBSrAapiPPhNi1oc+4l6i5C4NvHNE44VZWmFwBQWI0cA77A b57AWSiJk7SkzoKxKzpkrGozW7+Vz4StA4/hCVQWIgf723Dlqy/eppmQr+0XqAn3Pekv v22A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:dmarc-filter :delivered-to; bh=zRJlYgzUbLxQ9JVJ2IG7Wwl33z76X7RQGKYZNW1AbvI=; b=MwoQ9fCfF/Uyw1YtZxN1mTQwit2rHTueCWbdMgvyqNUdnWq/q17SRWi3rYIqtsOaVV j+hFHN1KXMKpbde502IPs3UrTMaxPZVw6subYMD1ZnzVnMA51gXZEoV/8WBjfn3pGg1i Mn6KpB+Ex2OrcWjaeKf6m68oppJ/Qlo2GIIg3jryjOXJxev5gjyJkCPS8TewcQyRZgYA HD+okY4EylFMIV1SL0cGUnhqvAt77rtviCuNuFp15saQNLqfcb01blKudaMx0/3lhg2u //2VSbt1g/cmREa7ekxQpORPZgcFvDMCzdzDKKaHGOAhzth8jzncLsZp9UN0jG7aLoXu EKjg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@embecosm.com header.s=google header.b=J9KopAI4; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org" Received: from sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id h17-20020a50ed91000000b004acbbafc603si18544371edr.335.2023.02.21.04.43.14 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Feb 2023 04:43:15 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@embecosm.com header.s=google header.b=J9KopAI4; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org" Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A43B838F7BE9 for ; Tue, 21 Feb 2023 12:14:41 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by sourceware.org (Postfix) with ESMTPS id 65447385B536 for ; Tue, 21 Feb 2023 12:04:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 65447385B536 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=embecosm.com Received: by mail-wr1-x42c.google.com with SMTP id r7so3991894wrz.6 for ; Tue, 21 Feb 2023 04:04:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; 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=zRJlYgzUbLxQ9JVJ2IG7Wwl33z76X7RQGKYZNW1AbvI=; b=J9KopAI4Mfn5MjA0tgrD1ju2OpglW+XXJXbaOahQAC6NnWWwOzBFj/9JU2UAkSS0ay dVRc1WKn3suKbEYwKRcRo1uW/aO3fg5Ny4wl3bxyrF8XSfknVXDpDEjwmBDotmp+aUkK KVXMqJB0fWV55G02h67t/ZG2930Xta6ukjL7II9rroDtqnrzxJ+bXTjpxNS61zQTXiF5 Vo7Jsc3LhjGFeD3wkrohQWOSuKGCd3lGmSOF8RpC079d1yMp0+Yq7GEuwqcuF9hJUIQZ gkaksxM38YwVCSGMhcHItIqT38u7ShoigJvRkDfPeda24lBgth7hgFiQafhLjglFK55l ueRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=zRJlYgzUbLxQ9JVJ2IG7Wwl33z76X7RQGKYZNW1AbvI=; b=zBVIyFWfr5xf8yTM2Ljw2Ceq9y7LggNBJSo5qexMjhi7/KZ4ATknfxqrYS+0dkDC18 24jPQzVw9xA5MCsKaWomQDT8Nlgkqq7tW1lg13tcENxyqaMHW0tgLtMxWArBH6NclD9U CCB3zMLLBl37mzUEliMTGQTMoFmLcO8CCCJmBM498jDsUqLBT5yijvJmnf2InDvmJ82T BubYI+4XXK/65sRlOiScDZtGihAclvmHMQL9sy7gx1tbrv7jkdobya24X1Tv30+5LnJh SJ/owa48+5MjsVAx9Cp3h1HmmPkAkWltYpgVU4FP8Vc+huPMgZrYy48iQM3yPpgx5HB2 tgGA== X-Gm-Message-State: AO0yUKUgmnbA1d2UdeK119mpyOgvH/uA5aF1E+jHnqLC3Iw/0WQQqBWP uOH1uSDJIxLcozWumbKP46FpPpnMszVcgLgLIA== X-Received: by 2002:a5d:4ccf:0:b0:2c6:5972:cd13 with SMTP id c15-20020a5d4ccf000000b002c65972cd13mr4761569wrt.26.1676981043543; Tue, 21 Feb 2023 04:04:03 -0800 (PST) Received: from platypus.localdomain ([62.23.166.218]) by smtp.gmail.com with ESMTPSA id c15-20020adffb4f000000b002c55b0e6ef1sm5013811wrs.4.2023.02.21.04.04.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Feb 2023 04:04:03 -0800 (PST) From: arthur.cohen@embecosm.com To: gcc-patches@gcc.gnu.org Cc: gcc-rust@gcc.gnu.org, Philip Herron Subject: [committed 049/103] gccrs: Initial Type resolution for closures Date: Tue, 21 Feb 2023 13:01:39 +0100 Message-Id: <20230221120230.596966-50-arthur.cohen@embecosm.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20230221120230.596966-1-arthur.cohen@embecosm.com> References: <20230221120230.596966-1-arthur.cohen@embecosm.com> MIME-Version: 1.0 X-Spam-Status: No, score=-14.9 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 autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: arthur.cohen@embecosm.com Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1758444540451696021?= X-GMAIL-MSGID: =?utf-8?q?1758444540451696021?= From: Philip Herron gcc/rust/ChangeLog: * hir/tree/rust-hir-expr.h: Add `get_params` method. * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Typecheck closure nodes. (TypeCheckExpr::resolve_fn_trait_call): New function. * typecheck/rust-hir-type-check-expr.h: Declare `resolve_fn_trait_call` and `resolve_possible_fn_trait_call_method_name`. * typecheck/rust-hir-type-check.h: Declare `get_context_type`. * typecheck/rust-tyctx.cc (TypeCheckContextItem::get_context_type): New function. * typecheck/rust-tyty-cmp.h: Visit closures properly. * typecheck/rust-tyty-rules.h: Likewise. * typecheck/rust-tyty.cc (BaseType::bounds_compatible): Add commented out assertin. (ClosureType::as_string): Implement it. (ClosureType::clone): Fix closure cloning. (ClosureType::setup_fn_once_output): New function. * typecheck/rust-tyty.h: Improve `ClosureType` class and declare `setup_fn_once_output`. --- gcc/rust/hir/tree/rust-hir-expr.h | 2 + .../typecheck/rust-hir-type-check-expr.cc | 308 +++++++++++++++++- gcc/rust/typecheck/rust-hir-type-check-expr.h | 7 + gcc/rust/typecheck/rust-hir-type-check.h | 2 + gcc/rust/typecheck/rust-tyctx.cc | 32 ++ gcc/rust/typecheck/rust-tyty-cmp.h | 23 ++ gcc/rust/typecheck/rust-tyty-rules.h | 40 ++- gcc/rust/typecheck/rust-tyty.cc | 58 +++- gcc/rust/typecheck/rust-tyty.h | 38 ++- 9 files changed, 479 insertions(+), 31 deletions(-) diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 4c5caf17ac3..227bacbe641 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -2131,6 +2131,8 @@ public: }; std::unique_ptr &get_expr () { return expr; } + std::vector &get_params () { return params; } + void accept_vis (HIRFullVisitor &vis) override; void accept_vis (HIRExpressionVisitor &vis) override; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 9140b8b1305..85590630378 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -178,16 +178,6 @@ TypeCheckExpr::visit (HIR::CallExpr &expr) { TyTy::BaseType *function_tyty = TypeCheckExpr::Resolve (expr.get_fnexpr ()); - bool valid_tyty = function_tyty->get_kind () == TyTy::TypeKind::ADT - || function_tyty->get_kind () == TyTy::TypeKind::FNDEF - || function_tyty->get_kind () == TyTy::TypeKind::FNPTR; - if (!valid_tyty) - { - rust_error_at (expr.get_locus (), - "Failed to resolve expression of function call"); - return; - } - rust_debug_loc (expr.get_locus (), "resolved_call_expr to: {%s}", function_tyty->get_name ().c_str ()); @@ -214,6 +204,24 @@ TypeCheckExpr::visit (HIR::CallExpr &expr) rust_assert (adt->number_of_variants () == 1); variant = *adt->get_variants ().at (0); } + + infered + = TyTy::TypeCheckCallExpr::go (function_tyty, expr, variant, context); + return; + } + + bool resolved_fn_trait_call + = resolve_fn_trait_call (expr, function_tyty, &infered); + if (resolved_fn_trait_call) + return; + + bool valid_tyty = function_tyty->get_kind () == TyTy::TypeKind::FNDEF + || function_tyty->get_kind () == TyTy::TypeKind::FNPTR; + if (!valid_tyty) + { + rust_error_at (expr.get_locus (), + "Failed to resolve expression of function call"); + return; } infered = TyTy::TypeCheckCallExpr::go (function_tyty, expr, variant, context); @@ -1422,7 +1430,123 @@ TypeCheckExpr::visit (HIR::MatchExpr &expr) void TypeCheckExpr::visit (HIR::ClosureExpr &expr) { - gcc_unreachable (); + TypeCheckContextItem ¤t_context = context->peek_context (); + TyTy::FnType *current_context_fndecl = current_context.get_context_type (); + + HirId ref = expr.get_mappings ().get_hirid (); + DefId id = expr.get_mappings ().get_defid (); + RustIdent ident{current_context_fndecl->get_ident ().path, expr.get_locus ()}; + + // get from parent context + std::vector subst_refs + = current_context_fndecl->clone_substs (); + + std::vector parameter_types; + for (auto &p : expr.get_params ()) + { + if (p.has_type_given ()) + { + TyTy::BaseType *param_tyty + = TypeCheckType::Resolve (p.get_type ().get ()); + TyTy::TyVar param_ty (param_tyty->get_ref ()); + parameter_types.push_back (param_ty); + + TypeCheckPattern::Resolve (p.get_pattern ().get (), + param_ty.get_tyty ()); + } + else + { + TyTy::TyVar param_ty + = TyTy::TyVar::get_implicit_infer_var (p.get_locus ()); + parameter_types.push_back (param_ty); + + TypeCheckPattern::Resolve (p.get_pattern ().get (), + param_ty.get_tyty ()); + } + } + + // we generate an implicit hirid for the closure args + HirId implicit_args_id = mappings->get_next_hir_id (); + TyTy::TupleType *closure_args + = new TyTy::TupleType (implicit_args_id, expr.get_locus (), + parameter_types); + context->insert_implicit_type (closure_args); + + Location result_type_locus = expr.has_return_type () + ? expr.get_return_type ()->get_locus () + : expr.get_locus (); + TyTy::TyVar result_type + = expr.has_return_type () + ? TyTy::TyVar ( + TypeCheckType::Resolve (expr.get_return_type ().get ())->get_ref ()) + : TyTy::TyVar::get_implicit_infer_var (expr.get_locus ()); + + // resolve the block + Location closure_expr_locus = expr.get_expr ()->get_locus (); + TyTy::BaseType *closure_expr_ty + = TypeCheckExpr::Resolve (expr.get_expr ().get ()); + coercion_site (expr.get_mappings ().get_hirid (), + TyTy::TyWithLocation (result_type.get_tyty (), + result_type_locus), + TyTy::TyWithLocation (closure_expr_ty, closure_expr_locus), + expr.get_locus ()); + + // generate the closure type + infered = new TyTy::ClosureType (ref, id, ident, closure_args, result_type, + subst_refs); + + // FIXME + // all closures automatically inherit the appropriate fn trait. Lets just + // assume FnOnce for now. I think this is based on the return type of the + // closure + + Analysis::RustLangItem::ItemType lang_item_type + = Analysis::RustLangItem::ItemType::FN_ONCE; + DefId respective_lang_item_id = UNKNOWN_DEFID; + bool lang_item_defined + = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id); + if (!lang_item_defined) + { + // FIXME + // we need to have a unified way or error'ing when we are missing lang + // items that is useful + rust_fatal_error ( + expr.get_locus (), "unable to find lang item: %<%s%>", + Analysis::RustLangItem::ToString (lang_item_type).c_str ()); + } + rust_assert (lang_item_defined); + + // these lang items are always traits + HIR::Item *item = mappings->lookup_defid (respective_lang_item_id); + rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait); + HIR::Trait *trait_item = static_cast (item); + + TraitReference *trait = TraitResolver::Resolve (*trait_item); + rust_assert (!trait->is_error ()); + + TyTy::TypeBoundPredicate predicate (*trait, expr.get_locus ()); + + // resolve the trait bound where the <(Args)> are the parameter tuple type + HIR::GenericArgs args = HIR::GenericArgs::create_empty (expr.get_locus ()); + + // lets generate an implicit Type so that it resolves to the implict tuple + // type we have created + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_mappings ().get_nodeid (), + implicit_args_id, UNKNOWN_LOCAL_DEFID); + HIR::TupleType *implicit_tuple + = new HIR::TupleType (mapping, + {} // we dont need to fill this out because it will + // auto resolve because the hir id's match + , + expr.get_locus ()); + args.get_type_args ().push_back (std::unique_ptr (implicit_tuple)); + + // apply the arguments + predicate.apply_generic_arguments (&args); + + // finally inherit the trait bound + infered->inherit_bounds ({predicate}); } bool @@ -1630,6 +1754,168 @@ TypeCheckExpr::resolve_operator_overload ( return true; } +HIR::PathIdentSegment +TypeCheckExpr::resolve_possible_fn_trait_call_method_name ( + const TyTy::BaseType &receiver) +{ + // Question + // do we need to probe possible bounds here? I think not, i think when we + // support Fn traits they are explicitly specified + + // FIXME + // the logic to map the FnTrait to their respective call trait-item is + // duplicated over in the backend/rust-compile-expr.cc + for (const auto &bound : receiver.get_specified_bounds ()) + { + bool found_fn = bound.get_name ().compare ("Fn") == 0; + bool found_fn_mut = bound.get_name ().compare ("FnMut") == 0; + bool found_fn_once = bound.get_name ().compare ("FnOnce") == 0; + + if (found_fn) + { + return HIR::PathIdentSegment ("call"); + } + else if (found_fn_mut) + { + return HIR::PathIdentSegment ("call_mut"); + } + else if (found_fn_once) + { + return HIR::PathIdentSegment ("call_once"); + } + } + + // nothing + return HIR::PathIdentSegment (""); +} + +bool +TypeCheckExpr::resolve_fn_trait_call (HIR::CallExpr &expr, + TyTy::BaseType *receiver_tyty, + TyTy::BaseType **result) +{ + // we turn this into a method call expr + HIR::PathIdentSegment method_name + = resolve_possible_fn_trait_call_method_name (*receiver_tyty); + if (method_name.is_error ()) + return false; + + auto candidates = MethodResolver::Probe (receiver_tyty, method_name); + if (candidates.empty ()) + return false; + + if (candidates.size () > 1) + { + RichLocation r (expr.get_locus ()); + for (auto &c : candidates) + r.add_range (c.candidate.locus); + + rust_error_at ( + r, "multiple candidates found for function trait method call %<%s%>", + method_name.as_string ().c_str ()); + return false; + } + + if (receiver_tyty->get_kind () == TyTy::TypeKind::CLOSURE) + { + const TyTy::ClosureType &closure + = static_cast (*receiver_tyty); + closure.setup_fn_once_output (); + } + + auto candidate = *candidates.begin (); + rust_debug_loc (expr.get_locus (), + "resolved call-expr to fn trait: {%u} {%s}", + candidate.candidate.ty->get_ref (), + candidate.candidate.ty->debug_str ().c_str ()); + + // Get the adjusted self + Adjuster adj (receiver_tyty); + TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments); + + // store the adjustments for code-generation to know what to do which must be + // stored onto the receiver to so as we don't trigger duplicate deref mappings + // ICE when an argument is a method call + HirId autoderef_mappings_id = expr.get_mappings ().get_hirid (); + context->insert_autoderef_mappings (autoderef_mappings_id, + std::move (candidate.adjustments)); + context->insert_receiver (expr.get_mappings ().get_hirid (), receiver_tyty); + + PathProbeCandidate &resolved_candidate = candidate.candidate; + TyTy::BaseType *lookup_tyty = candidate.candidate.ty; + NodeId resolved_node_id + = resolved_candidate.is_impl_candidate () + ? resolved_candidate.item.impl.impl_item->get_impl_mappings () + .get_nodeid () + : resolved_candidate.item.trait.item_ref->get_mappings ().get_nodeid (); + + if (lookup_tyty->get_kind () != TyTy::TypeKind::FNDEF) + { + RichLocation r (expr.get_locus ()); + r.add_range (resolved_candidate.locus); + rust_error_at (r, "associated impl item is not a method"); + return false; + } + + TyTy::BaseType *lookup = lookup_tyty; + TyTy::FnType *fn = static_cast (lookup); + if (!fn->is_method ()) + { + RichLocation r (expr.get_locus ()); + r.add_range (resolved_candidate.locus); + rust_error_at (r, "associated function is not a method"); + return false; + } + + // fn traits only support tuple argument passing so we need to implicitly set + // this up to get the same type checking we get in the rest of the pipeline + + std::vector call_args; + for (auto &arg : expr.get_arguments ()) + { + TyTy::BaseType *a = TypeCheckExpr::Resolve (arg.get ()); + call_args.push_back (TyTy::TyVar (a->get_ref ())); + } + + // crate implicit tuple + HirId implicit_arg_id = mappings->get_next_hir_id (); + Analysis::NodeMapping mapping (mappings->get_current_crate (), UNKNOWN_NODEID, + implicit_arg_id, UNKNOWN_LOCAL_DEFID); + + TyTy::TupleType *tuple + = new TyTy::TupleType (implicit_arg_id, expr.get_locus (), call_args); + context->insert_implicit_type (implicit_arg_id, tuple); + + std::vector args; + TyTy::Argument a (mapping, tuple, + expr.get_locus () /*FIXME is there a better location*/); + args.push_back (std::move (a)); + + TyTy::BaseType *function_ret_tyty + = TyTy::TypeCheckMethodCallExpr::go (fn, expr.get_mappings (), args, + expr.get_locus (), expr.get_locus (), + adjusted_self, context); + if (function_ret_tyty == nullptr + || function_ret_tyty->get_kind () == TyTy::TypeKind::ERROR) + { + rust_error_at (expr.get_locus (), + "failed check fn trait call-expr MethodCallExpr"); + return false; + } + + // store the expected fntype + context->insert_operator_overload (expr.get_mappings ().get_hirid (), fn); + + // set up the resolved name on the path + resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (), + resolved_node_id); + + // return the result of the function back + *result = function_ret_tyty; + + return true; +} + bool TypeCheckExpr::validate_arithmetic_type ( const TyTy::BaseType *tyty, HIR::ArithmeticOrLogicalExpr::ExprType expr_type) diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 7f787fa9766..d800549dea2 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -103,6 +103,13 @@ protected: HIR::OperatorExprMeta expr, TyTy::BaseType *lhs, TyTy::BaseType *rhs); + bool resolve_fn_trait_call (HIR::CallExpr &expr, + TyTy::BaseType *function_tyty, + TyTy::BaseType **result); + + HIR::PathIdentSegment + resolve_possible_fn_trait_call_method_name (const TyTy::BaseType &receiver); + private: TypeCheckExpr (); diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index 2b47c6738b5..adec2f91961 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -70,6 +70,8 @@ public: return item.trait_item; } + TyTy::FnType *get_context_type (); + private: union Item { diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc index a0b5c5e849e..886842b0623 100644 --- a/gcc/rust/typecheck/rust-tyctx.cc +++ b/gcc/rust/typecheck/rust-tyctx.cc @@ -154,5 +154,37 @@ TypeCheckContext::peek_context () return return_type_stack.back ().first; } +// TypeCheckContextItem + +TyTy::FnType * +TypeCheckContextItem::get_context_type () +{ + auto &context = *TypeCheckContext::get (); + + HirId reference = UNKNOWN_HIRID; + switch (get_type ()) + { + case ITEM: + reference = get_item ()->get_mappings ().get_hirid (); + break; + + case IMPL_ITEM: + reference = get_impl_item ().second->get_mappings ().get_hirid (); + break; + + case TRAIT_ITEM: + reference = get_trait_item ()->get_mappings ().get_hirid (); + break; + } + + rust_assert (reference != UNKNOWN_HIRID); + + TyTy::BaseType *lookup = nullptr; + bool ok = context.lookup_type (reference, &lookup); + rust_assert (ok); + rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF); + return static_cast (lookup); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h index 5dfd2d7184a..293c8bfa641 100644 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ b/gcc/rust/typecheck/rust-tyty-cmp.h @@ -871,6 +871,29 @@ public: ok = true; } + void visit (const ClosureType &type) override + { + if (base->get_def_id () != type.get_def_id ()) + { + BaseCmp::visit (type); + return; + } + + if (!base->get_parameters ().can_eq (&type.get_parameters (), false)) + { + BaseCmp::visit (type); + return; + } + + if (!base->get_result_type ().can_eq (&type.get_result_type (), false)) + { + BaseCmp::visit (type); + return; + } + + ok = true; + } + private: const BaseType *get_base () const override { return base; } const ClosureType *base; diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 7ffffc1dd59..4b1fe4fd418 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -624,7 +624,45 @@ class ClosureRules : public BaseRules public: ClosureRules (ClosureType *base) : BaseRules (base), base (base) {} - // TODO + void visit (InferType &type) override + { + if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) + { + BaseRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); + } + + void visit (ClosureType &type) override + { + if (base->get_def_id () != type.get_def_id ()) + { + BaseRules::visit (type); + return; + } + + TyTy::BaseType *args_res + = base->get_parameters ().unify (&type.get_parameters ()); + if (args_res == nullptr || args_res->get_kind () == TypeKind::ERROR) + { + BaseRules::visit (type); + return; + } + + TyTy::BaseType *res + = base->get_result_type ().unify (&type.get_result_type ()); + if (res == nullptr || res->get_kind () == TypeKind::ERROR) + { + BaseRules::visit (type); + return; + } + + resolved = base->clone (); + resolved->set_ref (type.get_ref ()); + } private: BaseType *get_base () override { return base; } diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 462c5bf91fd..0d96c0f04fd 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -27,6 +27,7 @@ #include "rust-substitution-mapper.h" #include "rust-hir-trait-ref.h" #include "rust-hir-type-bounds.h" +#include "rust-hir-trait-resolve.h" #include "options.h" namespace Rust { @@ -200,6 +201,7 @@ BaseType::bounds_compatible (const BaseType &other, Location locus, rust_error_at (r, "bounds not satisfied for %s %<%s%> is not satisfied", other.get_name ().c_str (), missing_preds.c_str ()); + // rust_assert (!emit_error); } } @@ -1672,7 +1674,9 @@ ClosureType::accept_vis (TyConstVisitor &vis) const std::string ClosureType::as_string () const { - return "TODO"; + std::string params_buf = parameters->as_string (); + return "|" + params_buf + "| {" + result_type.get_tyty ()->as_string () + + "} {" + raw_bounds_as_string () + "}"; } BaseType * @@ -1699,8 +1703,10 @@ ClosureType::is_equal (const BaseType &other) const BaseType * ClosureType::clone () const { - return new ClosureType (get_ref (), get_ty_ref (), ident, id, parameter_types, - result_type, clone_substs (), get_combined_refs ()); + return new ClosureType (get_ref (), get_ty_ref (), ident, id, + (TyTy::TupleType *) parameters->clone (), result_type, + clone_substs (), get_combined_refs (), + specified_bounds); } BaseType * @@ -1716,6 +1722,52 @@ ClosureType::handle_substitions (SubstitutionArgumentMappings mappings) return nullptr; } +void +ClosureType::setup_fn_once_output () const +{ + // lookup the lang items + auto fn_once_lang_item = Analysis::RustLangItem::ItemType::FN_ONCE; + auto fn_once_output_lang_item + = Analysis::RustLangItem::ItemType::FN_ONCE_OUTPUT; + + DefId trait_id = UNKNOWN_DEFID; + bool trait_lang_item_defined + = mappings->lookup_lang_item (fn_once_lang_item, &trait_id); + rust_assert (trait_lang_item_defined); + + DefId trait_item_id = UNKNOWN_DEFID; + bool trait_item_lang_item_defined + = mappings->lookup_lang_item (fn_once_output_lang_item, &trait_item_id); + rust_assert (trait_item_lang_item_defined); + + // resolve to the trait + HIR::Item *item = mappings->lookup_defid (trait_id); + rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait); + HIR::Trait *trait = static_cast (item); + + Resolver::TraitReference *trait_ref + = Resolver::TraitResolver::Resolve (*trait); + rust_assert (!trait_ref->is_error ()); + + // resolve to trait item + HIR::TraitItem *trait_item + = mappings->lookup_trait_item_defid (trait_item_id); + rust_assert (trait_item != nullptr); + rust_assert (trait_item->get_item_kind () + == HIR::TraitItem::TraitItemKind::TYPE); + std::string item_identifier = trait_item->trait_identifier (); + + // setup associated types #[lang = "fn_once_output"] + Resolver::TraitItemReference *item_reference = nullptr; + bool found = trait_ref->lookup_trait_item_by_type ( + item_identifier, Resolver::TraitItemReference::TraitItemType::TYPE, + &item_reference); + rust_assert (found); + + // setup + item_reference->associated_type_set (&get_result_type ()); +} + void ArrayType::accept_vis (TyVisitor &vis) { diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index b17f01f67ea..5eaec352567 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -1626,31 +1626,35 @@ class ClosureType : public BaseType, public SubstitutionRef { public: ClosureType (HirId ref, DefId id, RustIdent ident, - std::vector parameter_types, TyVar result_type, + TyTy::TupleType *parameters, TyVar result_type, std::vector subst_refs, - std::set refs = std::set ()) + std::set refs = std::set (), + std::vector specified_bounds + = std::vector ()) : BaseType (ref, ref, TypeKind::CLOSURE, ident, refs), SubstitutionRef (std::move (subst_refs), SubstitutionArgumentMappings::error ()), - parameter_types (std::move (parameter_types)), - result_type (std::move (result_type)), id (id) + parameters (parameters), result_type (std::move (result_type)), id (id) { LocalDefId local_def_id = id.localDefId; rust_assert (local_def_id != UNKNOWN_LOCAL_DEFID); + inherit_bounds (specified_bounds); } ClosureType (HirId ref, HirId ty_ref, RustIdent ident, DefId id, - std::vector parameter_types, TyVar result_type, + TyTy::TupleType *parameters, TyVar result_type, std::vector subst_refs, - std::set refs = std::set ()) + std::set refs = std::set (), + std::vector specified_bounds + = std::vector ()) : BaseType (ref, ty_ref, TypeKind::CLOSURE, ident, refs), SubstitutionRef (std::move (subst_refs), SubstitutionArgumentMappings::error ()), - parameter_types (std::move (parameter_types)), - result_type (std::move (result_type)), id (id) + parameters (parameters), result_type (std::move (result_type)), id (id) { LocalDefId local_def_id = id.localDefId; rust_assert (local_def_id != UNKNOWN_LOCAL_DEFID); + inherit_bounds (specified_bounds); } void accept_vis (TyVisitor &vis) override; @@ -1669,13 +1673,8 @@ public: bool is_concrete () const override final { - for (auto ¶m : parameter_types) - { - auto p = param.get_tyty (); - if (!p->is_concrete ()) - return false; - } - return result_type.get_tyty ()->is_concrete (); + return parameters->is_concrete () + && result_type.get_tyty ()->is_concrete (); } bool needs_generic_substitutions () const override final @@ -1693,8 +1692,15 @@ public: ClosureType * handle_substitions (SubstitutionArgumentMappings mappings) override final; + TyTy::TupleType &get_parameters () const { return *parameters; } + TyTy::BaseType &get_result_type () const { return *result_type.get_tyty (); } + + DefId get_def_id () const { return id; } + + void setup_fn_once_output () const; + private: - std::vector parameter_types; + TyTy::TupleType *parameters; TyVar result_type; DefId id; };