From bf724a30cc281528d993bd17d7c2d2c7c54d420a Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 12 Jan 2023 16:22:17 +0000 Subject: gccrs: Add another test case for passing associated type-bounds This demonstrates that this also works for custom algebraic data types too. gcc/testsuite/ChangeLog: * rust/execute/torture/issue-1720-2.rs: New test. Signed-off-by: Philip Herron --- gcc/testsuite/rust/execute/torture/issue-1720-2.rs | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 gcc/testsuite/rust/execute/torture/issue-1720-2.rs (limited to 'gcc') diff --git a/gcc/testsuite/rust/execute/torture/issue-1720-2.rs b/gcc/testsuite/rust/execute/torture/issue-1720-2.rs new file mode 100644 index 0000000..35833db --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/issue-1720-2.rs @@ -0,0 +1,30 @@ +mod core { + mod ops { + #[lang = "add"] + pub trait Add { + type Output; + + fn add(self, rhs: Rhs) -> Self::Output; + } + } +} + +struct Foo(i32); + +impl core::ops::Add for Foo { + type Output = i32; + + fn add(self, rhs: Foo) -> Self::Output { + self.0 + rhs.0 + } +} + +pub fn bar>(a: T) -> i32 { + a + a +} + +pub fn main() -> i32 { + let a = Foo(1); + + bar(a) - 2 +} -- cgit v1.1 From 8e9f9807f35aeb63a21fc49c0fa55a76a6d3107e Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 12 Jan 2023 16:40:30 +0000 Subject: gccrs: Move TypePredicateItem impl out of the header This moves the implementation code out of the header and into its respective cc file. Signed-off-by: Philip Herron gcc/rust/ChangeLog: * typecheck/rust-tyty-bounds.cc (TypeBoundPredicateItem::error): refactor (TypeBoundPredicateItem::is_error): likewise (TypeBoundPredicateItem::get_parent): likewise * typecheck/rust-tyty.h: Move the implementation for the above --- gcc/rust/typecheck/rust-tyty-bounds.cc | 24 ++++++++++++++++++++++++ gcc/rust/typecheck/rust-tyty.h | 16 ++++------------ 2 files changed, 28 insertions(+), 12 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index e5057c8..a307dd3 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -364,6 +364,30 @@ TypeBoundPredicate::lookup_associated_item (const std::string &search) const return TypeBoundPredicateItem (this, trait_item_ref); } +TypeBoundPredicateItem::TypeBoundPredicateItem ( + const TypeBoundPredicate *parent, + const Resolver::TraitItemReference *trait_item_ref) + : parent (parent), trait_item_ref (trait_item_ref) +{} + +TypeBoundPredicateItem +TypeBoundPredicateItem::error () +{ + return TypeBoundPredicateItem (nullptr, nullptr); +} + +bool +TypeBoundPredicateItem::is_error () const +{ + return parent == nullptr || trait_item_ref == nullptr; +} + +const TypeBoundPredicate * +TypeBoundPredicateItem::get_parent () const +{ + return parent; +} + TypeBoundPredicateItem TypeBoundPredicate::lookup_associated_item ( const Resolver::TraitItemReference *ref) const diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 4f333a8..365bf7d 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -82,19 +82,11 @@ class TypeBoundPredicateItem { public: TypeBoundPredicateItem (const TypeBoundPredicate *parent, - const Resolver::TraitItemReference *trait_item_ref) - : parent (parent), trait_item_ref (trait_item_ref) - {} + const Resolver::TraitItemReference *trait_item_ref); - static TypeBoundPredicateItem error () - { - return TypeBoundPredicateItem (nullptr, nullptr); - } + static TypeBoundPredicateItem error (); - bool is_error () const - { - return parent == nullptr || trait_item_ref == nullptr; - } + bool is_error () const; BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver); @@ -102,7 +94,7 @@ public: bool needs_implementation () const; - const TypeBoundPredicate *get_parent () const { return parent; } + const TypeBoundPredicate *get_parent () const; Location get_locus () const; -- cgit v1.1 From 1fbf184bb9221f91a8c921ab868d8e1e5d2b56c3 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 12 Jan 2023 18:00:52 +0000 Subject: gccrs: Refactor TyVar and TypeBoundPredicates This extract these helpers into seperate files Signed-off-by: Philip Herron gcc/rust/ChangeLog: * Make-lang.in: update makefile * typecheck/rust-tyty.cc (TyVar::TyVar): move to new file (TyVar::get_tyty): likewise (TyVar::get_implicit_infer_var): likewise (TyVar::subst_covariant_var): likewise (TyVar::clone): likewise (TyVar::monomorphized_clone): likewise (TyWithLocation::TyWithLocation): likewise * typecheck/rust-tyty.h (class BaseType): cleanup (class TypeBoundPredicate): move to its own file (class TypeBoundPredicateItem): likewise (class TypeBoundsMappings): likewise (class TyVar): likewise (class TyWithLocation): likewise * typecheck/rust-tyty-bounds.h: New file. * typecheck/rust-tyty-util.cc: New file. * typecheck/rust-tyty-util.h: New file. --- gcc/rust/Make-lang.in | 1 + gcc/rust/typecheck/rust-tyty-bounds.h | 88 ++++++++++++++++++++++++++ gcc/rust/typecheck/rust-tyty-util.cc | 116 ++++++++++++++++++++++++++++++++++ gcc/rust/typecheck/rust-tyty-util.h | 69 ++++++++++++++++++++ gcc/rust/typecheck/rust-tyty.cc | 90 -------------------------- gcc/rust/typecheck/rust-tyty.h | 90 +------------------------- 6 files changed, 276 insertions(+), 178 deletions(-) create mode 100644 gcc/rust/typecheck/rust-tyty-bounds.h create mode 100644 gcc/rust/typecheck/rust-tyty-util.cc create mode 100644 gcc/rust/typecheck/rust-tyty-util.h (limited to 'gcc') diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 1aebf79..986b878 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -115,6 +115,7 @@ GRS_OBJS = \ rust/rust-pub-restricted-visitor.o \ rust/rust-privacy-reporter.o \ rust/rust-tyty.o \ + rust/rust-tyty-util.o \ rust/rust-tyty-call.o \ rust/rust-tyctx.o \ rust/rust-tyty-bounds.o \ diff --git a/gcc/rust/typecheck/rust-tyty-bounds.h b/gcc/rust/typecheck/rust-tyty-bounds.h new file mode 100644 index 0000000..44839bd --- /dev/null +++ b/gcc/rust/typecheck/rust-tyty-bounds.h @@ -0,0 +1,88 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_TYTY_BOUNDS_H +#define RUST_TYTY_BOUNDS_H + +#include "rust-location.h" + +namespace Rust { + +namespace Resolver { +class TraitReference; +class TraitItemReference; +class AssociatedImplTrait; +} // namespace Resolver + +namespace TyTy { + +class BaseType; +class TypeBoundPredicate; +class TypeBoundPredicateItem +{ +public: + TypeBoundPredicateItem (const TypeBoundPredicate *parent, + const Resolver::TraitItemReference *trait_item_ref); + + static TypeBoundPredicateItem error (); + + bool is_error () const; + + BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver); + + const Resolver::TraitItemReference *get_raw_item () const; + + bool needs_implementation () const; + + const TypeBoundPredicate *get_parent () const; + + Location get_locus () const; + +private: + const TypeBoundPredicate *parent; + const Resolver::TraitItemReference *trait_item_ref; +}; + +class TypeBoundsMappings +{ +protected: + TypeBoundsMappings (std::vector specified_bounds); + +public: + std::vector &get_specified_bounds (); + + const std::vector &get_specified_bounds () const; + + size_t num_specified_bounds () const; + + std::string raw_bounds_as_string () const; + + std::string bounds_as_string () const; + + std::string raw_bounds_as_name () const; + +protected: + void add_bound (TypeBoundPredicate predicate); + + std::vector specified_bounds; +}; + +} // namespace TyTy +} // namespace Rust + +#endif // RUST_TYTY_BOUNDS_H diff --git a/gcc/rust/typecheck/rust-tyty-util.cc b/gcc/rust/typecheck/rust-tyty-util.cc new file mode 100644 index 0000000..5037f68 --- /dev/null +++ b/gcc/rust/typecheck/rust-tyty-util.cc @@ -0,0 +1,116 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#include "rust-hir-type-check.h" +#include "rust-tyty.h" + +namespace Rust { +namespace TyTy { + +TyVar::TyVar (HirId ref) : ref (ref) +{ + // ensure this reference is defined within the context + auto context = Resolver::TypeCheckContext::get (); + BaseType *lookup = nullptr; + bool ok = context->lookup_type (ref, &lookup); + rust_assert (ok); +} + +BaseType * +TyVar::get_tyty () const +{ + auto context = Resolver::TypeCheckContext::get (); + BaseType *lookup = nullptr; + bool ok = context->lookup_type (ref, &lookup); + rust_assert (ok); + return lookup; +} + +TyVar +TyVar::get_implicit_infer_var (Location locus) +{ + auto mappings = Analysis::Mappings::get (); + auto context = Resolver::TypeCheckContext::get (); + + InferType *infer = new InferType (mappings->get_next_hir_id (), + InferType::InferTypeKind::GENERAL, locus); + context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (), + UNKNOWN_NODEID, + infer->get_ref (), + UNKNOWN_LOCAL_DEFID), + infer); + mappings->insert_location (infer->get_ref (), locus); + + return TyVar (infer->get_ref ()); +} + +TyVar +TyVar::subst_covariant_var (TyTy::BaseType *orig, TyTy::BaseType *subst) +{ + if (orig->get_kind () != TyTy::TypeKind::PARAM) + return TyVar (subst->get_ty_ref ()); + else if (subst->get_kind () == TyTy::TypeKind::PARAM) + { + TyTy::ParamType *p = static_cast (subst); + if (p->resolve ()->get_kind () == TyTy::TypeKind::PARAM) + { + return TyVar (subst->get_ty_ref ()); + } + } + + return TyVar (subst->get_ref ()); +} + +TyVar +TyVar::clone () const +{ + TyTy::BaseType *c = get_tyty ()->clone (); + return TyVar (c->get_ref ()); +} + +TyVar +TyVar::monomorphized_clone () const +{ + auto mappings = Analysis::Mappings::get (); + auto context = Resolver::TypeCheckContext::get (); + + // this needs a new hirid + TyTy::BaseType *c = get_tyty ()->monomorphized_clone (); + c->set_ref (mappings->get_next_hir_id ()); + + // insert it + context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (), + UNKNOWN_NODEID, c->get_ref (), + UNKNOWN_LOCAL_DEFID), + c); + + return TyVar (c->get_ref ()); +} + +TyWithLocation::TyWithLocation (BaseType *ty, Location locus) + : ty (ty), locus (locus) +{} + +TyWithLocation::TyWithLocation (BaseType *ty) : ty (ty) +{ + auto mappings = Analysis::Mappings::get (); + locus = mappings->lookup_location (ty->get_ref ()); +} + +} // namespace TyTy +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-util.h b/gcc/rust/typecheck/rust-tyty-util.h new file mode 100644 index 0000000..eccbb44 --- /dev/null +++ b/gcc/rust/typecheck/rust-tyty-util.h @@ -0,0 +1,69 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_TYTY_UTIL_H +#define RUST_TYTY_UTIL_H + +#include "rust-hir-map.h" + +namespace Rust { +namespace TyTy { + +class BaseType; + +// this is a placeholder for types that can change like inference variables +class TyVar +{ +public: + explicit TyVar (HirId ref); + + HirId get_ref () const { return ref; } + + BaseType *get_tyty () const; + + TyVar clone () const; + + TyVar monomorphized_clone () const; + + static TyVar get_implicit_infer_var (Location locus); + + static TyVar subst_covariant_var (TyTy::BaseType *orig, + TyTy::BaseType *subst); + +private: + HirId ref; +}; + +class TyWithLocation +{ +public: + explicit TyWithLocation (BaseType *ty, Location locus); + explicit TyWithLocation (BaseType *ty); + + BaseType *get_ty () const { return ty; } + Location get_locus () const { return locus; } + +private: + BaseType *ty; + Location locus; +}; + +} // namespace TyTy +} // namespace Rust + +#endif // RUST_TYTY_UTIL_H diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 9358919..333e7ab 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -330,96 +330,6 @@ BaseType::debug () const debug_str ().c_str ()); } -TyVar::TyVar (HirId ref) : ref (ref) -{ - // ensure this reference is defined within the context - auto context = Resolver::TypeCheckContext::get (); - BaseType *lookup = nullptr; - bool ok = context->lookup_type (ref, &lookup); - rust_assert (ok); -} - -BaseType * -TyVar::get_tyty () const -{ - auto context = Resolver::TypeCheckContext::get (); - BaseType *lookup = nullptr; - bool ok = context->lookup_type (ref, &lookup); - rust_assert (ok); - return lookup; -} - -TyVar -TyVar::get_implicit_infer_var (Location locus) -{ - auto mappings = Analysis::Mappings::get (); - auto context = Resolver::TypeCheckContext::get (); - - InferType *infer = new InferType (mappings->get_next_hir_id (), - InferType::InferTypeKind::GENERAL, locus); - context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (), - UNKNOWN_NODEID, - infer->get_ref (), - UNKNOWN_LOCAL_DEFID), - infer); - mappings->insert_location (infer->get_ref (), locus); - - return TyVar (infer->get_ref ()); -} - -TyVar -TyVar::subst_covariant_var (TyTy::BaseType *orig, TyTy::BaseType *subst) -{ - if (orig->get_kind () != TyTy::TypeKind::PARAM) - return TyVar (subst->get_ty_ref ()); - else if (subst->get_kind () == TyTy::TypeKind::PARAM) - { - TyTy::ParamType *p = static_cast (subst); - if (p->resolve ()->get_kind () == TyTy::TypeKind::PARAM) - { - return TyVar (subst->get_ty_ref ()); - } - } - - return TyVar (subst->get_ref ()); -} - -TyVar -TyVar::clone () const -{ - TyTy::BaseType *c = get_tyty ()->clone (); - return TyVar (c->get_ref ()); -} - -TyVar -TyVar::monomorphized_clone () const -{ - auto mappings = Analysis::Mappings::get (); - auto context = Resolver::TypeCheckContext::get (); - - // this needs a new hirid - TyTy::BaseType *c = get_tyty ()->monomorphized_clone (); - c->set_ref (mappings->get_next_hir_id ()); - - // insert it - context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (), - UNKNOWN_NODEID, c->get_ref (), - UNKNOWN_LOCAL_DEFID), - c); - - return TyVar (c->get_ref ()); -} - -TyWithLocation::TyWithLocation (BaseType *ty, Location locus) - : ty (ty), locus (locus) -{} - -TyWithLocation::TyWithLocation (BaseType *ty) : ty (ty) -{ - auto mappings = Analysis::Mappings::get (); - locus = mappings->lookup_location (ty->get_ref ()); -} - void InferType::accept_vis (TyVisitor &vis) { diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 365bf7d..5c564fa 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -25,6 +25,8 @@ #include "rust-abi.h" #include "rust-common.h" #include "rust-identifier.h" +#include "rust-tyty-bounds.h" +#include "rust-tyty-util.h" namespace Rust { @@ -76,57 +78,6 @@ public: static std::string to_string (TypeKind kind); }; -class BaseType; -class TypeBoundPredicate; -class TypeBoundPredicateItem -{ -public: - TypeBoundPredicateItem (const TypeBoundPredicate *parent, - const Resolver::TraitItemReference *trait_item_ref); - - static TypeBoundPredicateItem error (); - - bool is_error () const; - - BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver); - - const Resolver::TraitItemReference *get_raw_item () const; - - bool needs_implementation () const; - - const TypeBoundPredicate *get_parent () const; - - Location get_locus () const; - -private: - const TypeBoundPredicate *parent; - const Resolver::TraitItemReference *trait_item_ref; -}; - -class TypeBoundsMappings -{ -protected: - TypeBoundsMappings (std::vector specified_bounds); - -public: - std::vector &get_specified_bounds (); - - const std::vector &get_specified_bounds () const; - - size_t num_specified_bounds () const; - - std::string raw_bounds_as_string () const; - - std::string bounds_as_string () const; - - std::string raw_bounds_as_name () const; - -protected: - void add_bound (TypeBoundPredicate predicate); - - std::vector specified_bounds; -}; - extern void set_cmp_autoderef_mode (); extern void @@ -268,43 +219,6 @@ protected: Analysis::Mappings *mappings; }; -// this is a placeholder for types that can change like inference variables -class TyVar -{ -public: - explicit TyVar (HirId ref); - - HirId get_ref () const { return ref; } - - BaseType *get_tyty () const; - - TyVar clone () const; - - TyVar monomorphized_clone () const; - - static TyVar get_implicit_infer_var (Location locus); - - static TyVar subst_covariant_var (TyTy::BaseType *orig, - TyTy::BaseType *subst); - -private: - HirId ref; -}; - -class TyWithLocation -{ -public: - explicit TyWithLocation (BaseType *ty, Location locus); - explicit TyWithLocation (BaseType *ty); - - BaseType *get_ty () const { return ty; } - Location get_locus () const { return locus; } - -private: - BaseType *ty; - Location locus; -}; - class InferType : public BaseType { public: -- cgit v1.1 From fba98d61c34e349e0e4327a23b10732f4f4083fd Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 14 Jan 2023 23:22:59 +0000 Subject: gccrs: Refactor SubstitutionRef base class into its own CC file Signed-off-by: Philip Herron gcc/rust/ChangeLog: * Make-lang.in: update the makefile * typecheck/rust-tyty.cc (SubstitutionParamMapping::need_substitution): likewise (SubstitutionParamMapping::override_context): likewise (SubstitutionRef::get_mappings_from_generic_args): likewise (SubstitutionRef::infer_substitions): likewise (SubstitutionRef::are_mappings_bound): likewise (SubstitutionRef::solve_missing_mappings_from_this): likewise (SubstitutionRef::monomorphize): likewise * typecheck/rust-tyty.h (class SubstitutionParamMapping): likewise (class SubstitutionArg): likewise (std::function. + +#include "rust-tyty-subst.h" +#include "rust-hir-full.h" +#include "rust-tyty.h" +#include "rust-hir-type-check.h" +#include "rust-substitution-mapper.h" +#include "rust-hir-type-check-type.h" + +namespace Rust { +namespace TyTy { + +SubstitutionParamMapping::SubstitutionParamMapping ( + const HIR::TypeParam &generic, ParamType *param) + : generic (generic), param (param) +{} + +SubstitutionParamMapping::SubstitutionParamMapping ( + const SubstitutionParamMapping &other) + : generic (other.generic), param (other.param) +{} + +std::string +SubstitutionParamMapping::as_string () const +{ + if (param == nullptr) + return "nullptr"; + + return param->get_name (); +} + +SubstitutionParamMapping +SubstitutionParamMapping::clone () const +{ + return SubstitutionParamMapping (generic, + static_cast (param->clone ())); +} + +ParamType * +SubstitutionParamMapping::get_param_ty () +{ + return param; +} + +const ParamType * +SubstitutionParamMapping::get_param_ty () const +{ + return param; +} + +const HIR::TypeParam & +SubstitutionParamMapping::get_generic_param () +{ + return generic; +}; + +bool +SubstitutionParamMapping::needs_substitution () const +{ + return !(get_param_ty ()->is_concrete ()); +} + +Location +SubstitutionParamMapping::get_param_locus () const +{ + return generic.get_locus (); +} + +bool +SubstitutionParamMapping::param_has_default_ty () const +{ + return generic.has_type (); +} + +BaseType * +SubstitutionParamMapping::get_default_ty () const +{ + TyVar var (generic.get_type_mappings ().get_hirid ()); + return var.get_tyty (); +} + +bool +SubstitutionParamMapping::need_substitution () const +{ + if (!param->can_resolve ()) + return true; + + auto resolved = param->resolve (); + return !resolved->is_concrete (); +} + +bool +SubstitutionParamMapping::fill_param_ty ( + SubstitutionArgumentMappings &subst_mappings, Location locus) +{ + SubstitutionArg arg = SubstitutionArg::error (); + bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg); + if (!ok) + return true; + + TyTy::BaseType &type = *arg.get_tyty (); + if (type.get_kind () == TyTy::TypeKind::INFER) + { + type.inherit_bounds (*param); + } + else + { + if (!param->bounds_compatible (type, locus, true)) + return false; + } + + if (type.get_kind () == TypeKind::PARAM) + { + // delete param; + param = static_cast (type.clone ()); + } + else + { + // check the substitution is compatible with bounds + if (!param->bounds_compatible (type, locus, true)) + return false; + + // recursively pass this down to all HRTB's + for (auto &bound : param->get_specified_bounds ()) + bound.handle_substitions (subst_mappings); + + param->set_ty_ref (type.get_ref ()); + } + + return true; +} + +void +SubstitutionParamMapping::override_context () +{ + if (!param->can_resolve ()) + return; + + auto mappings = Analysis::Mappings::get (); + auto context = Resolver::TypeCheckContext::get (); + + context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (), + UNKNOWN_NODEID, + param->get_ref (), + UNKNOWN_LOCAL_DEFID), + param->resolve ()); +} + +SubstitutionArg::SubstitutionArg (const SubstitutionParamMapping *param, + BaseType *argument) + : param (param), argument (argument) +{} + +SubstitutionArg::SubstitutionArg (const SubstitutionArg &other) + : param (other.param), argument (other.argument) +{} + +SubstitutionArg & +SubstitutionArg::operator= (const SubstitutionArg &other) +{ + param = other.param; + argument = other.argument; + return *this; +} + +BaseType * +SubstitutionArg::get_tyty () +{ + return argument; +} + +const BaseType * +SubstitutionArg::get_tyty () const +{ + return argument; +} + +const SubstitutionParamMapping * +SubstitutionArg::get_param_mapping () const +{ + return param; +} + +SubstitutionArg +SubstitutionArg::error () +{ + return SubstitutionArg (nullptr, nullptr); +} + +bool +SubstitutionArg::is_error () const +{ + return param == nullptr || argument == nullptr; +} + +bool +SubstitutionArg::is_conrete () const +{ + if (argument != nullptr) + return true; + + if (argument->get_kind () == TyTy::TypeKind::PARAM) + return false; + + return argument->is_concrete (); +} + +std::string +SubstitutionArg::as_string () const +{ + return param->as_string () + + (argument != nullptr ? ":" + argument->as_string () : ""); +} + +// SubstitutionArgumentMappings + +SubstitutionArgumentMappings::SubstitutionArgumentMappings ( + std::vector mappings, + std::map binding_args, Location locus, + ParamSubstCb param_subst_cb, bool trait_item_flag) + : mappings (mappings), binding_args (binding_args), locus (locus), + param_subst_cb (param_subst_cb), trait_item_flag (trait_item_flag) +{} + +SubstitutionArgumentMappings::SubstitutionArgumentMappings ( + const SubstitutionArgumentMappings &other) + : mappings (other.mappings), binding_args (other.binding_args), + locus (other.locus), param_subst_cb (other.param_subst_cb), + trait_item_flag (other.trait_item_flag) +{} + +SubstitutionArgumentMappings & +SubstitutionArgumentMappings::operator= ( + const SubstitutionArgumentMappings &other) +{ + mappings = other.mappings; + binding_args = other.binding_args; + locus = other.locus; + param_subst_cb = other.param_subst_cb; + trait_item_flag = other.trait_item_flag; + + return *this; +} + +SubstitutionArgumentMappings +SubstitutionArgumentMappings::error () +{ + return SubstitutionArgumentMappings ({}, {}, Location (), nullptr, false); +} + +bool +SubstitutionArgumentMappings::is_error () const +{ + return mappings.size () == 0; +} + +bool +SubstitutionArgumentMappings::get_argument_for_symbol ( + const ParamType *param_to_find, SubstitutionArg *argument) +{ + for (auto &mapping : mappings) + { + const SubstitutionParamMapping *param = mapping.get_param_mapping (); + const ParamType *p = param->get_param_ty (); + + if (p->get_symbol ().compare (param_to_find->get_symbol ()) == 0) + { + *argument = mapping; + return true; + } + } + return false; +} + +bool +SubstitutionArgumentMappings::get_argument_at (size_t index, + SubstitutionArg *argument) +{ + if (index > mappings.size ()) + return false; + + *argument = mappings.at (index); + return true; +} + +bool +SubstitutionArgumentMappings::is_concrete () const +{ + for (auto &mapping : mappings) + { + if (!mapping.is_conrete ()) + return false; + } + return true; +} + +Location +SubstitutionArgumentMappings::get_locus () const +{ + return locus; +} + +size_t +SubstitutionArgumentMappings::size () const +{ + return mappings.size (); +} + +bool +SubstitutionArgumentMappings::is_empty () const +{ + return size () == 0; +} + +std::vector & +SubstitutionArgumentMappings::get_mappings () +{ + return mappings; +} + +const std::vector & +SubstitutionArgumentMappings::get_mappings () const +{ + return mappings; +} + +std::map & +SubstitutionArgumentMappings::get_binding_args () +{ + return binding_args; +} + +const std::map & +SubstitutionArgumentMappings::get_binding_args () const +{ + return binding_args; +} + +std::string +SubstitutionArgumentMappings::as_string () const +{ + std::string buffer; + for (auto &mapping : mappings) + { + buffer += mapping.as_string () + ", "; + } + return "<" + buffer + ">"; +} + +void +SubstitutionArgumentMappings::on_param_subst (const ParamType &p, + const SubstitutionArg &a) const +{ + if (param_subst_cb == nullptr) + return; + + param_subst_cb (p, a); +} + +ParamSubstCb +SubstitutionArgumentMappings::get_subst_cb () const +{ + return param_subst_cb; +} + +bool +SubstitutionArgumentMappings::trait_item_mode () const +{ + return trait_item_flag; +} + +// SubstitutionRef + +SubstitutionRef::SubstitutionRef ( + std::vector substitutions, + SubstitutionArgumentMappings arguments) + : substitutions (substitutions), used_arguments (arguments) +{} + +bool +SubstitutionRef::has_substitutions () const +{ + return substitutions.size () > 0; +} + +std::string +SubstitutionRef::subst_as_string () const +{ + std::string buffer; + for (size_t i = 0; i < substitutions.size (); i++) + { + const SubstitutionParamMapping &sub = substitutions.at (i); + buffer += sub.as_string (); + + if ((i + 1) < substitutions.size ()) + buffer += ", "; + } + + return buffer.empty () ? "" : "<" + buffer + ">"; +} + +bool +SubstitutionRef::supports_associated_bindings () const +{ + return get_num_associated_bindings () > 0; +} + +size_t +SubstitutionRef::get_num_associated_bindings () const +{ + return 0; +} + +TypeBoundPredicateItem +SubstitutionRef::lookup_associated_type (const std::string &search) +{ + return TypeBoundPredicateItem::error (); +} + +size_t +SubstitutionRef::get_num_substitutions () const +{ + return substitutions.size (); +} + +std::vector & +SubstitutionRef::get_substs () +{ + return substitutions; +} + +const std::vector & +SubstitutionRef::get_substs () const +{ + return substitutions; +} + +std::vector +SubstitutionRef::clone_substs () const +{ + std::vector clone; + + for (auto &sub : substitutions) + clone.push_back (sub.clone ()); + + return clone; +} + +void +SubstitutionRef::override_context () +{ + for (auto &sub : substitutions) + { + sub.override_context (); + } +} + +bool +SubstitutionRef::needs_substitution () const +{ + for (auto &sub : substitutions) + { + if (sub.need_substitution ()) + return true; + } + return false; +} + +bool +SubstitutionRef::was_substituted () const +{ + return !needs_substitution (); +} + +SubstitutionArgumentMappings +SubstitutionRef::get_substitution_arguments () const +{ + return used_arguments; +} + +size_t +SubstitutionRef::num_required_substitutions () const +{ + size_t n = 0; + for (auto &p : substitutions) + { + if (p.needs_substitution ()) + n++; + } + return n; +} + +size_t +SubstitutionRef::min_required_substitutions () const +{ + size_t n = 0; + for (auto &p : substitutions) + { + if (p.needs_substitution () && !p.param_has_default_ty ()) + n++; + } + return n; +} + +SubstitutionArgumentMappings +SubstitutionRef::get_used_arguments () const +{ + return used_arguments; +} + +SubstitutionArgumentMappings +SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args) +{ + std::map binding_arguments; + if (args.get_binding_args ().size () > 0) + { + if (supports_associated_bindings ()) + { + if (args.get_binding_args ().size () > get_num_associated_bindings ()) + { + RichLocation r (args.get_locus ()); + + rust_error_at (r, + "generic item takes at most %lu type binding " + "arguments but %lu were supplied", + (unsigned long) get_num_associated_bindings (), + (unsigned long) args.get_binding_args ().size ()); + return SubstitutionArgumentMappings::error (); + } + + for (auto &binding : args.get_binding_args ()) + { + BaseType *resolved + = Resolver::TypeCheckType::Resolve (binding.get_type ().get ()); + if (resolved == nullptr + || resolved->get_kind () == TyTy::TypeKind::ERROR) + { + rust_error_at (binding.get_locus (), + "failed to resolve type arguments"); + return SubstitutionArgumentMappings::error (); + } + + // resolve to relevant binding + auto binding_item + = lookup_associated_type (binding.get_identifier ()); + if (binding_item.is_error ()) + { + rust_error_at (binding.get_locus (), + "unknown associated type binding: %s", + binding.get_identifier ().c_str ()); + return SubstitutionArgumentMappings::error (); + } + + binding_arguments[binding.get_identifier ()] = resolved; + } + } + else + { + RichLocation r (args.get_locus ()); + for (auto &binding : args.get_binding_args ()) + r.add_range (binding.get_locus ()); + + rust_error_at (r, "associated type bindings are not allowed here"); + return SubstitutionArgumentMappings::error (); + } + } + + // for inherited arguments + size_t offs = used_arguments.size (); + if (args.get_type_args ().size () + offs > substitutions.size ()) + { + RichLocation r (args.get_locus ()); + r.add_range (substitutions.front ().get_param_locus ()); + + rust_error_at ( + r, + "generic item takes at most %lu type arguments but %lu were supplied", + (unsigned long) substitutions.size (), + (unsigned long) args.get_type_args ().size ()); + return SubstitutionArgumentMappings::error (); + } + + if (args.get_type_args ().size () + offs < min_required_substitutions ()) + { + RichLocation r (args.get_locus ()); + r.add_range (substitutions.front ().get_param_locus ()); + + rust_error_at ( + r, + "generic item takes at least %lu type arguments but %lu were supplied", + (unsigned long) (min_required_substitutions () - offs), + (unsigned long) args.get_type_args ().size ()); + return SubstitutionArgumentMappings::error (); + } + + std::vector mappings = used_arguments.get_mappings (); + for (auto &arg : args.get_type_args ()) + { + BaseType *resolved = Resolver::TypeCheckType::Resolve (arg.get ()); + if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR) + { + rust_error_at (args.get_locus (), "failed to resolve type arguments"); + return SubstitutionArgumentMappings::error (); + } + + SubstitutionArg subst_arg (&substitutions.at (offs), resolved); + offs++; + mappings.push_back (std::move (subst_arg)); + } + + // we must need to fill out defaults + size_t left_over + = num_required_substitutions () - min_required_substitutions (); + if (left_over > 0) + { + for (size_t offs = mappings.size (); offs < substitutions.size (); offs++) + { + SubstitutionParamMapping ¶m = substitutions.at (offs); + rust_assert (param.param_has_default_ty ()); + + BaseType *resolved = param.get_default_ty (); + if (resolved->get_kind () == TypeKind::ERROR) + return SubstitutionArgumentMappings::error (); + + // this resolved default might already contain default parameters + if (resolved->contains_type_parameters ()) + { + SubstitutionArgumentMappings intermediate (mappings, + binding_arguments, + args.get_locus ()); + resolved = Resolver::SubstMapperInternal::Resolve (resolved, + intermediate); + + if (resolved->get_kind () == TypeKind::ERROR) + return SubstitutionArgumentMappings::error (); + } + + SubstitutionArg subst_arg (¶m, resolved); + mappings.push_back (std::move (subst_arg)); + } + } + + return SubstitutionArgumentMappings (mappings, binding_arguments, + args.get_locus ()); +} + +BaseType * +SubstitutionRef::infer_substitions (Location locus) +{ + std::vector args; + std::map argument_mappings; + for (auto &p : get_substs ()) + { + if (p.needs_substitution ()) + { + const std::string &symbol = p.get_param_ty ()->get_symbol (); + auto it = argument_mappings.find (symbol); + bool have_mapping = it != argument_mappings.end (); + + if (have_mapping) + { + args.push_back (SubstitutionArg (&p, it->second)); + } + else + { + TyVar infer_var = TyVar::get_implicit_infer_var (locus); + args.push_back (SubstitutionArg (&p, infer_var.get_tyty ())); + argument_mappings[symbol] = infer_var.get_tyty (); + } + } + else + { + args.push_back (SubstitutionArg (&p, p.get_param_ty ()->resolve ())); + } + } + + // FIXME do we need to add inference variables to all the possible bindings? + // it might just lead to inference variable hell not 100% sure if rustc does + // this i think the language might needs this to be explicitly set + + SubstitutionArgumentMappings infer_arguments (std::move (args), + {} /* binding_arguments */, + locus); + return handle_substitions (std::move (infer_arguments)); +} + +SubstitutionArgumentMappings +SubstitutionRef::adjust_mappings_for_this ( + SubstitutionArgumentMappings &mappings) +{ + std::vector resolved_mappings; + for (size_t i = 0; i < substitutions.size (); i++) + { + auto &subst = substitutions.at (i); + + SubstitutionArg arg = SubstitutionArg::error (); + if (mappings.size () == substitutions.size ()) + { + mappings.get_argument_at (i, &arg); + } + else + { + if (subst.needs_substitution ()) + { + // get from passed in mappings + mappings.get_argument_for_symbol (subst.get_param_ty (), &arg); + } + else + { + // we should already have this somewhere + used_arguments.get_argument_for_symbol (subst.get_param_ty (), + &arg); + } + } + + bool ok = !arg.is_error (); + if (ok) + { + SubstitutionArg adjusted (&subst, arg.get_tyty ()); + resolved_mappings.push_back (std::move (adjusted)); + } + } + + if (resolved_mappings.empty ()) + return SubstitutionArgumentMappings::error (); + + return SubstitutionArgumentMappings (resolved_mappings, + mappings.get_binding_args (), + mappings.get_locus (), + mappings.get_subst_cb (), + mappings.trait_item_mode ()); +} + +bool +SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings) +{ + std::vector resolved_mappings; + for (size_t i = 0; i < substitutions.size (); i++) + { + auto &subst = substitutions.at (i); + + SubstitutionArg arg = SubstitutionArg::error (); + if (mappings.size () == substitutions.size ()) + { + mappings.get_argument_at (i, &arg); + } + else + { + if (subst.needs_substitution ()) + { + // get from passed in mappings + mappings.get_argument_for_symbol (subst.get_param_ty (), &arg); + } + else + { + // we should already have this somewhere + used_arguments.get_argument_for_symbol (subst.get_param_ty (), + &arg); + } + } + + bool ok = !arg.is_error (); + if (ok) + { + SubstitutionArg adjusted (&subst, arg.get_tyty ()); + resolved_mappings.push_back (std::move (adjusted)); + } + } + + return !resolved_mappings.empty (); +} + +// this function assumes that the mappings being passed are for the same type as +// this new substitution reference so ordering matters here +SubstitutionArgumentMappings +SubstitutionRef::solve_mappings_from_receiver_for_self ( + SubstitutionArgumentMappings &mappings) const +{ + std::vector resolved_mappings; + + rust_assert (mappings.size () == get_num_substitutions ()); + for (size_t i = 0; i < get_num_substitutions (); i++) + { + const SubstitutionParamMapping ¶m_mapping = substitutions.at (i); + SubstitutionArg &arg = mappings.get_mappings ().at (i); + + if (param_mapping.needs_substitution ()) + { + SubstitutionArg adjusted (¶m_mapping, arg.get_tyty ()); + resolved_mappings.push_back (std::move (adjusted)); + } + } + + return SubstitutionArgumentMappings (resolved_mappings, + mappings.get_binding_args (), + mappings.get_locus ()); +} + +SubstitutionArgumentMappings +SubstitutionRef::solve_missing_mappings_from_this (SubstitutionRef &ref, + SubstitutionRef &to) +{ + rust_assert (!ref.needs_substitution ()); + rust_assert (needs_substitution ()); + rust_assert (get_num_substitutions () == ref.get_num_substitutions ()); + + Location locus = used_arguments.get_locus (); + std::vector resolved_mappings; + + std::map> substs; + for (size_t i = 0; i < get_num_substitutions (); i++) + { + SubstitutionParamMapping &a = substitutions.at (i); + SubstitutionParamMapping &b = ref.substitutions.at (i); + + if (a.need_substitution ()) + { + const BaseType *root = a.get_param_ty ()->resolve ()->get_root (); + rust_assert (root->get_kind () == TyTy::TypeKind::PARAM); + const ParamType *p = static_cast (root); + + substs[p->get_ty_ref ()] = {static_cast (p->clone ()), + b.get_param_ty ()->resolve ()}; + } + } + + for (auto it = substs.begin (); it != substs.end (); it++) + { + HirId param_id = it->first; + BaseType *arg = it->second.second; + + const SubstitutionParamMapping *associate_param = nullptr; + for (SubstitutionParamMapping &p : to.substitutions) + { + if (p.get_param_ty ()->get_ty_ref () == param_id) + { + associate_param = &p; + break; + } + } + + rust_assert (associate_param != nullptr); + SubstitutionArg argument (associate_param, arg); + resolved_mappings.push_back (std::move (argument)); + } + + return SubstitutionArgumentMappings (resolved_mappings, {}, locus); +} + +bool +SubstitutionRef::monomorphize () +{ + auto context = Resolver::TypeCheckContext::get (); + for (const auto &subst : get_substs ()) + { + const TyTy::ParamType *pty = subst.get_param_ty (); + + if (!pty->can_resolve ()) + continue; + + const TyTy::BaseType *binding = pty->resolve (); + if (binding->get_kind () == TyTy::TypeKind::PARAM) + continue; + + for (const auto &bound : pty->get_specified_bounds ()) + { + const Resolver::TraitReference *specified_bound_ref = bound.get (); + + // setup any associated type mappings for the specified bonds and this + // type + auto candidates = Resolver::TypeBoundsProbe::Probe (binding); + + Resolver::AssociatedImplTrait *associated_impl_trait = nullptr; + for (auto &probed_bound : candidates) + { + const Resolver::TraitReference *bound_trait_ref + = probed_bound.first; + const HIR::ImplBlock *associated_impl = probed_bound.second; + + HirId impl_block_id + = associated_impl->get_mappings ().get_hirid (); + Resolver::AssociatedImplTrait *associated = nullptr; + bool found_impl_trait + = context->lookup_associated_trait_impl (impl_block_id, + &associated); + if (found_impl_trait) + { + bool found_trait + = specified_bound_ref->is_equal (*bound_trait_ref); + bool found_self + = associated->get_self ()->can_eq (binding, false); + if (found_trait && found_self) + { + associated_impl_trait = associated; + break; + } + } + } + + if (associated_impl_trait != nullptr) + { + associated_impl_trait->setup_associated_types (binding, bound); + } + } + } + + return true; +} + +} // namespace TyTy +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h new file mode 100644 index 0000000..4d09a30 --- /dev/null +++ b/gcc/rust/typecheck/rust-tyty-subst.h @@ -0,0 +1,316 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_TYTY_SUBST_H +#define RUST_TYTY_SUBST_H + +#include "rust-system.h" +#include "rust-location.h" +#include "rust-hir-full-decls.h" +#include "rust-tyty-bounds.h" + +namespace Rust { +namespace TyTy { + +class BaseType; +class ParamType; +class SubstitutionArgumentMappings; +class SubstitutionParamMapping +{ +public: + SubstitutionParamMapping (const HIR::TypeParam &generic, ParamType *param); + + SubstitutionParamMapping (const SubstitutionParamMapping &other); + + std::string as_string () const; + + bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings, + Location locus); + + SubstitutionParamMapping clone () const; + + ParamType *get_param_ty (); + + const ParamType *get_param_ty () const; + + const HIR::TypeParam &get_generic_param (); + + // this is used for the backend to override the HirId ref of the param to + // what the concrete type is for the rest of the context + void override_context (); + + bool needs_substitution () const; + + Location get_param_locus () const; + + bool param_has_default_ty () const; + + BaseType *get_default_ty () const; + + bool need_substitution () const; + +private: + const HIR::TypeParam &generic; + ParamType *param; +}; + +class SubstitutionArg +{ +public: + SubstitutionArg (const SubstitutionParamMapping *param, BaseType *argument); + + // FIXME + // the copy constructors need removed - they are unsafe see + // TypeBoundPredicate + SubstitutionArg (const SubstitutionArg &other); + + SubstitutionArg &operator= (const SubstitutionArg &other); + + BaseType *get_tyty (); + + const BaseType *get_tyty () const; + + const SubstitutionParamMapping *get_param_mapping () const; + + static SubstitutionArg error (); + + bool is_error () const; + + bool is_conrete () const; + + std::string as_string () const; + +private: + const SubstitutionParamMapping *param; + BaseType *argument; +}; + +typedef std::function + ParamSubstCb; +class SubstitutionArgumentMappings +{ +public: + SubstitutionArgumentMappings (std::vector mappings, + std::map binding_args, + Location locus, + ParamSubstCb param_subst_cb = nullptr, + bool trait_item_flag = false); + + SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other); + SubstitutionArgumentMappings & + operator= (const SubstitutionArgumentMappings &other); + + SubstitutionArgumentMappings (SubstitutionArgumentMappings &&other) = default; + SubstitutionArgumentMappings &operator= (SubstitutionArgumentMappings &&other) + = default; + + static SubstitutionArgumentMappings error (); + + bool is_error () const; + + bool get_argument_for_symbol (const ParamType *param_to_find, + SubstitutionArg *argument); + + bool get_argument_at (size_t index, SubstitutionArg *argument); + + // is_concrete means if the used args is non error, ie: non empty this will + // verify if actual real types have been put in place of are they still + // ParamTy + bool is_concrete () const; + + Location get_locus () const; + + size_t size () const; + + bool is_empty () const; + + std::vector &get_mappings (); + + const std::vector &get_mappings () const; + + std::map &get_binding_args (); + + const std::map &get_binding_args () const; + + std::string as_string () const; + + void on_param_subst (const ParamType &p, const SubstitutionArg &a) const; + + ParamSubstCb get_subst_cb () const; + + bool trait_item_mode () const; + +private: + std::vector mappings; + std::map binding_args; + Location locus; + ParamSubstCb param_subst_cb; + bool trait_item_flag; +}; + +class SubstitutionRef +{ +public: + SubstitutionRef (std::vector substitutions, + SubstitutionArgumentMappings arguments); + + bool has_substitutions () const; + + std::string subst_as_string () const; + + bool supports_associated_bindings () const; + + // this is overridden in TypeBoundPredicate + // which support bindings we don't add them directly to the SubstitutionRef + // base class because this class represents the fn. The only + // construct which supports associated types + virtual size_t get_num_associated_bindings () const; + + // this is overridden in TypeBoundPredicate + virtual TypeBoundPredicateItem + lookup_associated_type (const std::string &search); + + size_t get_num_substitutions () const; + + std::vector &get_substs (); + + const std::vector &get_substs () const; + + std::vector clone_substs () const; + + void override_context (); + + bool needs_substitution () const; + + bool was_substituted () const; + + SubstitutionArgumentMappings get_substitution_arguments () const; + + // this is the count of type params that are not substituted fuly + size_t num_required_substitutions () const; + + // this is the count of type params that need substituted taking into account + // possible defaults + size_t min_required_substitutions () const; + + // We are trying to subst into Struct Foo {} + // in the case of Foo{...} + // + // the substitions we have here define X,Y but the arguments have no bindings + // so its a matter of ordering + SubstitutionArgumentMappings + get_mappings_from_generic_args (HIR::GenericArgs &args); + + // Recursive substitutions + // Foo { a:A, b: B}; Bar {a:X, b: Foo} + // + // we have bindings for X Y Z and need to propagate the binding Y,Z into Foo + // Which binds to A,B + SubstitutionArgumentMappings + adjust_mappings_for_this (SubstitutionArgumentMappings &mappings); + + // Are the mappings here actually bound to this type. For example imagine the + // case: + // + // struct Foo(T); + // impl Foo { + // fn test(self) { ... } + // } + // + // In this case we have a generic ADT of Foo and an impl block of a generic T + // on Foo for the Self type. When we it comes to path resolution we can have: + // + // Foo::::test() + // + // This means the first segment of Foo:: returns the ADT Foo not the + // Self ADT bound to the T from the impl block. This means when it comes to + // the next segment of test which resolves to the function we need to check + // wether the arguments in the struct definition of foo can be bound here + // before substituting the previous segments type here. This functions acts as + // a guard for the solve_mappings_from_receiver_for_self to handle the case + // where arguments are not bound. This is important for this next case: + // + // struct Baz(A, B); + // impl Baz { + // fn test(a: X) -> X { + // a + // } + // } + // + // In this case Baz has been already substituted for the impl's Self to become + // ADT so that the function test only has 1 generic argument of X. + // The path for this will be: + // + // Baz::test::<_>(123) + // + // So the first segment here will be Baz<_, _> to try and infer the arguments + // which will be taken from the impl's Self type in this case since it is + // already substituted and like the previous case the check to see if we need + // to inherit the previous segments generic arguments takes place but the + // generic arguments are not bound to this type as they have already been + // substituted. + // + // Its important to remember from the first example the FnType actually looks + // like: + // + // fn test(self :Foo(T)) + // + // As the generic parameters are "bound" to each of the items in the impl + // block. So this check is about wether the arguments we have here can + // actually be bound to this type. + bool are_mappings_bound (SubstitutionArgumentMappings &mappings); + + // struct Foo(A, B); + // + // impl Foo; + // -> fn test(self, a: X) -> X + // + // We might invoke this via: + // + // a = Foo(123, 456f32); + // b = a.test::(false); + // + // we need to figure out relevant generic arguemts for self to apply to the + // fntype + SubstitutionArgumentMappings solve_mappings_from_receiver_for_self ( + SubstitutionArgumentMappings &mappings) const; + + // TODO comment + SubstitutionArgumentMappings + solve_missing_mappings_from_this (SubstitutionRef &ref, SubstitutionRef &to); + + // TODO comment + BaseType *infer_substitions (Location locus); + + // TODO comment + bool monomorphize (); + + // TODO comment + virtual BaseType *handle_substitions (SubstitutionArgumentMappings mappings) + = 0; + + SubstitutionArgumentMappings get_used_arguments () const; + +protected: + std::vector substitutions; + SubstitutionArgumentMappings used_arguments; +}; + +} // namespace TyTy +} // namespace Rust +#endif // RUST_TYTY_SUBST_H diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 333e7ab..7b86112 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -514,472 +514,6 @@ StructFieldType::monomorphized_clone () const get_field_type ()->monomorphized_clone (), locus); } -bool -SubstitutionParamMapping::need_substitution () const -{ - if (!param->can_resolve ()) - return true; - - auto resolved = param->resolve (); - return !resolved->is_concrete (); -} - -bool -SubstitutionParamMapping::fill_param_ty ( - SubstitutionArgumentMappings &subst_mappings, Location locus) -{ - SubstitutionArg arg = SubstitutionArg::error (); - bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg); - if (!ok) - return true; - - TyTy::BaseType &type = *arg.get_tyty (); - if (type.get_kind () == TyTy::TypeKind::INFER) - { - type.inherit_bounds (*param); - } - else - { - if (!param->bounds_compatible (type, locus, true)) - return false; - } - - if (type.get_kind () == TypeKind::PARAM) - { - // delete param; - param = static_cast (type.clone ()); - } - else - { - // check the substitution is compatible with bounds - if (!param->bounds_compatible (type, locus, true)) - return false; - - // recursively pass this down to all HRTB's - for (auto &bound : param->get_specified_bounds ()) - bound.handle_substitions (subst_mappings); - - param->set_ty_ref (type.get_ref ()); - } - - return true; -} - -void -SubstitutionParamMapping::override_context () -{ - if (!param->can_resolve ()) - return; - - auto mappings = Analysis::Mappings::get (); - auto context = Resolver::TypeCheckContext::get (); - - context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (), - UNKNOWN_NODEID, - param->get_ref (), - UNKNOWN_LOCAL_DEFID), - param->resolve ()); -} - -SubstitutionArgumentMappings -SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args) -{ - std::map binding_arguments; - if (args.get_binding_args ().size () > 0) - { - if (supports_associated_bindings ()) - { - if (args.get_binding_args ().size () > get_num_associated_bindings ()) - { - RichLocation r (args.get_locus ()); - - rust_error_at (r, - "generic item takes at most %lu type binding " - "arguments but %lu were supplied", - (unsigned long) get_num_associated_bindings (), - (unsigned long) args.get_binding_args ().size ()); - return SubstitutionArgumentMappings::error (); - } - - for (auto &binding : args.get_binding_args ()) - { - BaseType *resolved - = Resolver::TypeCheckType::Resolve (binding.get_type ().get ()); - if (resolved == nullptr - || resolved->get_kind () == TyTy::TypeKind::ERROR) - { - rust_error_at (binding.get_locus (), - "failed to resolve type arguments"); - return SubstitutionArgumentMappings::error (); - } - - // resolve to relevant binding - auto binding_item - = lookup_associated_type (binding.get_identifier ()); - if (binding_item.is_error ()) - { - rust_error_at (binding.get_locus (), - "unknown associated type binding: %s", - binding.get_identifier ().c_str ()); - return SubstitutionArgumentMappings::error (); - } - - binding_arguments[binding.get_identifier ()] = resolved; - } - } - else - { - RichLocation r (args.get_locus ()); - for (auto &binding : args.get_binding_args ()) - r.add_range (binding.get_locus ()); - - rust_error_at (r, "associated type bindings are not allowed here"); - return SubstitutionArgumentMappings::error (); - } - } - - // for inherited arguments - size_t offs = used_arguments.size (); - if (args.get_type_args ().size () + offs > substitutions.size ()) - { - RichLocation r (args.get_locus ()); - r.add_range (substitutions.front ().get_param_locus ()); - - rust_error_at ( - r, - "generic item takes at most %lu type arguments but %lu were supplied", - (unsigned long) substitutions.size (), - (unsigned long) args.get_type_args ().size ()); - return SubstitutionArgumentMappings::error (); - } - - if (args.get_type_args ().size () + offs < min_required_substitutions ()) - { - RichLocation r (args.get_locus ()); - r.add_range (substitutions.front ().get_param_locus ()); - - rust_error_at ( - r, - "generic item takes at least %lu type arguments but %lu were supplied", - (unsigned long) (min_required_substitutions () - offs), - (unsigned long) args.get_type_args ().size ()); - return SubstitutionArgumentMappings::error (); - } - - std::vector mappings = used_arguments.get_mappings (); - for (auto &arg : args.get_type_args ()) - { - BaseType *resolved = Resolver::TypeCheckType::Resolve (arg.get ()); - if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR) - { - rust_error_at (args.get_locus (), "failed to resolve type arguments"); - return SubstitutionArgumentMappings::error (); - } - - SubstitutionArg subst_arg (&substitutions.at (offs), resolved); - offs++; - mappings.push_back (std::move (subst_arg)); - } - - // we must need to fill out defaults - size_t left_over - = num_required_substitutions () - min_required_substitutions (); - if (left_over > 0) - { - for (size_t offs = mappings.size (); offs < substitutions.size (); offs++) - { - SubstitutionParamMapping ¶m = substitutions.at (offs); - rust_assert (param.param_has_default_ty ()); - - BaseType *resolved = param.get_default_ty (); - if (resolved->get_kind () == TypeKind::ERROR) - return SubstitutionArgumentMappings::error (); - - // this resolved default might already contain default parameters - if (resolved->contains_type_parameters ()) - { - SubstitutionArgumentMappings intermediate (mappings, - binding_arguments, - args.get_locus ()); - resolved = Resolver::SubstMapperInternal::Resolve (resolved, - intermediate); - - if (resolved->get_kind () == TypeKind::ERROR) - return SubstitutionArgumentMappings::error (); - } - - SubstitutionArg subst_arg (¶m, resolved); - mappings.push_back (std::move (subst_arg)); - } - } - - return SubstitutionArgumentMappings (mappings, binding_arguments, - args.get_locus ()); -} - -BaseType * -SubstitutionRef::infer_substitions (Location locus) -{ - std::vector args; - std::map argument_mappings; - for (auto &p : get_substs ()) - { - if (p.needs_substitution ()) - { - const std::string &symbol = p.get_param_ty ()->get_symbol (); - auto it = argument_mappings.find (symbol); - bool have_mapping = it != argument_mappings.end (); - - if (have_mapping) - { - args.push_back (SubstitutionArg (&p, it->second)); - } - else - { - TyVar infer_var = TyVar::get_implicit_infer_var (locus); - args.push_back (SubstitutionArg (&p, infer_var.get_tyty ())); - argument_mappings[symbol] = infer_var.get_tyty (); - } - } - else - { - args.push_back (SubstitutionArg (&p, p.get_param_ty ()->resolve ())); - } - } - - // FIXME do we need to add inference variables to all the possible bindings? - // it might just lead to inference variable hell not 100% sure if rustc does - // this i think the language might needs this to be explicitly set - - SubstitutionArgumentMappings infer_arguments (std::move (args), - {} /* binding_arguments */, - locus); - return handle_substitions (std::move (infer_arguments)); -} - -SubstitutionArgumentMappings -SubstitutionRef::adjust_mappings_for_this ( - SubstitutionArgumentMappings &mappings) -{ - std::vector resolved_mappings; - for (size_t i = 0; i < substitutions.size (); i++) - { - auto &subst = substitutions.at (i); - - SubstitutionArg arg = SubstitutionArg::error (); - if (mappings.size () == substitutions.size ()) - { - mappings.get_argument_at (i, &arg); - } - else - { - if (subst.needs_substitution ()) - { - // get from passed in mappings - mappings.get_argument_for_symbol (subst.get_param_ty (), &arg); - } - else - { - // we should already have this somewhere - used_arguments.get_argument_for_symbol (subst.get_param_ty (), - &arg); - } - } - - bool ok = !arg.is_error (); - if (ok) - { - SubstitutionArg adjusted (&subst, arg.get_tyty ()); - resolved_mappings.push_back (std::move (adjusted)); - } - } - - if (resolved_mappings.empty ()) - return SubstitutionArgumentMappings::error (); - - return SubstitutionArgumentMappings (resolved_mappings, - mappings.get_binding_args (), - mappings.get_locus (), - mappings.get_subst_cb (), - mappings.trait_item_mode ()); -} - -bool -SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings) -{ - std::vector resolved_mappings; - for (size_t i = 0; i < substitutions.size (); i++) - { - auto &subst = substitutions.at (i); - - SubstitutionArg arg = SubstitutionArg::error (); - if (mappings.size () == substitutions.size ()) - { - mappings.get_argument_at (i, &arg); - } - else - { - if (subst.needs_substitution ()) - { - // get from passed in mappings - mappings.get_argument_for_symbol (subst.get_param_ty (), &arg); - } - else - { - // we should already have this somewhere - used_arguments.get_argument_for_symbol (subst.get_param_ty (), - &arg); - } - } - - bool ok = !arg.is_error (); - if (ok) - { - SubstitutionArg adjusted (&subst, arg.get_tyty ()); - resolved_mappings.push_back (std::move (adjusted)); - } - } - - return !resolved_mappings.empty (); -} - -// this function assumes that the mappings being passed are for the same type as -// this new substitution reference so ordering matters here -SubstitutionArgumentMappings -SubstitutionRef::solve_mappings_from_receiver_for_self ( - SubstitutionArgumentMappings &mappings) const -{ - std::vector resolved_mappings; - - rust_assert (mappings.size () == get_num_substitutions ()); - for (size_t i = 0; i < get_num_substitutions (); i++) - { - const SubstitutionParamMapping ¶m_mapping = substitutions.at (i); - SubstitutionArg &arg = mappings.get_mappings ().at (i); - - if (param_mapping.needs_substitution ()) - { - SubstitutionArg adjusted (¶m_mapping, arg.get_tyty ()); - resolved_mappings.push_back (std::move (adjusted)); - } - } - - return SubstitutionArgumentMappings (resolved_mappings, - mappings.get_binding_args (), - mappings.get_locus ()); -} - -SubstitutionArgumentMappings -SubstitutionRef::solve_missing_mappings_from_this (SubstitutionRef &ref, - SubstitutionRef &to) -{ - rust_assert (!ref.needs_substitution ()); - rust_assert (needs_substitution ()); - rust_assert (get_num_substitutions () == ref.get_num_substitutions ()); - - Location locus = used_arguments.get_locus (); - std::vector resolved_mappings; - - std::map> substs; - for (size_t i = 0; i < get_num_substitutions (); i++) - { - SubstitutionParamMapping &a = substitutions.at (i); - SubstitutionParamMapping &b = ref.substitutions.at (i); - - if (a.need_substitution ()) - { - const BaseType *root = a.get_param_ty ()->resolve ()->get_root (); - rust_assert (root->get_kind () == TyTy::TypeKind::PARAM); - const ParamType *p = static_cast (root); - - substs[p->get_ty_ref ()] = {static_cast (p->clone ()), - b.get_param_ty ()->resolve ()}; - } - } - - for (auto it = substs.begin (); it != substs.end (); it++) - { - HirId param_id = it->first; - BaseType *arg = it->second.second; - - const SubstitutionParamMapping *associate_param = nullptr; - for (SubstitutionParamMapping &p : to.substitutions) - { - if (p.get_param_ty ()->get_ty_ref () == param_id) - { - associate_param = &p; - break; - } - } - - rust_assert (associate_param != nullptr); - SubstitutionArg argument (associate_param, arg); - resolved_mappings.push_back (std::move (argument)); - } - - return SubstitutionArgumentMappings (resolved_mappings, {}, locus); -} - -bool -SubstitutionRef::monomorphize () -{ - auto context = Resolver::TypeCheckContext::get (); - for (const auto &subst : get_substs ()) - { - const TyTy::ParamType *pty = subst.get_param_ty (); - - if (!pty->can_resolve ()) - continue; - - const TyTy::BaseType *binding = pty->resolve (); - if (binding->get_kind () == TyTy::TypeKind::PARAM) - continue; - - for (const auto &bound : pty->get_specified_bounds ()) - { - const Resolver::TraitReference *specified_bound_ref = bound.get (); - - // setup any associated type mappings for the specified bonds and this - // type - auto candidates = Resolver::TypeBoundsProbe::Probe (binding); - - Resolver::AssociatedImplTrait *associated_impl_trait = nullptr; - for (auto &probed_bound : candidates) - { - const Resolver::TraitReference *bound_trait_ref - = probed_bound.first; - const HIR::ImplBlock *associated_impl = probed_bound.second; - - HirId impl_block_id - = associated_impl->get_mappings ().get_hirid (); - Resolver::AssociatedImplTrait *associated = nullptr; - bool found_impl_trait - = context->lookup_associated_trait_impl (impl_block_id, - &associated); - if (found_impl_trait) - { - bool found_trait - = specified_bound_ref->is_equal (*bound_trait_ref); - bool found_self - = associated->get_self ()->can_eq (binding, false); - if (found_trait && found_self) - { - associated_impl_trait = associated; - break; - } - } - } - - if (associated_impl_trait != nullptr) - { - associated_impl_trait->setup_associated_types (binding, bound); - } - } - } - - return true; -} - void ADTType::accept_vis (TyVisitor &vis) { diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 5c564fa..a97bfb7 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -27,6 +27,7 @@ #include "rust-identifier.h" #include "rust-tyty-bounds.h" #include "rust-tyty-util.h" +#include "rust-tyty-subst.h" namespace Rust { @@ -462,469 +463,6 @@ private: std::vector fields; }; -class SubstitutionParamMapping -{ -public: - SubstitutionParamMapping (const HIR::TypeParam &generic, ParamType *param) - : generic (generic), param (param) - {} - - SubstitutionParamMapping (const SubstitutionParamMapping &other) - : generic (other.generic), param (other.param) - {} - - std::string as_string () const - { - if (param == nullptr) - return "nullptr"; - - return param->get_name (); - } - - bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings, - Location locus); - - SubstitutionParamMapping clone () const - { - return SubstitutionParamMapping (generic, static_cast ( - param->clone ())); - } - - ParamType *get_param_ty () { return param; } - - const ParamType *get_param_ty () const { return param; } - - const HIR::TypeParam &get_generic_param () { return generic; }; - - // this is used for the backend to override the HirId ref of the param to - // what the concrete type is for the rest of the context - void override_context (); - - bool needs_substitution () const - { - return !(get_param_ty ()->is_concrete ()); - } - - Location get_param_locus () const { return generic.get_locus (); } - - bool param_has_default_ty () const { return generic.has_type (); } - - BaseType *get_default_ty () const - { - TyVar var (generic.get_type_mappings ().get_hirid ()); - return var.get_tyty (); - } - - bool need_substitution () const; - -private: - const HIR::TypeParam &generic; - ParamType *param; -}; - -class SubstitutionArg -{ -public: - SubstitutionArg (const SubstitutionParamMapping *param, BaseType *argument) - : param (param), argument (argument) - {} - - // FIXME - // the copy constructors need removed - they are unsafe see - // TypeBoundPredicate - SubstitutionArg (const SubstitutionArg &other) - : param (other.param), argument (other.argument) - {} - - SubstitutionArg &operator= (const SubstitutionArg &other) - { - param = other.param; - argument = other.argument; - return *this; - } - - BaseType *get_tyty () { return argument; } - - const BaseType *get_tyty () const { return argument; } - - const SubstitutionParamMapping *get_param_mapping () const { return param; } - - static SubstitutionArg error () { return SubstitutionArg (nullptr, nullptr); } - - bool is_error () const { return param == nullptr || argument == nullptr; } - - bool is_conrete () const - { - if (argument != nullptr) - return true; - - if (argument->get_kind () == TyTy::TypeKind::PARAM) - return false; - - return argument->is_concrete (); - } - - std::string as_string () const - { - return param->as_string () - + (argument != nullptr ? ":" + argument->as_string () : ""); - } - -private: - const SubstitutionParamMapping *param; - BaseType *argument; -}; - -typedef std::function - ParamSubstCb; -class SubstitutionArgumentMappings -{ -public: - SubstitutionArgumentMappings (std::vector mappings, - std::map binding_args, - Location locus, - ParamSubstCb param_subst_cb = nullptr, - bool trait_item_flag = false) - : mappings (mappings), binding_args (binding_args), locus (locus), - param_subst_cb (param_subst_cb), trait_item_flag (trait_item_flag) - {} - - SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other) - : mappings (other.mappings), binding_args (other.binding_args), - locus (other.locus), param_subst_cb (other.param_subst_cb), - trait_item_flag (other.trait_item_flag) - {} - - SubstitutionArgumentMappings & - operator= (const SubstitutionArgumentMappings &other) - { - mappings = other.mappings; - binding_args = other.binding_args; - locus = other.locus; - param_subst_cb = other.param_subst_cb; - trait_item_flag = other.trait_item_flag; - - return *this; - } - - SubstitutionArgumentMappings (SubstitutionArgumentMappings &&other) = default; - SubstitutionArgumentMappings &operator= (SubstitutionArgumentMappings &&other) - = default; - - static SubstitutionArgumentMappings error () - { - return SubstitutionArgumentMappings ({}, {}, Location (), nullptr, false); - } - - bool is_error () const { return mappings.size () == 0; } - - bool get_argument_for_symbol (const ParamType *param_to_find, - SubstitutionArg *argument) - { - for (auto &mapping : mappings) - { - const SubstitutionParamMapping *param = mapping.get_param_mapping (); - const ParamType *p = param->get_param_ty (); - - if (p->get_symbol ().compare (param_to_find->get_symbol ()) == 0) - { - *argument = mapping; - return true; - } - } - return false; - } - - bool get_argument_at (size_t index, SubstitutionArg *argument) - { - if (index > mappings.size ()) - return false; - - *argument = mappings.at (index); - return true; - } - - // is_concrete means if the used args is non error, ie: non empty this will - // verify if actual real types have been put in place of are they still - // ParamTy - bool is_concrete () const - { - for (auto &mapping : mappings) - { - if (!mapping.is_conrete ()) - return false; - } - return true; - } - - Location get_locus () const { return locus; } - - size_t size () const { return mappings.size (); } - - bool is_empty () const { return size () == 0; } - - std::vector &get_mappings () { return mappings; } - - const std::vector &get_mappings () const { return mappings; } - - std::map &get_binding_args () - { - return binding_args; - } - - const std::map &get_binding_args () const - { - return binding_args; - } - - std::string as_string () const - { - std::string buffer; - for (auto &mapping : mappings) - { - buffer += mapping.as_string () + ", "; - } - return "<" + buffer + ">"; - } - - void on_param_subst (const ParamType &p, const SubstitutionArg &a) const - { - if (param_subst_cb == nullptr) - return; - - param_subst_cb (p, a); - } - - ParamSubstCb get_subst_cb () const { return param_subst_cb; } - - bool trait_item_mode () const { return trait_item_flag; } - -private: - std::vector mappings; - std::map binding_args; - Location locus; - ParamSubstCb param_subst_cb; - bool trait_item_flag; -}; - -class SubstitutionRef -{ -public: - SubstitutionRef (std::vector substitutions, - SubstitutionArgumentMappings arguments) - : substitutions (substitutions), used_arguments (arguments) - {} - - bool has_substitutions () const { return substitutions.size () > 0; } - - std::string subst_as_string () const - { - std::string buffer; - for (size_t i = 0; i < substitutions.size (); i++) - { - const SubstitutionParamMapping &sub = substitutions.at (i); - buffer += sub.as_string (); - - if ((i + 1) < substitutions.size ()) - buffer += ", "; - } - - return buffer.empty () ? "" : "<" + buffer + ">"; - } - - bool supports_associated_bindings () const - { - return get_num_associated_bindings () > 0; - } - - // this is overridden in TypeBoundPredicate - // which support bindings we don't add them directly to the SubstitutionRef - // base class because this class represents the fn. The only - // construct which supports associated types - virtual size_t get_num_associated_bindings () const { return 0; } - - // this is overridden in TypeBoundPredicate - virtual TypeBoundPredicateItem - lookup_associated_type (const std::string &search) - { - return TypeBoundPredicateItem::error (); - } - - size_t get_num_substitutions () const { return substitutions.size (); } - - std::vector &get_substs () { return substitutions; } - - const std::vector &get_substs () const - { - return substitutions; - } - - std::vector clone_substs () const - { - std::vector clone; - - for (auto &sub : substitutions) - clone.push_back (sub.clone ()); - - return clone; - } - - void override_context () - { - for (auto &sub : substitutions) - { - sub.override_context (); - } - } - - bool needs_substitution () const - { - for (auto &sub : substitutions) - { - if (sub.need_substitution ()) - return true; - } - return false; - } - - bool was_substituted () const { return !needs_substitution (); } - - SubstitutionArgumentMappings get_substitution_arguments () const - { - return used_arguments; - } - - // this is the count of type params that are not substituted fuly - size_t num_required_substitutions () const - { - size_t n = 0; - for (auto &p : substitutions) - { - if (p.needs_substitution ()) - n++; - } - return n; - } - - // this is the count of type params that need substituted taking into account - // possible defaults - size_t min_required_substitutions () const - { - size_t n = 0; - for (auto &p : substitutions) - { - if (p.needs_substitution () && !p.param_has_default_ty ()) - n++; - } - return n; - } - - // We are trying to subst into Struct Foo {} - // in the case of Foo{...} - // - // the substitions we have here define X,Y but the arguments have no bindings - // so its a matter of ordering - SubstitutionArgumentMappings - get_mappings_from_generic_args (HIR::GenericArgs &args); - - // Recursive substitutions - // Foo { a:A, b: B}; Bar {a:X, b: Foo} - // - // we have bindings for X Y Z and need to propagate the binding Y,Z into Foo - // Which binds to A,B - SubstitutionArgumentMappings - adjust_mappings_for_this (SubstitutionArgumentMappings &mappings); - - // Are the mappings here actually bound to this type. For example imagine the - // case: - // - // struct Foo(T); - // impl Foo { - // fn test(self) { ... } - // } - // - // In this case we have a generic ADT of Foo and an impl block of a generic T - // on Foo for the Self type. When we it comes to path resolution we can have: - // - // Foo::::test() - // - // This means the first segment of Foo:: returns the ADT Foo not the - // Self ADT bound to the T from the impl block. This means when it comes to - // the next segment of test which resolves to the function we need to check - // wether the arguments in the struct definition of foo can be bound here - // before substituting the previous segments type here. This functions acts as - // a guard for the solve_mappings_from_receiver_for_self to handle the case - // where arguments are not bound. This is important for this next case: - // - // struct Baz(A, B); - // impl Baz { - // fn test(a: X) -> X { - // a - // } - // } - // - // In this case Baz has been already substituted for the impl's Self to become - // ADT so that the function test only has 1 generic argument of X. - // The path for this will be: - // - // Baz::test::<_>(123) - // - // So the first segment here will be Baz<_, _> to try and infer the arguments - // which will be taken from the impl's Self type in this case since it is - // already substituted and like the previous case the check to see if we need - // to inherit the previous segments generic arguments takes place but the - // generic arguments are not bound to this type as they have already been - // substituted. - // - // Its important to remember from the first example the FnType actually looks - // like: - // - // fn test(self :Foo(T)) - // - // As the generic parameters are "bound" to each of the items in the impl - // block. So this check is about wether the arguments we have here can - // actually be bound to this type. - bool are_mappings_bound (SubstitutionArgumentMappings &mappings); - - // struct Foo(A, B); - // - // impl Foo; - // -> fn test(self, a: X) -> X - // - // We might invoke this via: - // - // a = Foo(123, 456f32); - // b = a.test::(false); - // - // we need to figure out relevant generic arguemts for self to apply to the - // fntype - SubstitutionArgumentMappings solve_mappings_from_receiver_for_self ( - SubstitutionArgumentMappings &mappings) const; - - // TODO comment - SubstitutionArgumentMappings - solve_missing_mappings_from_this (SubstitutionRef &ref, SubstitutionRef &to); - - // TODO comment - BaseType *infer_substitions (Location locus); - - // TODO comment - bool monomorphize (); - - // TODO comment - virtual BaseType *handle_substitions (SubstitutionArgumentMappings mappings) - = 0; - - SubstitutionArgumentMappings get_used_arguments () const - { - return used_arguments; - } - -protected: - std::vector substitutions; - SubstitutionArgumentMappings used_arguments; -}; - class TypeBoundPredicate : public SubstitutionRef { public: -- cgit v1.1 From 1cd74211cca9f5696c15d9f8b6ef4c2a2be7ea3a Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 14 Jan 2023 23:36:47 +0000 Subject: gccrs: Refactor all substitution mapper code implementation into its own CC file Signed-off-by: Philip Herron gcc/rust/ChangeLog: * typecheck/rust-substitution-mapper.cc (SubstMapper::SubstMapper): refactor (SubstMapper::Resolve): likewise (SubstMapper::InferSubst): likewise (SubstMapper::have_generic_args): likewise (SubstMapper::visit): likewise (SubstMapperInternal::visit): likewise (SubstMapperFromExisting::SubstMapperFromExisting): likewise (SubstMapperFromExisting::Resolve): likewise (SubstMapperFromExisting::visit): likewise (GetUsedSubstArgs::GetUsedSubstArgs): likewise (GetUsedSubstArgs::From): likewise (GetUsedSubstArgs::visit): likewise * typecheck/rust-substitution-mapper.h: refactor * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::get_generic_param): likewise --- gcc/rust/typecheck/rust-substitution-mapper.cc | 343 +++++++++++++++++++++++++ gcc/rust/typecheck/rust-substitution-mapper.h | 286 ++++----------------- gcc/rust/typecheck/rust-tyty-subst.cc | 2 +- 3 files changed, 387 insertions(+), 244 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc index f80368a..9ccb80b 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.cc +++ b/gcc/rust/typecheck/rust-substitution-mapper.cc @@ -22,6 +22,116 @@ namespace Rust { namespace Resolver { +SubstMapper::SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus) + : resolved (new TyTy::ErrorType (ref)), generics (generics), locus (locus) +{} + +TyTy::BaseType * +SubstMapper::Resolve (TyTy::BaseType *base, Location locus, + HIR::GenericArgs *generics) +{ + SubstMapper mapper (base->get_ref (), generics, locus); + base->accept_vis (mapper); + rust_assert (mapper.resolved != nullptr); + return mapper.resolved; +} + +TyTy::BaseType * +SubstMapper::InferSubst (TyTy::BaseType *base, Location locus) +{ + return SubstMapper::Resolve (base, locus, nullptr); +} + +bool +SubstMapper::have_generic_args () const +{ + return generics != nullptr; +} + +void +SubstMapper::visit (TyTy::FnType &type) +{ + TyTy::FnType *concrete = nullptr; + if (!have_generic_args ()) + { + TyTy::BaseType *substs = type.infer_substitions (locus); + rust_assert (substs->get_kind () == TyTy::TypeKind::FNDEF); + concrete = static_cast (substs); + } + else + { + TyTy::SubstitutionArgumentMappings mappings + = type.get_mappings_from_generic_args (*generics); + if (mappings.is_error ()) + return; + + concrete = type.handle_substitions (mappings); + } + + if (concrete != nullptr) + resolved = concrete; +} + +void +SubstMapper::visit (TyTy::ADTType &type) +{ + TyTy::ADTType *concrete = nullptr; + if (!have_generic_args ()) + { + TyTy::BaseType *substs = type.infer_substitions (locus); + rust_assert (substs->get_kind () == TyTy::TypeKind::ADT); + concrete = static_cast (substs); + } + else + { + TyTy::SubstitutionArgumentMappings mappings + = type.get_mappings_from_generic_args (*generics); + if (mappings.is_error ()) + return; + + concrete = type.handle_substitions (mappings); + } + + if (concrete != nullptr) + resolved = concrete; +} + +void +SubstMapper::visit (TyTy::PlaceholderType &type) +{ + rust_assert (type.can_resolve ()); + resolved = SubstMapper::Resolve (type.resolve (), locus, generics); +} + +void +SubstMapper::visit (TyTy::ProjectionType &type) +{ + TyTy::ProjectionType *concrete = nullptr; + if (!have_generic_args ()) + { + TyTy::BaseType *substs = type.infer_substitions (locus); + rust_assert (substs->get_kind () == TyTy::TypeKind::PROJECTION); + concrete = static_cast (substs); + } + else + { + TyTy::SubstitutionArgumentMappings mappings + = type.get_mappings_from_generic_args (*generics); + if (mappings.is_error ()) + return; + + concrete = type.handle_substitions (mappings); + } + + if (concrete != nullptr) + resolved = concrete; +} + +SubstMapperInternal::SubstMapperInternal ( + HirId ref, TyTy::SubstitutionArgumentMappings &mappings) + : resolved (new TyTy::ErrorType (ref)), mappings (mappings) +{} + TyTy::BaseType * SubstMapperInternal::Resolve (TyTy::BaseType *base, TyTy::SubstitutionArgumentMappings &mappings) @@ -73,5 +183,238 @@ SubstMapperInternal::mappings_are_bound ( return false; } +void +SubstMapperInternal::visit (TyTy::FnType &type) +{ + TyTy::SubstitutionArgumentMappings adjusted + = type.adjust_mappings_for_this (mappings); + if (adjusted.is_error ()) + return; + + TyTy::BaseType *concrete = type.handle_substitions (adjusted); + if (concrete != nullptr) + resolved = concrete; +} + +void +SubstMapperInternal::visit (TyTy::ADTType &type) +{ + TyTy::SubstitutionArgumentMappings adjusted + = type.adjust_mappings_for_this (mappings); + if (adjusted.is_error ()) + return; + + TyTy::BaseType *concrete = type.handle_substitions (adjusted); + if (concrete != nullptr) + resolved = concrete; +} + +// these don't support generic arguments but might contain a type param +void +SubstMapperInternal::visit (TyTy::TupleType &type) +{ + resolved = type.handle_substitions (mappings); +} + +void +SubstMapperInternal::visit (TyTy::ReferenceType &type) +{ + resolved = type.handle_substitions (mappings); +} + +void +SubstMapperInternal::visit (TyTy::PointerType &type) +{ + resolved = type.handle_substitions (mappings); +} + +void +SubstMapperInternal::visit (TyTy::ParamType &type) +{ + resolved = type.handle_substitions (mappings); +} + +void +SubstMapperInternal::visit (TyTy::PlaceholderType &type) +{ + rust_assert (type.can_resolve ()); + if (mappings.trait_item_mode ()) + { + resolved = type.resolve (); + } + else + { + resolved = SubstMapperInternal::Resolve (type.resolve (), mappings); + } +} + +void +SubstMapperInternal::visit (TyTy::ProjectionType &type) +{ + resolved = type.handle_substitions (mappings); +} + +void +SubstMapperInternal::visit (TyTy::ClosureType &type) +{ + resolved = type.handle_substitions (mappings); +} + +void +SubstMapperInternal::visit (TyTy::ArrayType &type) +{ + resolved = type.handle_substitions (mappings); +} + +void +SubstMapperInternal::visit (TyTy::SliceType &type) +{ + resolved = type.handle_substitions (mappings); +} + +// nothing to do for these +void +SubstMapperInternal::visit (TyTy::InferType &type) +{ + resolved = type.clone (); +} +void +SubstMapperInternal::visit (TyTy::FnPtr &type) +{ + resolved = type.clone (); +} +void +SubstMapperInternal::visit (TyTy::BoolType &type) +{ + resolved = type.clone (); +} +void +SubstMapperInternal::visit (TyTy::IntType &type) +{ + resolved = type.clone (); +} +void +SubstMapperInternal::visit (TyTy::UintType &type) +{ + resolved = type.clone (); +} +void +SubstMapperInternal::visit (TyTy::FloatType &type) +{ + resolved = type.clone (); +} +void +SubstMapperInternal::visit (TyTy::USizeType &type) +{ + resolved = type.clone (); +} +void +SubstMapperInternal::visit (TyTy::ISizeType &type) +{ + resolved = type.clone (); +} +void +SubstMapperInternal::visit (TyTy::ErrorType &type) +{ + resolved = type.clone (); +} +void +SubstMapperInternal::visit (TyTy::CharType &type) +{ + resolved = type.clone (); +} +void +SubstMapperInternal::visit (TyTy::StrType &type) +{ + resolved = type.clone (); +} +void +SubstMapperInternal::visit (TyTy::NeverType &type) +{ + resolved = type.clone (); +} +void +SubstMapperInternal::visit (TyTy::DynamicObjectType &type) +{ + resolved = type.clone (); +} + +// SubstMapperFromExisting + +SubstMapperFromExisting::SubstMapperFromExisting (TyTy::BaseType *concrete, + TyTy::BaseType *receiver) + : concrete (concrete), receiver (receiver), resolved (nullptr) +{} + +TyTy::BaseType * +SubstMapperFromExisting::Resolve (TyTy::BaseType *concrete, + TyTy::BaseType *receiver) +{ + rust_assert (concrete->get_kind () == receiver->get_kind ()); + + SubstMapperFromExisting mapper (concrete, receiver); + concrete->accept_vis (mapper); + return mapper.resolved; +} + +void +SubstMapperFromExisting::visit (TyTy::FnType &type) +{ + rust_assert (type.was_substituted ()); + + TyTy::FnType *to_sub = static_cast (receiver); + resolved = to_sub->handle_substitions (type.get_substitution_arguments ()); +} + +void +SubstMapperFromExisting::visit (TyTy::ADTType &type) +{ + rust_assert (type.was_substituted ()); + + TyTy::ADTType *to_sub = static_cast (receiver); + resolved = to_sub->handle_substitions (type.get_substitution_arguments ()); +} + +void +SubstMapperFromExisting::visit (TyTy::ClosureType &type) +{ + rust_assert (type.was_substituted ()); + + TyTy::ClosureType *to_sub = static_cast (receiver); + resolved = to_sub->handle_substitions (type.get_substitution_arguments ()); +} + +// GetUsedSubstArgs + +GetUsedSubstArgs::GetUsedSubstArgs () + : args (TyTy::SubstitutionArgumentMappings::error ()) +{} + +TyTy::SubstitutionArgumentMappings +GetUsedSubstArgs::From (const TyTy::BaseType *from) +{ + GetUsedSubstArgs mapper; + from->accept_vis (mapper); + return mapper.args; +} + +void +GetUsedSubstArgs::visit (const TyTy::FnType &type) +{ + args = type.get_substitution_arguments (); +} + +void +GetUsedSubstArgs::visit (const TyTy::ADTType &type) +{ + args = type.get_substitution_arguments (); +} + +void +GetUsedSubstArgs::visit (const TyTy::ClosureType &type) +{ + args = type.get_substitution_arguments (); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h index e326bbd..047034e 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.h +++ b/gcc/rust/typecheck/rust-substitution-mapper.h @@ -29,95 +29,16 @@ class SubstMapper : public TyTy::TyVisitor { public: static TyTy::BaseType *Resolve (TyTy::BaseType *base, Location locus, - HIR::GenericArgs *generics = nullptr) - { - SubstMapper mapper (base->get_ref (), generics, locus); - base->accept_vis (mapper); - rust_assert (mapper.resolved != nullptr); - return mapper.resolved; - } + HIR::GenericArgs *generics = nullptr); - static TyTy::BaseType *InferSubst (TyTy::BaseType *base, Location locus) - { - return SubstMapper::Resolve (base, locus, nullptr); - } + static TyTy::BaseType *InferSubst (TyTy::BaseType *base, Location locus); - bool have_generic_args () const { return generics != nullptr; } + bool have_generic_args () const; - void visit (TyTy::FnType &type) override - { - TyTy::FnType *concrete = nullptr; - if (!have_generic_args ()) - { - TyTy::BaseType *substs = type.infer_substitions (locus); - rust_assert (substs->get_kind () == TyTy::TypeKind::FNDEF); - concrete = static_cast (substs); - } - else - { - TyTy::SubstitutionArgumentMappings mappings - = type.get_mappings_from_generic_args (*generics); - if (mappings.is_error ()) - return; - - concrete = type.handle_substitions (mappings); - } - - if (concrete != nullptr) - resolved = concrete; - } - - void visit (TyTy::ADTType &type) override - { - TyTy::ADTType *concrete = nullptr; - if (!have_generic_args ()) - { - TyTy::BaseType *substs = type.infer_substitions (locus); - rust_assert (substs->get_kind () == TyTy::TypeKind::ADT); - concrete = static_cast (substs); - } - else - { - TyTy::SubstitutionArgumentMappings mappings - = type.get_mappings_from_generic_args (*generics); - if (mappings.is_error ()) - return; - - concrete = type.handle_substitions (mappings); - } - - if (concrete != nullptr) - resolved = concrete; - } - - void visit (TyTy::PlaceholderType &type) override - { - rust_assert (type.can_resolve ()); - resolved = SubstMapper::Resolve (type.resolve (), locus, generics); - } - - void visit (TyTy::ProjectionType &type) override - { - TyTy::ProjectionType *concrete = nullptr; - if (!have_generic_args ()) - { - TyTy::BaseType *substs = type.infer_substitions (locus); - rust_assert (substs->get_kind () == TyTy::TypeKind::PROJECTION); - concrete = static_cast (substs); - } - else - { - TyTy::SubstitutionArgumentMappings mappings - = type.get_mappings_from_generic_args (*generics); - if (mappings.is_error ()) - return; - - concrete = type.handle_substitions (mappings); - } - - if (concrete != nullptr) - resolved = concrete; - } + void visit (TyTy::FnType &type) override; + void visit (TyTy::ADTType &type) override; + void visit (TyTy::PlaceholderType &type) override; + void visit (TyTy::ProjectionType &type) override; // nothing to do for these void visit (TyTy::InferType &) override { gcc_unreachable (); } @@ -142,9 +63,7 @@ public: void visit (TyTy::ClosureType &) override { gcc_unreachable (); } private: - SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus) - : resolved (new TyTy::ErrorType (ref)), generics (generics), locus (locus) - {} + SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus); TyTy::BaseType *resolved; HIR::GenericArgs *generics; @@ -160,106 +79,33 @@ public: static bool mappings_are_bound (TyTy::BaseType *ty, TyTy::SubstitutionArgumentMappings &mappings); - void visit (TyTy::FnType &type) override - { - TyTy::SubstitutionArgumentMappings adjusted - = type.adjust_mappings_for_this (mappings); - if (adjusted.is_error ()) - return; - - TyTy::BaseType *concrete = type.handle_substitions (adjusted); - if (concrete != nullptr) - resolved = concrete; - } - - void visit (TyTy::ADTType &type) override - { - TyTy::SubstitutionArgumentMappings adjusted - = type.adjust_mappings_for_this (mappings); - if (adjusted.is_error ()) - return; - - TyTy::BaseType *concrete = type.handle_substitions (adjusted); - if (concrete != nullptr) - resolved = concrete; - } - - // these don't support generic arguments but might contain a type param - void visit (TyTy::TupleType &type) override - { - resolved = type.handle_substitions (mappings); - } - - void visit (TyTy::ReferenceType &type) override - { - resolved = type.handle_substitions (mappings); - } - - void visit (TyTy::PointerType &type) override - { - resolved = type.handle_substitions (mappings); - } - - void visit (TyTy::ParamType &type) override - { - resolved = type.handle_substitions (mappings); - } - - void visit (TyTy::PlaceholderType &type) override - { - rust_assert (type.can_resolve ()); - if (mappings.trait_item_mode ()) - { - resolved = type.resolve (); - } - else - { - resolved = SubstMapperInternal::Resolve (type.resolve (), mappings); - } - } - - void visit (TyTy::ProjectionType &type) override - { - resolved = type.handle_substitions (mappings); - } - - void visit (TyTy::ClosureType &type) override - { - resolved = type.handle_substitions (mappings); - } - - void visit (TyTy::ArrayType &type) override - { - resolved = type.handle_substitions (mappings); - } - - void visit (TyTy::SliceType &type) override - { - resolved = type.handle_substitions (mappings); - } - - // nothing to do for these - void visit (TyTy::InferType &type) override { resolved = type.clone (); } - void visit (TyTy::FnPtr &type) override { resolved = type.clone (); } - void visit (TyTy::BoolType &type) override { resolved = type.clone (); } - void visit (TyTy::IntType &type) override { resolved = type.clone (); } - void visit (TyTy::UintType &type) override { resolved = type.clone (); } - void visit (TyTy::FloatType &type) override { resolved = type.clone (); } - void visit (TyTy::USizeType &type) override { resolved = type.clone (); } - void visit (TyTy::ISizeType &type) override { resolved = type.clone (); } - void visit (TyTy::ErrorType &type) override { resolved = type.clone (); } - void visit (TyTy::CharType &type) override { resolved = type.clone (); } - void visit (TyTy::StrType &type) override { resolved = type.clone (); } - void visit (TyTy::NeverType &type) override { resolved = type.clone (); } - void visit (TyTy::DynamicObjectType &type) override - { - resolved = type.clone (); - } + void visit (TyTy::FnType &type) override; + void visit (TyTy::ADTType &type) override; + void visit (TyTy::TupleType &type) override; + void visit (TyTy::ReferenceType &type) override; + void visit (TyTy::PointerType &type) override; + void visit (TyTy::ParamType &type) override; + void visit (TyTy::PlaceholderType &type) override; + void visit (TyTy::ProjectionType &type) override; + void visit (TyTy::ClosureType &type) override; + void visit (TyTy::ArrayType &type) override; + void visit (TyTy::SliceType &type) override; + void visit (TyTy::InferType &type) override; + void visit (TyTy::FnPtr &type) override; + void visit (TyTy::BoolType &type) override; + void visit (TyTy::IntType &type) override; + void visit (TyTy::UintType &type) override; + void visit (TyTy::FloatType &type) override; + void visit (TyTy::USizeType &type) override; + void visit (TyTy::ISizeType &type) override; + void visit (TyTy::ErrorType &type) override; + void visit (TyTy::CharType &type) override; + void visit (TyTy::StrType &type) override; + void visit (TyTy::NeverType &type) override; + void visit (TyTy::DynamicObjectType &type) override; private: - SubstMapperInternal (HirId ref, TyTy::SubstitutionArgumentMappings &mappings) - : resolved (new TyTy::ErrorType (ref)), mappings (mappings) - {} + SubstMapperInternal (HirId ref, TyTy::SubstitutionArgumentMappings &mappings); TyTy::BaseType *resolved; TyTy::SubstitutionArgumentMappings &mappings; @@ -269,38 +115,11 @@ class SubstMapperFromExisting : public TyTy::TyVisitor { public: static TyTy::BaseType *Resolve (TyTy::BaseType *concrete, - TyTy::BaseType *receiver) - { - rust_assert (concrete->get_kind () == receiver->get_kind ()); - - SubstMapperFromExisting mapper (concrete, receiver); - concrete->accept_vis (mapper); - return mapper.resolved; - } + TyTy::BaseType *receiver); - void visit (TyTy::FnType &type) override - { - rust_assert (type.was_substituted ()); - - TyTy::FnType *to_sub = static_cast (receiver); - resolved = to_sub->handle_substitions (type.get_substitution_arguments ()); - } - - void visit (TyTy::ADTType &type) override - { - rust_assert (type.was_substituted ()); - - TyTy::ADTType *to_sub = static_cast (receiver); - resolved = to_sub->handle_substitions (type.get_substitution_arguments ()); - } - - void visit (TyTy::ClosureType &type) override - { - rust_assert (type.was_substituted ()); - - TyTy::ClosureType *to_sub = static_cast (receiver); - resolved = to_sub->handle_substitions (type.get_substitution_arguments ()); - } + void visit (TyTy::FnType &type) override; + void visit (TyTy::ADTType &type) override; + void visit (TyTy::ClosureType &type) override; void visit (TyTy::InferType &) override { gcc_unreachable (); } void visit (TyTy::TupleType &) override { gcc_unreachable (); } @@ -325,40 +144,21 @@ public: void visit (TyTy::DynamicObjectType &) override { gcc_unreachable (); } private: - SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver) - : concrete (concrete), receiver (receiver), resolved (nullptr) - {} + SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver); TyTy::BaseType *concrete; TyTy::BaseType *receiver; - TyTy::BaseType *resolved; }; class GetUsedSubstArgs : public TyTy::TyConstVisitor { public: - static TyTy::SubstitutionArgumentMappings From (const TyTy::BaseType *from) - { - GetUsedSubstArgs mapper; - from->accept_vis (mapper); - return mapper.args; - } - - void visit (const TyTy::FnType &type) override - { - args = type.get_substitution_arguments (); - } - - void visit (const TyTy::ADTType &type) override - { - args = type.get_substitution_arguments (); - } + static TyTy::SubstitutionArgumentMappings From (const TyTy::BaseType *from); - void visit (const TyTy::ClosureType &type) override - { - args = type.get_substitution_arguments (); - } + void visit (const TyTy::FnType &type) override; + void visit (const TyTy::ADTType &type) override; + void visit (const TyTy::ClosureType &type) override; void visit (const TyTy::InferType &) override {} void visit (const TyTy::TupleType &) override {} @@ -383,7 +183,7 @@ public: void visit (const TyTy::DynamicObjectType &) override {} private: - GetUsedSubstArgs () : args (TyTy::SubstitutionArgumentMappings::error ()) {} + GetUsedSubstArgs (); TyTy::SubstitutionArgumentMappings args; }; diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc index 6400145..aceed29 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.cc +++ b/gcc/rust/typecheck/rust-tyty-subst.cc @@ -68,7 +68,7 @@ const HIR::TypeParam & SubstitutionParamMapping::get_generic_param () { return generic; -}; +} bool SubstitutionParamMapping::needs_substitution () const -- cgit v1.1 From 725a25a197917d6fd5e1e95937990fc71e48c739 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 14 Jan 2023 23:54:19 +0000 Subject: gccrs: Refactor BaseType, InferType and ErrorType impl into cc file Signed-off-by: Philip Herron gcc/rust/ChangeLog: * typecheck/rust-tyty.cc (BaseType::BaseType): refactor (BaseType::~BaseType): likewise (BaseType::get_ref): likewise (BaseType::set_ref): likewise (BaseType::get_ty_ref): likewise (BaseType::set_ty_ref): likewise (BaseType::is_equal): likewise (BaseType::is_unit): likewise (BaseType::get_kind): likewise (BaseType::get_combined_refs): likewise (BaseType::append_reference): likewise (BaseType::supports_substitutions): likewise (BaseType::has_subsititions_defined): likewise (BaseType::can_substitute): likewise (BaseType::needs_generic_substitutions): likewise (BaseType::contains_type_parameters): likewise (BaseType::get_ident): likewise (BaseType::get_locus): likewise (InferType::InferType): likewise (InferType::get_infer_kind): likewise (InferType::get_name): likewise (InferType::is_concrete): likewise (ErrorType::ErrorType): likewise (ErrorType::is_unit): likewise (ErrorType::is_concrete): likewise (ErrorType::get_name): likewise (ErrorType::monomorphized_clone): likewise * typecheck/rust-tyty.h (class SubstitutionArgumentMappings): likewise --- gcc/rust/typecheck/rust-tyty.cc | 181 ++++++++++++++++++++++++++++++++++++++++ gcc/rust/typecheck/rust-tyty.h | 92 +++++++------------- 2 files changed, 211 insertions(+), 62 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 7b86112..86d19ee 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -146,6 +146,122 @@ is_primitive_type_kind (TypeKind kind) } } +// BASE TYPE + +BaseType::BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident, + std::set refs) + : TypeBoundsMappings ({}), kind (kind), ref (ref), ty_ref (ty_ref), + combined (refs), ident (ident), mappings (Analysis::Mappings::get ()) +{} + +BaseType::BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident, + std::vector specified_bounds, + std::set refs) + : TypeBoundsMappings (specified_bounds), kind (kind), ref (ref), + ty_ref (ty_ref), combined (refs), ident (ident), + mappings (Analysis::Mappings::get ()) +{} + +BaseType::~BaseType () {} + +HirId +BaseType::get_ref () const +{ + return ref; +} + +void +BaseType::set_ref (HirId id) +{ + if (id != ref) + append_reference (ref); + ref = id; +} + +HirId +BaseType::get_ty_ref () const +{ + return ty_ref; +} + +void +BaseType::set_ty_ref (HirId id) +{ + ty_ref = id; +} + +bool +BaseType::is_equal (const BaseType &other) const +{ + return get_kind () == other.get_kind (); +} + +bool +BaseType::is_unit () const +{ + return false; +} + +TypeKind +BaseType::get_kind () const +{ + return kind; +} + +std::set +BaseType::get_combined_refs () const +{ + return combined; +} + +void +BaseType::append_reference (HirId id) +{ + combined.insert (id); +} + +bool +BaseType::supports_substitutions () const +{ + return false; +} + +bool +BaseType::has_subsititions_defined () const +{ + return false; +} + +bool +BaseType::can_substitute () const +{ + return supports_substitutions () && has_subsititions_defined (); +} + +bool +BaseType::needs_generic_substitutions () const +{ + return false; +} + +bool +BaseType::contains_type_parameters () const +{ + return !is_concrete (); +} + +const RustIdent & +BaseType::get_ident () const +{ + return ident; +} + +Location +BaseType::get_locus () const +{ + return ident.locus; +} + bool BaseType::satisfies_bound (const TypeBoundPredicate &predicate) const { @@ -330,6 +446,40 @@ BaseType::debug () const debug_str ().c_str ()); } +// InferType + +InferType::InferType (HirId ref, InferTypeKind infer_kind, Location locus, + std::set refs) + : BaseType (ref, ref, TypeKind::INFER, + {Resolver::CanonicalPath::create_empty (), locus}, refs), + infer_kind (infer_kind) +{} + +InferType::InferType (HirId ref, HirId ty_ref, InferTypeKind infer_kind, + Location locus, std::set refs) + : BaseType (ref, ty_ref, TypeKind::INFER, + {Resolver::CanonicalPath::create_empty (), locus}, refs), + infer_kind (infer_kind) +{} + +InferType::InferTypeKind +InferType::get_infer_kind () const +{ + return infer_kind; +} + +std::string +InferType::get_name () const +{ + return as_string (); +} + +bool +InferType::is_concrete () const +{ + return true; +} + void InferType::accept_vis (TyVisitor &vis) { @@ -435,6 +585,35 @@ InferType::default_type (BaseType **type) const return false; } +// ErrorType + +ErrorType::ErrorType (HirId ref, std::set refs) + : BaseType (ref, ref, TypeKind::ERROR, + {Resolver::CanonicalPath::create_empty (), Location ()}, refs) +{} + +ErrorType::ErrorType (HirId ref, HirId ty_ref, std::set refs) + : BaseType (ref, ty_ref, TypeKind::ERROR, + {Resolver::CanonicalPath::create_empty (), Location ()}, refs) +{} + +bool +ErrorType::is_unit () const +{ + return true; +} +bool +ErrorType::is_concrete () const +{ + return false; +} + +std::string +ErrorType::get_name () const +{ + return as_string (); +} + void ErrorType::accept_vis (TyVisitor &vis) { @@ -477,6 +656,8 @@ ErrorType::monomorphized_clone () const return clone (); } +// Struct Field type + std::string StructFieldType::as_string () const { diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index a97bfb7..48058ba 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -89,20 +89,15 @@ class TyConstVisitor; class BaseType : public TypeBoundsMappings { public: - virtual ~BaseType () {} + virtual ~BaseType (); - HirId get_ref () const { return ref; } + HirId get_ref () const; - void set_ref (HirId id) - { - if (id != ref) - append_reference (ref); - ref = id; - } + void set_ref (HirId id); - HirId get_ty_ref () const { return ty_ref; } + HirId get_ty_ref () const; - void set_ty_ref (HirId id) { ty_ref = id; } + void set_ty_ref (HirId id); virtual void accept_vis (TyVisitor &vis) = 0; @@ -133,10 +128,7 @@ public: // ty are considered equal if they're of the same kind, and // 1. (For ADTs, arrays, tuples, refs) have the same underlying ty // 2. (For functions) have the same signature - virtual bool is_equal (const BaseType &other) const - { - return get_kind () == other.get_kind (); - } + virtual bool is_equal (const BaseType &other) const; bool satisfies_bound (const TypeBoundPredicate &predicate) const; @@ -148,11 +140,11 @@ public: void inherit_bounds ( const std::vector &specified_bounds); - virtual bool is_unit () const { return false; } + virtual bool is_unit () const; virtual bool is_concrete () const = 0; - TypeKind get_kind () const { return kind; } + TypeKind get_kind () const; /* Returns a pointer to a clone of this. The caller is responsible for * releasing the memory of the returned ty. */ @@ -162,22 +154,19 @@ public: virtual BaseType *monomorphized_clone () const = 0; // get_combined_refs returns the chain of node refs involved in unification - std::set get_combined_refs () const { return combined; } + std::set get_combined_refs () const; - void append_reference (HirId id) { combined.insert (id); } + void append_reference (HirId id); - virtual bool supports_substitutions () const { return false; } + virtual bool supports_substitutions () const; - virtual bool has_subsititions_defined () const { return false; } + virtual bool has_subsititions_defined () const; - virtual bool can_substitute () const - { - return supports_substitutions () && has_subsititions_defined (); - } + virtual bool can_substitute () const; - virtual bool needs_generic_substitutions () const { return false; } + virtual bool needs_generic_substitutions () const; - bool contains_type_parameters () const { return !is_concrete (); } + bool contains_type_parameters () const; std::string mappings_str () const; @@ -192,24 +181,17 @@ public: // Projections if available or error const BaseType *destructure () const; - const RustIdent &get_ident () const { return ident; } + const RustIdent &get_ident () const; - Location get_locus () const { return ident.locus; } + Location get_locus () const; protected: BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident, - std::set refs = std::set ()) - : TypeBoundsMappings ({}), kind (kind), ref (ref), ty_ref (ty_ref), - combined (refs), ident (ident), mappings (Analysis::Mappings::get ()) - {} + std::set refs = std::set ()); BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident, std::vector specified_bounds, - std::set refs = std::set ()) - : TypeBoundsMappings (specified_bounds), kind (kind), ref (ref), - ty_ref (ty_ref), combined (refs), ident (ident), - mappings (Analysis::Mappings::get ()) - {} + std::set refs = std::set ()); TypeKind kind; HirId ref; @@ -231,18 +213,10 @@ public: }; InferType (HirId ref, InferTypeKind infer_kind, Location locus, - std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::INFER, - {Resolver::CanonicalPath::create_empty (), locus}, refs), - infer_kind (infer_kind) - {} + std::set refs = std::set ()); InferType (HirId ref, HirId ty_ref, InferTypeKind infer_kind, Location locus, - std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::INFER, - {Resolver::CanonicalPath::create_empty (), locus}, refs), - infer_kind (infer_kind) - {} + std::set refs = std::set ()); void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; @@ -256,13 +230,13 @@ public: BaseType *clone () const final override; BaseType *monomorphized_clone () const final override; - InferTypeKind get_infer_kind () const { return infer_kind; } + InferTypeKind get_infer_kind () const; - std::string get_name () const override final { return as_string (); } + std::string get_name () const override final; bool default_type (BaseType **type) const; - bool is_concrete () const final override { return true; } + bool is_concrete () const final override; private: InferTypeKind infer_kind; @@ -271,20 +245,15 @@ private: class ErrorType : public BaseType { public: - ErrorType (HirId ref, std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::ERROR, - {Resolver::CanonicalPath::create_empty (), Location ()}, refs) - {} + ErrorType (HirId ref, std::set refs = std::set ()); - ErrorType (HirId ref, HirId ty_ref, std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::ERROR, - {Resolver::CanonicalPath::create_empty (), Location ()}, refs) - {} + ErrorType (HirId ref, HirId ty_ref, + std::set refs = std::set ()); void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; - bool is_unit () const override { return true; } + bool is_unit () const override; std::string as_string () const override; @@ -294,12 +263,11 @@ public: BaseType *clone () const final override; BaseType *monomorphized_clone () const final override; - std::string get_name () const override final { return as_string (); } + std::string get_name () const override final; - bool is_concrete () const final override { return false; } + bool is_concrete () const final override; }; -class SubstitutionArgumentMappings; class ParamType : public BaseType { public: -- cgit v1.1 From 3e044eb0d53b5fb66cf683e0a86706ce68eec2f1 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 16 Jan 2023 17:08:14 +0000 Subject: gccrs: Refactor PathProbe into cc file Signed-off-by: Philip Herron gcc/rust/ChangeLog: * typecheck/rust-hir-path-probe.cc (PathProbeType::PathProbeType): refactor (PathProbeType::Probe): likewise (PathProbeType::visit): likewise (PathProbeType::process_enum_item_for_candiates): likewise (PathProbeType::process_impl_items_for_candidates): likewise (PathProbeType::is_reciever_generic): likewise (PathProbeImplTrait::PathProbeImplTrait): likewise (PathProbeImplTrait::Probe): likewise (PathProbeImplTrait::process_trait_impl_items_for_candidates): likewise * typecheck/rust-hir-path-probe.h (struct PathProbeCandidate): likewise * typecheck/rust-hir-trait-resolve.cc (PathProbeImplTrait::process_trait_impl_items_for_candidates): likewise --- gcc/rust/typecheck/rust-hir-path-probe.cc | 344 +++++++++++++++++++++++++++ gcc/rust/typecheck/rust-hir-path-probe.h | 302 ++--------------------- gcc/rust/typecheck/rust-hir-trait-resolve.cc | 22 -- 3 files changed, 360 insertions(+), 308 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-hir-path-probe.cc b/gcc/rust/typecheck/rust-hir-path-probe.cc index cb3270d..06d8920 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.cc +++ b/gcc/rust/typecheck/rust-hir-path-probe.cc @@ -18,10 +18,168 @@ #include "rust-hir-path-probe.h" #include "rust-hir-type-check-item.h" +#include "rust-hir-trait-resolve.h" namespace Rust { namespace Resolver { +// PathProbeType + +PathProbeType::PathProbeType (const TyTy::BaseType *receiver, + const HIR::PathIdentSegment &query, + DefId specific_trait_id) + : TypeCheckBase (), receiver (receiver), search (query), + current_impl (nullptr), specific_trait_id (specific_trait_id) +{} + +std::set +PathProbeType::Probe (const TyTy::BaseType *receiver, + const HIR::PathIdentSegment &segment_name, + bool probe_impls, bool probe_bounds, + bool ignore_mandatory_trait_items, + DefId specific_trait_id) +{ + PathProbeType probe (receiver, segment_name, specific_trait_id); + if (probe_impls) + { + if (receiver->get_kind () == TyTy::TypeKind::ADT) + { + const TyTy::ADTType *adt + = static_cast (receiver); + if (adt->is_enum ()) + probe.process_enum_item_for_candiates (adt); + } + + probe.process_impl_items_for_candidates (); + } + + if (!probe_bounds) + return probe.candidates; + + if (!probe.is_reciever_generic ()) + { + std::vector> probed_bounds + = TypeBoundsProbe::Probe (receiver); + for (auto &candidate : probed_bounds) + { + const TraitReference *trait_ref = candidate.first; + if (specific_trait_id != UNKNOWN_DEFID) + { + if (trait_ref->get_mappings ().get_defid () != specific_trait_id) + continue; + } + + HIR::ImplBlock *impl = candidate.second; + probe.process_associated_trait_for_candidates ( + trait_ref, impl, ignore_mandatory_trait_items); + } + } + + for (const TyTy::TypeBoundPredicate &predicate : + receiver->get_specified_bounds ()) + { + const TraitReference *trait_ref = predicate.get (); + if (specific_trait_id != UNKNOWN_DEFID) + { + if (trait_ref->get_mappings ().get_defid () != specific_trait_id) + continue; + } + + probe.process_predicate_for_candidates (predicate, + ignore_mandatory_trait_items); + } + + return probe.candidates; +} + +void +PathProbeType::visit (HIR::TypeAlias &alias) +{ + Identifier name = alias.get_new_type_name (); + if (search.as_string ().compare (name) == 0) + { + HirId tyid = alias.get_mappings ().get_hirid (); + TyTy::BaseType *ty = nullptr; + bool ok = query_type (tyid, &ty); + rust_assert (ok); + + PathProbeCandidate::ImplItemCandidate impl_item_candidate{&alias, + current_impl}; + PathProbeCandidate candidate{ + PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS, ty, + alias.get_locus (), impl_item_candidate}; + candidates.insert (std::move (candidate)); + } +} + +void +PathProbeType::visit (HIR::ConstantItem &constant) +{ + Identifier name = constant.get_identifier (); + if (search.as_string ().compare (name) == 0) + { + HirId tyid = constant.get_mappings ().get_hirid (); + TyTy::BaseType *ty = nullptr; + bool ok = query_type (tyid, &ty); + rust_assert (ok); + + PathProbeCandidate::ImplItemCandidate impl_item_candidate{&constant, + current_impl}; + PathProbeCandidate candidate{ + PathProbeCandidate::CandidateType::IMPL_CONST, ty, + constant.get_locus (), impl_item_candidate}; + candidates.insert (std::move (candidate)); + } +} + +void +PathProbeType::visit (HIR::Function &function) +{ + Identifier name = function.get_function_name (); + if (search.as_string ().compare (name) == 0) + { + HirId tyid = function.get_mappings ().get_hirid (); + TyTy::BaseType *ty = nullptr; + bool ok = query_type (tyid, &ty); + rust_assert (ok); + + PathProbeCandidate::ImplItemCandidate impl_item_candidate{&function, + current_impl}; + PathProbeCandidate candidate{PathProbeCandidate::CandidateType::IMPL_FUNC, + ty, function.get_locus (), + impl_item_candidate}; + candidates.insert (std::move (candidate)); + } +} + +void +PathProbeType::process_enum_item_for_candiates (const TyTy::ADTType *adt) +{ + if (specific_trait_id != UNKNOWN_DEFID) + return; + + TyTy::VariantDef *v; + if (!adt->lookup_variant (search.as_string (), &v)) + return; + + PathProbeCandidate::EnumItemCandidate enum_item_candidate{adt, v}; + PathProbeCandidate candidate{PathProbeCandidate::CandidateType::ENUM_VARIANT, + receiver->clone (), + mappings->lookup_location (adt->get_ty_ref ()), + enum_item_candidate}; + candidates.insert (std::move (candidate)); +} + +void +PathProbeType::process_impl_items_for_candidates () +{ + mappings->iterate_impl_items ( + [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool { + process_impl_item_candidate (id, item, impl); + return true; + }); +} + void PathProbeType::process_impl_item_candidate (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) @@ -42,5 +200,191 @@ PathProbeType::process_impl_item_candidate (HirId id, HIR::ImplItem *item, item->accept_vis (*this); } +void +PathProbeType::process_associated_trait_for_candidates ( + const TraitReference *trait_ref, HIR::ImplBlock *impl, + bool ignore_mandatory_trait_items) +{ + const TraitItemReference *trait_item_ref = nullptr; + if (!trait_ref->lookup_trait_item (search.as_string (), &trait_item_ref)) + return; + + bool trait_item_needs_implementation = !trait_item_ref->is_optional (); + if (ignore_mandatory_trait_items && trait_item_needs_implementation) + return; + + PathProbeCandidate::CandidateType candidate_type; + switch (trait_item_ref->get_trait_item_type ()) + { + case TraitItemReference::TraitItemType::FN: + candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC; + break; + case TraitItemReference::TraitItemType::CONST: + candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST; + break; + case TraitItemReference::TraitItemType::TYPE: + candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS; + break; + + case TraitItemReference::TraitItemType::ERROR: + default: + gcc_unreachable (); + break; + } + + TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty (); + + // we can substitute the Self with the receiver here + if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF) + { + TyTy::FnType *fn = static_cast (trait_item_tyty); + TyTy::SubstitutionParamMapping *param = nullptr; + for (auto ¶m_mapping : fn->get_substs ()) + { + const HIR::TypeParam &type_param = param_mapping.get_generic_param (); + if (type_param.get_type_representation ().compare ("Self") == 0) + { + param = ¶m_mapping; + break; + } + } + rust_assert (param != nullptr); + + std::vector mappings; + mappings.push_back (TyTy::SubstitutionArg (param, receiver->clone ())); + + Location locus; // FIXME + TyTy::SubstitutionArgumentMappings args (std::move (mappings), {}, locus); + trait_item_tyty = SubstMapperInternal::Resolve (trait_item_tyty, args); + } + + PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref, + trait_item_ref, + impl}; + + PathProbeCandidate candidate{candidate_type, trait_item_tyty, + trait_item_ref->get_locus (), + trait_item_candidate}; + candidates.insert (std::move (candidate)); +} + +void +PathProbeType::process_predicate_for_candidates ( + const TyTy::TypeBoundPredicate &predicate, bool ignore_mandatory_trait_items) +{ + const TraitReference *trait_ref = predicate.get (); + + TyTy::TypeBoundPredicateItem item + = predicate.lookup_associated_item (search.as_string ()); + if (item.is_error ()) + return; + + if (ignore_mandatory_trait_items && item.needs_implementation ()) + return; + + const TraitItemReference *trait_item_ref = item.get_raw_item (); + PathProbeCandidate::CandidateType candidate_type; + switch (trait_item_ref->get_trait_item_type ()) + { + case TraitItemReference::TraitItemType::FN: + candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC; + break; + case TraitItemReference::TraitItemType::CONST: + candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST; + break; + case TraitItemReference::TraitItemType::TYPE: + candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS; + break; + + case TraitItemReference::TraitItemType::ERROR: + default: + gcc_unreachable (); + break; + } + + TyTy::BaseType *trait_item_tyty = item.get_tyty_for_receiver (receiver); + PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref, + trait_item_ref, + nullptr}; + PathProbeCandidate candidate{candidate_type, trait_item_tyty, + trait_item_ref->get_locus (), + trait_item_candidate}; + candidates.insert (std::move (candidate)); +} + +std::vector> +PathProbeType::union_bounds ( + const std::vector> a, + const std::vector> b) + const +{ + std::map> mapper; + for (auto &ref : a) + { + mapper.insert ({ref.first->get_mappings ().get_defid (), ref}); + } + for (auto &ref : b) + { + mapper.insert ({ref.first->get_mappings ().get_defid (), ref}); + } + + std::vector> union_set; + for (auto it = mapper.begin (); it != mapper.end (); it++) + { + union_set.push_back ({it->second.first, it->second.second}); + } + return union_set; +} + +bool +PathProbeType::is_reciever_generic () const +{ + const TyTy::BaseType *root = receiver->get_root (); + bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM; + bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC; + return receiver_is_type_param || receiver_is_dyn; +} + +// PathProbImplTrait + +PathProbeImplTrait::PathProbeImplTrait (const TyTy::BaseType *receiver, + const HIR::PathIdentSegment &query, + const TraitReference *trait_reference) + : PathProbeType (receiver, query, UNKNOWN_DEFID), + trait_reference (trait_reference) +{} + +std::set +PathProbeImplTrait::Probe (const TyTy::BaseType *receiver, + const HIR::PathIdentSegment &segment_name, + const TraitReference *trait_reference) +{ + PathProbeImplTrait probe (receiver, segment_name, trait_reference); + // iterate all impls for this trait and receiver + // then search for possible candidates using base class behaviours + probe.process_trait_impl_items_for_candidates (); + return probe.candidates; +} + +void +PathProbeImplTrait::process_trait_impl_items_for_candidates () +{ + mappings->iterate_impl_items ( + [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool { + // just need to check if this is an impl block for this trait the next + // function checks the receiver + if (!impl->has_trait_ref ()) + return true; + + TraitReference *resolved + = TraitResolver::Lookup (*(impl->get_trait_ref ().get ())); + if (!trait_reference->is_equal (*resolved)) + return true; + + process_impl_item_candidate (id, item, impl); + return true; + }); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h index ac7d4f5..d46d797 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.h +++ b/gcc/rust/typecheck/rust-hir-path-probe.h @@ -152,7 +152,7 @@ struct PathProbeCandidate return UNKNOWN_DEFID; } - bool operator< (const PathProbeCandidate &c) const + bool operator<(const PathProbeCandidate &c) const { return get_defid () < c.get_defid (); } @@ -165,144 +165,16 @@ public: Probe (const TyTy::BaseType *receiver, const HIR::PathIdentSegment &segment_name, bool probe_impls, bool probe_bounds, bool ignore_mandatory_trait_items, - DefId specific_trait_id = UNKNOWN_DEFID) - { - PathProbeType probe (receiver, segment_name, specific_trait_id); - if (probe_impls) - { - if (receiver->get_kind () == TyTy::TypeKind::ADT) - { - const TyTy::ADTType *adt - = static_cast (receiver); - if (adt->is_enum ()) - probe.process_enum_item_for_candiates (adt); - } - - probe.process_impl_items_for_candidates (); - } + DefId specific_trait_id = UNKNOWN_DEFID); - if (!probe_bounds) - return probe.candidates; - - if (!probe.is_reciever_generic ()) - { - std::vector> probed_bounds - = TypeBoundsProbe::Probe (receiver); - for (auto &candidate : probed_bounds) - { - const TraitReference *trait_ref = candidate.first; - if (specific_trait_id != UNKNOWN_DEFID) - { - if (trait_ref->get_mappings ().get_defid () - != specific_trait_id) - continue; - } - - HIR::ImplBlock *impl = candidate.second; - probe.process_associated_trait_for_candidates ( - trait_ref, impl, ignore_mandatory_trait_items); - } - } - - for (const TyTy::TypeBoundPredicate &predicate : - receiver->get_specified_bounds ()) - { - const TraitReference *trait_ref = predicate.get (); - if (specific_trait_id != UNKNOWN_DEFID) - { - if (trait_ref->get_mappings ().get_defid () != specific_trait_id) - continue; - } - - probe.process_predicate_for_candidates (predicate, - ignore_mandatory_trait_items); - } - - return probe.candidates; - } - - void visit (HIR::TypeAlias &alias) override - { - Identifier name = alias.get_new_type_name (); - if (search.as_string ().compare (name) == 0) - { - HirId tyid = alias.get_mappings ().get_hirid (); - TyTy::BaseType *ty = nullptr; - bool ok = query_type (tyid, &ty); - rust_assert (ok); - - PathProbeCandidate::ImplItemCandidate impl_item_candidate{&alias, - current_impl}; - PathProbeCandidate candidate{ - PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS, ty, - alias.get_locus (), impl_item_candidate}; - candidates.insert (std::move (candidate)); - } - } - - void visit (HIR::ConstantItem &constant) override - { - Identifier name = constant.get_identifier (); - if (search.as_string ().compare (name) == 0) - { - HirId tyid = constant.get_mappings ().get_hirid (); - TyTy::BaseType *ty = nullptr; - bool ok = query_type (tyid, &ty); - rust_assert (ok); - - PathProbeCandidate::ImplItemCandidate impl_item_candidate{&constant, - current_impl}; - PathProbeCandidate candidate{ - PathProbeCandidate::CandidateType::IMPL_CONST, ty, - constant.get_locus (), impl_item_candidate}; - candidates.insert (std::move (candidate)); - } - } - - void visit (HIR::Function &function) override - { - Identifier name = function.get_function_name (); - if (search.as_string ().compare (name) == 0) - { - HirId tyid = function.get_mappings ().get_hirid (); - TyTy::BaseType *ty = nullptr; - bool ok = query_type (tyid, &ty); - rust_assert (ok); - - PathProbeCandidate::ImplItemCandidate impl_item_candidate{&function, - current_impl}; - PathProbeCandidate candidate{ - PathProbeCandidate::CandidateType::IMPL_FUNC, ty, - function.get_locus (), impl_item_candidate}; - candidates.insert (std::move (candidate)); - } - } + void visit (HIR::TypeAlias &alias) override; + void visit (HIR::ConstantItem &constant) override; + void visit (HIR::Function &function) override; protected: - void process_enum_item_for_candiates (const TyTy::ADTType *adt) - { - if (specific_trait_id != UNKNOWN_DEFID) - return; - - TyTy::VariantDef *v; - if (!adt->lookup_variant (search.as_string (), &v)) - return; - - PathProbeCandidate::EnumItemCandidate enum_item_candidate{adt, v}; - PathProbeCandidate candidate{ - PathProbeCandidate::CandidateType::ENUM_VARIANT, receiver->clone (), - mappings->lookup_location (adt->get_ty_ref ()), enum_item_candidate}; - candidates.insert (std::move (candidate)); - } + void process_enum_item_for_candiates (const TyTy::ADTType *adt); - void process_impl_items_for_candidates () - { - mappings->iterate_impl_items ([&] (HirId id, HIR::ImplItem *item, - HIR::ImplBlock *impl) mutable -> bool { - process_impl_item_candidate (id, item, impl); - return true; - }); - } + void process_impl_items_for_candidates (); void process_impl_item_candidate (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl); @@ -310,156 +182,24 @@ protected: void process_associated_trait_for_candidates (const TraitReference *trait_ref, HIR::ImplBlock *impl, - bool ignore_mandatory_trait_items) - { - const TraitItemReference *trait_item_ref = nullptr; - if (!trait_ref->lookup_trait_item (search.as_string (), &trait_item_ref)) - return; - - bool trait_item_needs_implementation = !trait_item_ref->is_optional (); - if (ignore_mandatory_trait_items && trait_item_needs_implementation) - return; - - PathProbeCandidate::CandidateType candidate_type; - switch (trait_item_ref->get_trait_item_type ()) - { - case TraitItemReference::TraitItemType::FN: - candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC; - break; - case TraitItemReference::TraitItemType::CONST: - candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST; - break; - case TraitItemReference::TraitItemType::TYPE: - candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS; - break; - - case TraitItemReference::TraitItemType::ERROR: - default: - gcc_unreachable (); - break; - } - - TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty (); - - // we can substitute the Self with the receiver here - if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF) - { - TyTy::FnType *fn = static_cast (trait_item_tyty); - TyTy::SubstitutionParamMapping *param = nullptr; - for (auto ¶m_mapping : fn->get_substs ()) - { - const HIR::TypeParam &type_param - = param_mapping.get_generic_param (); - if (type_param.get_type_representation ().compare ("Self") == 0) - { - param = ¶m_mapping; - break; - } - } - rust_assert (param != nullptr); - - std::vector mappings; - mappings.push_back (TyTy::SubstitutionArg (param, receiver->clone ())); - - Location locus; // FIXME - TyTy::SubstitutionArgumentMappings args (std::move (mappings), {}, - locus); - trait_item_tyty = SubstMapperInternal::Resolve (trait_item_tyty, args); - } - - PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref, - trait_item_ref, - impl}; - - PathProbeCandidate candidate{candidate_type, trait_item_tyty, - trait_item_ref->get_locus (), - trait_item_candidate}; - candidates.insert (std::move (candidate)); - } + bool ignore_mandatory_trait_items); void process_predicate_for_candidates (const TyTy::TypeBoundPredicate &predicate, - bool ignore_mandatory_trait_items) - { - const TraitReference *trait_ref = predicate.get (); - - TyTy::TypeBoundPredicateItem item - = predicate.lookup_associated_item (search.as_string ()); - if (item.is_error ()) - return; - - if (ignore_mandatory_trait_items && item.needs_implementation ()) - return; - - const TraitItemReference *trait_item_ref = item.get_raw_item (); - PathProbeCandidate::CandidateType candidate_type; - switch (trait_item_ref->get_trait_item_type ()) - { - case TraitItemReference::TraitItemType::FN: - candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC; - break; - case TraitItemReference::TraitItemType::CONST: - candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST; - break; - case TraitItemReference::TraitItemType::TYPE: - candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS; - break; - - case TraitItemReference::TraitItemType::ERROR: - default: - gcc_unreachable (); - break; - } - - TyTy::BaseType *trait_item_tyty = item.get_tyty_for_receiver (receiver); - PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref, - trait_item_ref, - nullptr}; - PathProbeCandidate candidate{candidate_type, trait_item_tyty, - trait_item_ref->get_locus (), - trait_item_candidate}; - candidates.insert (std::move (candidate)); - } + bool ignore_mandatory_trait_items); protected: PathProbeType (const TyTy::BaseType *receiver, - const HIR::PathIdentSegment &query, DefId specific_trait_id) - : TypeCheckBase (), receiver (receiver), search (query), - current_impl (nullptr), specific_trait_id (specific_trait_id) - {} + const HIR::PathIdentSegment &query, DefId specific_trait_id); std::vector> union_bounds ( const std::vector> a, const std::vector> b) - const - { - std::map> mapper; - for (auto &ref : a) - { - mapper.insert ({ref.first->get_mappings ().get_defid (), ref}); - } - for (auto &ref : b) - { - mapper.insert ({ref.first->get_mappings ().get_defid (), ref}); - } - - std::vector> union_set; - for (auto it = mapper.begin (); it != mapper.end (); it++) - { - union_set.push_back ({it->second.first, it->second.second}); - } - return union_set; - } + const; - bool is_reciever_generic () const - { - const TyTy::BaseType *root = receiver->get_root (); - bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM; - bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC; - return receiver_is_type_param || receiver_is_dyn; - } + bool is_reciever_generic () const; const TyTy::BaseType *receiver; const HIR::PathIdentSegment &search; @@ -489,24 +229,14 @@ public: static std::set Probe (const TyTy::BaseType *receiver, const HIR::PathIdentSegment &segment_name, - const TraitReference *trait_reference) - { - PathProbeImplTrait probe (receiver, segment_name, trait_reference); - // iterate all impls for this trait and receiver - // then search for possible candidates using base class behaviours - probe.process_trait_impl_items_for_candidates (); - return probe.candidates; - } + const TraitReference *trait_reference); private: - void process_trait_impl_items_for_candidates (); - PathProbeImplTrait (const TyTy::BaseType *receiver, const HIR::PathIdentSegment &query, - const TraitReference *trait_reference) - : PathProbeType (receiver, query, UNKNOWN_DEFID), - trait_reference (trait_reference) - {} + const TraitReference *trait_reference); + + void process_trait_impl_items_for_candidates (); const TraitReference *trait_reference; }; diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc index d968c20..cc6693f 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc @@ -594,27 +594,5 @@ TraitItemReference::is_object_safe () const return false; } -// rust-hir-path-probe.h - -void -PathProbeImplTrait::process_trait_impl_items_for_candidates () -{ - mappings->iterate_impl_items ( - [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool { - // just need to check if this is an impl block for this trait the next - // function checks the receiver - if (!impl->has_trait_ref ()) - return true; - - TraitReference *resolved - = TraitResolver::Lookup (*(impl->get_trait_ref ().get ())); - if (!trait_reference->is_equal (*resolved)) - return true; - - process_impl_item_candidate (id, item, impl); - return true; - }); -} - } // namespace Resolver } // namespace Rust -- cgit v1.1 From d5d70e3fa6e66798b1f2eca4b9aa3821ae4dc0c5 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 16 Jan 2023 17:54:41 +0000 Subject: gccrs: Refactor PathProbeType code into CC file Signed-off-by: Philip Herron gcc/rust/ChangeLog: * typecheck/rust-hir-path-probe.cc (PathProbeCandidate::Candidate::Candidate): refactor (PathProbeCandidate::PathProbeCandidate): likewise (PathProbeCandidate::as_string): likewise (PathProbeCandidate::is_enum_candidate): likewise (PathProbeCandidate::is_impl_candidate): likewise (PathProbeCandidate::is_trait_candidate): likewise (PathProbeCandidate::is_full_trait_item_candidate): likewise (PathProbeCandidate::get_error): likewise (PathProbeCandidate::is_error): likewise (PathProbeCandidate::get_defid): likewise (PathProbeCandidate::operator<): likewise * typecheck/rust-hir-path-probe.h (struct PathProbeCandidate): likewise --- gcc/rust/typecheck/rust-hir-path-probe.cc | 109 ++++++++++++++++++++++++++++++ gcc/rust/typecheck/rust-hir-path-probe.h | 82 ++++------------------ 2 files changed, 124 insertions(+), 67 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-hir-path-probe.cc b/gcc/rust/typecheck/rust-hir-path-probe.cc index 06d8920..be89ceb 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.cc +++ b/gcc/rust/typecheck/rust-hir-path-probe.cc @@ -23,6 +23,115 @@ namespace Rust { namespace Resolver { +// PathProbeCandidate + +PathProbeCandidate::Candidate::Candidate (EnumItemCandidate enum_field) + : enum_field (enum_field) +{} + +PathProbeCandidate::Candidate::Candidate (ImplItemCandidate impl) : impl (impl) +{} + +PathProbeCandidate::Candidate::Candidate (TraitItemCandidate trait) + : trait (trait) +{} + +PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, + Location locus, + EnumItemCandidate enum_field) + : type (type), ty (ty), locus (locus), item (enum_field) +{} + +PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, + Location locus, ImplItemCandidate impl) + : type (type), ty (ty), locus (locus), item (impl) +{} + +PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, + Location locus, + TraitItemCandidate trait) + : type (type), ty (ty), locus (locus), item (trait) +{} + +std::string +PathProbeCandidate::as_string () const +{ + return "PathProbe candidate TODO - as_string"; +} + +bool +PathProbeCandidate::is_enum_candidate () const +{ + return type == ENUM_VARIANT; +} + +bool +PathProbeCandidate::is_impl_candidate () const +{ + return type == IMPL_CONST || type == IMPL_TYPE_ALIAS || type == IMPL_FUNC; +} + +bool +PathProbeCandidate::is_trait_candidate () const +{ + return type == TRAIT_ITEM_CONST || type == TRAIT_TYPE_ALIAS + || type == TRAIT_FUNC; +} + +bool +PathProbeCandidate::is_full_trait_item_candidate () const +{ + return is_trait_candidate () && item.trait.impl == nullptr; +} + +PathProbeCandidate +PathProbeCandidate::get_error () +{ + return PathProbeCandidate (ERROR, nullptr, Location (), + ImplItemCandidate{nullptr, nullptr}); +} + +bool +PathProbeCandidate::is_error () const +{ + return type == ERROR; +} + +DefId +PathProbeCandidate::get_defid () const +{ + switch (type) + { + case ENUM_VARIANT: + return item.enum_field.variant->get_defid (); + break; + + case IMPL_CONST: + case IMPL_TYPE_ALIAS: + case IMPL_FUNC: + return item.impl.impl_item->get_impl_mappings ().get_defid (); + break; + + case TRAIT_ITEM_CONST: + case TRAIT_TYPE_ALIAS: + case TRAIT_FUNC: + return item.trait.item_ref->get_mappings ().get_defid (); + break; + + case ERROR: + default: + return UNKNOWN_DEFID; + } + + return UNKNOWN_DEFID; +} + +bool +PathProbeCandidate::operator< (const PathProbeCandidate &c) const +{ + return get_defid () < c.get_defid (); +} + // PathProbeType PathProbeType::PathProbeType (const TyTy::BaseType *receiver, diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h index d46d797..0bb3b99 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.h +++ b/gcc/rust/typecheck/rust-hir-path-probe.h @@ -73,89 +73,37 @@ struct PathProbeCandidate ImplItemCandidate impl; TraitItemCandidate trait; - Candidate (EnumItemCandidate enum_field) : enum_field (enum_field) {} - Candidate (ImplItemCandidate impl) : impl (impl) {} - Candidate (TraitItemCandidate trait) : trait (trait) {} + Candidate (EnumItemCandidate enum_field); + Candidate (ImplItemCandidate impl); + Candidate (TraitItemCandidate trait); } item; PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus, - EnumItemCandidate enum_field) - : type (type), ty (ty), locus (locus), item (enum_field) - {} + EnumItemCandidate enum_field); PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus, - ImplItemCandidate impl) - : type (type), ty (ty), locus (locus), item (impl) - {} + ImplItemCandidate impl); PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus, - TraitItemCandidate trait) - : type (type), ty (ty), locus (locus), item (trait) - {} + TraitItemCandidate trait); - std::string as_string () const - { - return "PathProbe candidate TODO - as_string"; - } + std::string as_string () const; - bool is_enum_candidate () const { return type == ENUM_VARIANT; } + bool is_enum_candidate () const; - bool is_impl_candidate () const - { - return type == IMPL_CONST || type == IMPL_TYPE_ALIAS || type == IMPL_FUNC; - } + bool is_impl_candidate () const; - bool is_trait_candidate () const - { - return type == TRAIT_ITEM_CONST || type == TRAIT_TYPE_ALIAS - || type == TRAIT_FUNC; - } + bool is_trait_candidate () const; - bool is_full_trait_item_candidate () const - { - return is_trait_candidate () && item.trait.impl == nullptr; - } + bool is_full_trait_item_candidate () const; - static PathProbeCandidate get_error () - { - return PathProbeCandidate (ERROR, nullptr, Location (), - ImplItemCandidate{nullptr, nullptr}); - } + static PathProbeCandidate get_error (); - bool is_error () const { return type == ERROR; } + bool is_error () const; - DefId get_defid () const - { - switch (type) - { - case ENUM_VARIANT: - return item.enum_field.variant->get_defid (); - break; - - case IMPL_CONST: - case IMPL_TYPE_ALIAS: - case IMPL_FUNC: - return item.impl.impl_item->get_impl_mappings ().get_defid (); - break; - - case TRAIT_ITEM_CONST: - case TRAIT_TYPE_ALIAS: - case TRAIT_FUNC: - return item.trait.item_ref->get_mappings ().get_defid (); - break; - - case ERROR: - default: - return UNKNOWN_DEFID; - } - - return UNKNOWN_DEFID; - } + DefId get_defid () const; - bool operator<(const PathProbeCandidate &c) const - { - return get_defid () < c.get_defid (); - } + bool operator< (const PathProbeCandidate &c) const; }; class PathProbeType : public TypeCheckBase, public HIR::HIRImplVisitor -- cgit v1.1 From 5ea0f26bab31e63aaab85eee25250eddb753486f Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 16 Jan 2023 19:27:36 +0000 Subject: gccrs: Refactor all code out of the rust-tyty.h header Signed-off-by: Philip Herron gcc/rust/ChangeLog: * typecheck/rust-hir-type-check.h: refactor * typecheck/rust-tyctx.cc (TypeCheckContext::iterate): refactor (TypeCheckContext::have_loop_context): likewise (TypeCheckContext::push_new_loop_context): likewise (TypeCheckContext::push_new_while_loop_context): likewise (TypeCheckContext::peek_loop_context): likewise (TypeCheckContext::pop_loop_context): likewise (TypeCheckContext::swap_head_loop_context): likewise (TypeCheckContext::insert_trait_reference): likewise (TypeCheckContext::lookup_trait_reference): likewise (TypeCheckContext::insert_receiver): likewise (TypeCheckContext::lookup_receiver): likewise (TypeCheckContext::insert_associated_type_mapping): likewise (TypeCheckContext::clear_associated_type_mapping): likewise (TypeCheckContext::lookup_associated_type_mapping): likewise (TypeCheckContext::insert_variant_definition): likewise (TypeCheckContext::lookup_variant_definition): likewise (TypeCheckContext::insert_operator_overload): likewise (TypeCheckContext::lookup_operator_overload): likewise (TypeCheckContext::insert_unconstrained_check_marker): likewise (TypeCheckContext::have_checked_for_unconstrained): likewise (TypeCheckContext::insert_resolved_predicate): likewise (TypeCheckContext::lookup_predicate): likewise (TypeCheckContext::insert_query): likewise (TypeCheckContext::query_completed): likewise (TypeCheckContext::query_in_progress): likewise (TypeCheckContext::insert_trait_query): likewise (TypeCheckContext::trait_query_completed): likewise (TypeCheckContext::trait_query_in_progress): likewise (TypeCheckContextItem::Item::Item): likewise (TypeCheckContextItem::TypeCheckContextItem): likewise (TypeCheckContextItem::get_item): likewise (TypeCheckContextItem::get_impl_item): likewise (TypeCheckContextItem::get_trait_item): likewise (TypeCheckContextItem::get_type): likewise * typecheck/rust-tyty.cc (StructFieldType::StructFieldType): likewise (StructFieldType::get_ref): likewise (StructFieldType::get_name): likewise (StructFieldType::get_field_type): likewise (StructFieldType::set_field_type): likewise (StructFieldType::is_concrete): likewise (StructFieldType::debug): likewise (StructFieldType::get_locus): likewise (VariantDef::variant_type_string): likewise (VariantDef::VariantDef): likewise (VariantDef::operator=): likewise (VariantDef::get_error_node): likewise (VariantDef::is_error): likewise (VariantDef::get_id): likewise (VariantDef::get_defid): likewise (VariantDef::get_variant_type): likewise (VariantDef::is_data_variant): likewise (VariantDef::is_dataless_variant): likewise (VariantDef::get_identifier): likewise (VariantDef::num_fields): likewise (VariantDef::get_field_at_index): likewise (VariantDef::get_fields): likewise (VariantDef::lookup_field): likewise (VariantDef::get_discriminant): likewise (VariantDef::as_string): likewise (VariantDef::is_equal): likewise (VariantDef::clone): likewise (VariantDef::monomorphized_clone): likewise (VariantDef::get_ident): likewise (TupleType::TupleType): likewise (TupleType::get_unit_type): likewise (TupleType::is_unit): likewise (TupleType::num_fields): likewise (TupleType::is_concrete): likewise (TupleType::get_fields): likewise (BoolType::BoolType): likewise (BoolType::get_name): likewise (BoolType::is_concrete): likewise (IntType::IntType): likewise (IntType::get_name): likewise (IntType::get_int_kind): likewise (IntType::is_concrete): likewise (UintType::UintType): likewise (UintType::get_name): likewise (UintType::get_uint_kind): likewise (UintType::is_concrete): likewise (FloatType::FloatType): likewise (FloatType::get_name): likewise (FloatType::get_float_kind): likewise (FloatType::is_concrete): likewise (USizeType::USizeType): likewise (USizeType::get_name): likewise (USizeType::is_concrete): likewise (ISizeType::ISizeType): likewise (ISizeType::get_name): likewise (ISizeType::is_concrete): likewise (CharType::CharType): likewise (CharType::is_concrete): likewise (CharType::get_name): likewise (ReferenceType::ReferenceType): likewise (ReferenceType::is_concrete): likewise (ReferenceType::mutability): likewise (ReferenceType::is_mutable): likewise (ReferenceType::is_dyn_object): likewise (ReferenceType::is_dyn_slice_type): likewise (ReferenceType::is_dyn_str_type): likewise (PointerType::PointerType): likewise (PointerType::is_concrete): likewise (PointerType::mutability): likewise (PointerType::is_mutable): likewise (PointerType::is_const): likewise (PointerType::is_dyn_object): likewise (PointerType::is_dyn_slice_type): likewise (PointerType::is_dyn_str_type): likewise (ParamType::ParamType): likewise (ParamType::get_generic_param): likewise (ParamType::can_resolve): likewise (ParamType::is_concrete): likewise (StrType::StrType): likewise (StrType::get_name): likewise (StrType::is_concrete): likewise (NeverType::NeverType): likewise (NeverType::get_name): likewise (NeverType::is_unit): likewise (NeverType::is_concrete): likewise (PlaceholderType::PlaceholderType): likewise (PlaceholderType::get_name): likewise (PlaceholderType::is_unit): likewise (PlaceholderType::get_symbol): likewise (PlaceholderType::is_concrete): likewise (ProjectionType::is_unit): likewise (ProjectionType::get_name): likewise (ProjectionType::needs_generic_substitutions): likewise (ProjectionType::supports_substitutions): likewise (ProjectionType::has_subsititions_defined): likewise (ProjectionType::get): likewise (ProjectionType::is_concrete): likewise (DynamicObjectType::is_concrete): likewise * typecheck/rust-tyty.h: likewise --- gcc/rust/typecheck/rust-hir-type-check.h | 332 ++--------- gcc/rust/typecheck/rust-tyctx.cc | 379 ++++++++++++ gcc/rust/typecheck/rust-tyty.cc | 960 ++++++++++++++++++++++++++++++- gcc/rust/typecheck/rust-tyty.h | 667 ++++----------------- 4 files changed, 1508 insertions(+), 830 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index d785835..8e5c8f6 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -38,37 +38,17 @@ public: TRAIT_ITEM, }; - TypeCheckContextItem (HIR::Function *item) - : type (ItemType::ITEM), item (item) - {} + TypeCheckContextItem (HIR::Function *item); + TypeCheckContextItem (HIR::ImplBlock *impl_block, HIR::Function *item); + TypeCheckContextItem (HIR::TraitItemFunc *trait_item); - TypeCheckContextItem (HIR::ImplBlock *impl_block, HIR::Function *item) - : type (ItemType::IMPL_ITEM), item (impl_block, item) - {} + ItemType get_type () const; - TypeCheckContextItem (HIR::TraitItemFunc *trait_item) - : type (ItemType::TRAIT_ITEM), item (trait_item) - {} + HIR::Function *get_item (); - ItemType get_type () const { return type; } + std::pair &get_impl_item (); - HIR::Function *get_item () - { - rust_assert (get_type () == ItemType::ITEM); - return item.item; - } - - std::pair &get_impl_item () - { - rust_assert (get_type () == ItemType::IMPL_ITEM); - return item.impl_item; - }; - - HIR::TraitItemFunc *get_trait_item () - { - rust_assert (get_type () == ItemType::TRAIT_ITEM); - return item.trait_item; - } + HIR::TraitItemFunc *get_trait_item (); TyTy::FnType *get_context_type (); @@ -79,13 +59,9 @@ private: std::pair impl_item; HIR::TraitItemFunc *trait_item; - Item (HIR::Function *item) : item (item) {} - - Item (HIR::ImplBlock *impl_block, HIR::Function *item) - : impl_item ({impl_block, item}) - {} - - Item (HIR::TraitItemFunc *trait_item) : trait_item (trait_item) {} + Item (HIR::Function *item); + Item (HIR::ImplBlock *impl_block, HIR::Function *item); + Item (HIR::TraitItemFunc *trait_item); }; ItemType type; @@ -118,283 +94,71 @@ public: void push_return_type (TypeCheckContextItem item, TyTy::BaseType *return_type); void pop_return_type (); + void iterate (std::function cb); - void iterate (std::function cb) - { - for (auto it = resolved.begin (); it != resolved.end (); it++) - { - if (!cb (it->first, it->second)) - return; - } - } - - bool have_loop_context () const { return !loop_type_stack.empty (); } - - void push_new_loop_context (HirId id, Location locus) - { - TyTy::BaseType *infer_var - = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL, - locus); - loop_type_stack.push_back (infer_var); - } - - void push_new_while_loop_context (HirId id) - { - TyTy::BaseType *infer_var = new TyTy::ErrorType (id); - loop_type_stack.push_back (infer_var); - } - - TyTy::BaseType *peek_loop_context () { return loop_type_stack.back (); } - - TyTy::BaseType *pop_loop_context () - { - auto back = peek_loop_context (); - loop_type_stack.pop_back (); - return back; - } - - void swap_head_loop_context (TyTy::BaseType *val) - { - loop_type_stack.pop_back (); - loop_type_stack.push_back (val); - } - - void insert_trait_reference (DefId id, TraitReference &&ref) - { - rust_assert (trait_context.find (id) == trait_context.end ()); - trait_context.emplace (id, std::move (ref)); - } - - bool lookup_trait_reference (DefId id, TraitReference **ref) - { - auto it = trait_context.find (id); - if (it == trait_context.end ()) - return false; + bool have_loop_context () const; + void push_new_loop_context (HirId id, Location locus); + void push_new_while_loop_context (HirId id); + TyTy::BaseType *peek_loop_context (); + TyTy::BaseType *pop_loop_context (); - *ref = &it->second; - return true; - } - - void insert_receiver (HirId id, TyTy::BaseType *t) - { - receiver_context[id] = t; - } + void swap_head_loop_context (TyTy::BaseType *val); - bool lookup_receiver (HirId id, TyTy::BaseType **ref) - { - auto it = receiver_context.find (id); - if (it == receiver_context.end ()) - return false; + void insert_trait_reference (DefId id, TraitReference &&ref); + bool lookup_trait_reference (DefId id, TraitReference **ref); - *ref = it->second; - return true; - } + void insert_receiver (HirId id, TyTy::BaseType *t); + bool lookup_receiver (HirId id, TyTy::BaseType **ref); - void insert_associated_trait_impl (HirId id, AssociatedImplTrait &&associated) - { - rust_assert (associated_impl_traits.find (id) - == associated_impl_traits.end ()); - associated_impl_traits.emplace (id, std::move (associated)); - } + void insert_associated_trait_impl (HirId id, + AssociatedImplTrait &&associated); + bool lookup_associated_trait_impl (HirId id, + AssociatedImplTrait **associated); - bool lookup_associated_trait_impl (HirId id, AssociatedImplTrait **associated) - { - auto it = associated_impl_traits.find (id); - if (it == associated_impl_traits.end ()) - return false; - - *associated = &it->second; - return true; - } - - void insert_associated_type_mapping (HirId id, HirId mapping) - { - associated_type_mappings[id] = mapping; - } - - void clear_associated_type_mapping (HirId id) - { - auto it = associated_type_mappings.find (id); - if (it != associated_type_mappings.end ()) - associated_type_mappings.erase (it); - } + void insert_associated_type_mapping (HirId id, HirId mapping); + void clear_associated_type_mapping (HirId id); // lookup any associated type mappings, the out parameter of mapping is // allowed to be nullptr which allows this interface to do a simple does exist // check - bool lookup_associated_type_mapping (HirId id, HirId *mapping) - { - auto it = associated_type_mappings.find (id); - if (it == associated_type_mappings.end ()) - return false; - - if (mapping != nullptr) - *mapping = it->second; - - return true; - } + bool lookup_associated_type_mapping (HirId id, HirId *mapping); void insert_associated_impl_mapping (HirId trait_id, const TyTy::BaseType *impl_type, - HirId impl_id) - { - auto it = associated_traits_to_impls.find (trait_id); - if (it == associated_traits_to_impls.end ()) - { - associated_traits_to_impls[trait_id] = {}; - } - - associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id}); - } - + HirId impl_id); bool lookup_associated_impl_mapping_for_self (HirId trait_id, const TyTy::BaseType *self, - HirId *mapping) - { - auto it = associated_traits_to_impls.find (trait_id); - if (it == associated_traits_to_impls.end ()) - return false; - - for (auto &item : it->second) - { - if (item.first->can_eq (self, false)) - { - *mapping = item.second; - return true; - } - } - return false; - } + HirId *mapping); void insert_autoderef_mappings (HirId id, - std::vector &&adjustments) - { - rust_assert (autoderef_mappings.find (id) == autoderef_mappings.end ()); - autoderef_mappings.emplace (id, std::move (adjustments)); - } - + std::vector &&adjustments); bool lookup_autoderef_mappings (HirId id, - std::vector **adjustments) - { - auto it = autoderef_mappings.find (id); - if (it == autoderef_mappings.end ()) - return false; - - *adjustments = &it->second; - return true; - } + std::vector **adjustments); void insert_cast_autoderef_mappings (HirId id, - std::vector &&adjustments) - { - rust_assert (cast_autoderef_mappings.find (id) - == cast_autoderef_mappings.end ()); - cast_autoderef_mappings.emplace (id, std::move (adjustments)); - } - + std::vector &&adjustments); bool lookup_cast_autoderef_mappings (HirId id, - std::vector **adjustments) - { - auto it = cast_autoderef_mappings.find (id); - if (it == cast_autoderef_mappings.end ()) - return false; + std::vector **adjustments); - *adjustments = &it->second; - return true; - } + void insert_variant_definition (HirId id, HirId variant); + bool lookup_variant_definition (HirId id, HirId *variant); - void insert_variant_definition (HirId id, HirId variant) - { - auto it = variants.find (id); - rust_assert (it == variants.end ()); + void insert_operator_overload (HirId id, TyTy::FnType *call_site); + bool lookup_operator_overload (HirId id, TyTy::FnType **call); - variants[id] = variant; - } + void insert_unconstrained_check_marker (HirId id, bool status); + bool have_checked_for_unconstrained (HirId id, bool *result); - bool lookup_variant_definition (HirId id, HirId *variant) - { - auto it = variants.find (id); - if (it == variants.end ()) - return false; + void insert_resolved_predicate (HirId id, TyTy::TypeBoundPredicate predicate); + bool lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result); - *variant = it->second; - return true; - } - - void insert_operator_overload (HirId id, TyTy::FnType *call_site) - { - auto it = operator_overloads.find (id); - rust_assert (it == operator_overloads.end ()); - - operator_overloads[id] = call_site; - } - - bool lookup_operator_overload (HirId id, TyTy::FnType **call) - { - auto it = operator_overloads.find (id); - if (it == operator_overloads.end ()) - return false; - - *call = it->second; - return true; - } + void insert_query (HirId id); + void query_completed (HirId id); + bool query_in_progress (HirId id) const; - void insert_unconstrained_check_marker (HirId id, bool status) - { - unconstrained[id] = status; - } - - bool have_checked_for_unconstrained (HirId id, bool *result) - { - auto it = unconstrained.find (id); - bool found = it != unconstrained.end (); - if (!found) - return false; - - *result = it->second; - return true; - } - - void insert_resolved_predicate (HirId id, TyTy::TypeBoundPredicate predicate) - { - auto it = predicates.find (id); - rust_assert (it == predicates.end ()); - - predicates.insert ({id, predicate}); - } - - bool lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result) - { - auto it = predicates.find (id); - bool found = it != predicates.end (); - if (!found) - return false; - - *result = it->second; - return true; - } - - void insert_query (HirId id) { querys_in_progress.insert (id); } - - void query_completed (HirId id) { querys_in_progress.erase (id); } - - bool query_in_progress (HirId id) const - { - return querys_in_progress.find (id) != querys_in_progress.end (); - } - - void insert_trait_query (DefId id) { trait_queries_in_progress.insert (id); } - - void trait_query_completed (DefId id) - { - trait_queries_in_progress.erase (id); - } - - bool trait_query_in_progress (DefId id) const - { - return trait_queries_in_progress.find (id) - != trait_queries_in_progress.end (); - } + void insert_trait_query (DefId id); + void trait_query_completed (DefId id); + bool trait_query_in_progress (DefId id) const; private: TypeCheckContext (); diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc index 34b60b3..ba4d322 100644 --- a/gcc/rust/typecheck/rust-tyctx.cc +++ b/gcc/rust/typecheck/rust-tyctx.cc @@ -154,8 +154,387 @@ TypeCheckContext::peek_context () return return_type_stack.back ().first; } +void +TypeCheckContext::iterate (std::function cb) +{ + for (auto it = resolved.begin (); it != resolved.end (); it++) + { + if (!cb (it->first, it->second)) + return; + } +} + +bool +TypeCheckContext::have_loop_context () const +{ + return !loop_type_stack.empty (); +} + +void +TypeCheckContext::push_new_loop_context (HirId id, Location locus) +{ + TyTy::BaseType *infer_var + = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL, locus); + loop_type_stack.push_back (infer_var); +} + +void +TypeCheckContext::push_new_while_loop_context (HirId id) +{ + TyTy::BaseType *infer_var = new TyTy::ErrorType (id); + loop_type_stack.push_back (infer_var); +} + +TyTy::BaseType * +TypeCheckContext::peek_loop_context () +{ + return loop_type_stack.back (); +} + +TyTy::BaseType * +TypeCheckContext::pop_loop_context () +{ + auto back = peek_loop_context (); + loop_type_stack.pop_back (); + return back; +} + +void +TypeCheckContext::swap_head_loop_context (TyTy::BaseType *val) +{ + loop_type_stack.pop_back (); + loop_type_stack.push_back (val); +} + +void +TypeCheckContext::insert_trait_reference (DefId id, TraitReference &&ref) +{ + rust_assert (trait_context.find (id) == trait_context.end ()); + trait_context.emplace (id, std::move (ref)); +} + +bool +TypeCheckContext::lookup_trait_reference (DefId id, TraitReference **ref) +{ + auto it = trait_context.find (id); + if (it == trait_context.end ()) + return false; + + *ref = &it->second; + return true; +} + +void +TypeCheckContext::insert_receiver (HirId id, TyTy::BaseType *t) +{ + receiver_context[id] = t; +} + +bool +TypeCheckContext::lookup_receiver (HirId id, TyTy::BaseType **ref) +{ + auto it = receiver_context.find (id); + if (it == receiver_context.end ()) + return false; + + *ref = it->second; + return true; +} + +void +TypeCheckContext::insert_associated_trait_impl ( + HirId id, AssociatedImplTrait &&associated) +{ + rust_assert (associated_impl_traits.find (id) + == associated_impl_traits.end ()); + associated_impl_traits.emplace (id, std::move (associated)); +} + +bool +TypeCheckContext::lookup_associated_trait_impl ( + HirId id, AssociatedImplTrait **associated) +{ + auto it = associated_impl_traits.find (id); + if (it == associated_impl_traits.end ()) + return false; + + *associated = &it->second; + return true; +} + +void +TypeCheckContext::insert_associated_type_mapping (HirId id, HirId mapping) +{ + associated_type_mappings[id] = mapping; +} + +void +TypeCheckContext::clear_associated_type_mapping (HirId id) +{ + auto it = associated_type_mappings.find (id); + if (it != associated_type_mappings.end ()) + associated_type_mappings.erase (it); +} + +// lookup any associated type mappings, the out parameter of mapping is +// allowed to be nullptr which allows this interface to do a simple does exist +// check +bool +TypeCheckContext::lookup_associated_type_mapping (HirId id, HirId *mapping) +{ + auto it = associated_type_mappings.find (id); + if (it == associated_type_mappings.end ()) + return false; + + if (mapping != nullptr) + *mapping = it->second; + + return true; +} + +void +TypeCheckContext::insert_associated_impl_mapping ( + HirId trait_id, const TyTy::BaseType *impl_type, HirId impl_id) +{ + auto it = associated_traits_to_impls.find (trait_id); + if (it == associated_traits_to_impls.end ()) + { + associated_traits_to_impls[trait_id] = {}; + } + + associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id}); +} + +bool +TypeCheckContext::lookup_associated_impl_mapping_for_self ( + HirId trait_id, const TyTy::BaseType *self, HirId *mapping) +{ + auto it = associated_traits_to_impls.find (trait_id); + if (it == associated_traits_to_impls.end ()) + return false; + + for (auto &item : it->second) + { + if (item.first->can_eq (self, false)) + { + *mapping = item.second; + return true; + } + } + return false; +} + +void +TypeCheckContext::insert_autoderef_mappings ( + HirId id, std::vector &&adjustments) +{ + rust_assert (autoderef_mappings.find (id) == autoderef_mappings.end ()); + autoderef_mappings.emplace (id, std::move (adjustments)); +} + +bool +TypeCheckContext::lookup_autoderef_mappings ( + HirId id, std::vector **adjustments) +{ + auto it = autoderef_mappings.find (id); + if (it == autoderef_mappings.end ()) + return false; + + *adjustments = &it->second; + return true; +} + +void +TypeCheckContext::insert_cast_autoderef_mappings ( + HirId id, std::vector &&adjustments) +{ + rust_assert (cast_autoderef_mappings.find (id) + == cast_autoderef_mappings.end ()); + cast_autoderef_mappings.emplace (id, std::move (adjustments)); +} + +bool +TypeCheckContext::lookup_cast_autoderef_mappings ( + HirId id, std::vector **adjustments) +{ + auto it = cast_autoderef_mappings.find (id); + if (it == cast_autoderef_mappings.end ()) + return false; + + *adjustments = &it->second; + return true; +} + +void +TypeCheckContext::insert_variant_definition (HirId id, HirId variant) +{ + auto it = variants.find (id); + rust_assert (it == variants.end ()); + + variants[id] = variant; +} + +bool +TypeCheckContext::lookup_variant_definition (HirId id, HirId *variant) +{ + auto it = variants.find (id); + if (it == variants.end ()) + return false; + + *variant = it->second; + return true; +} + +void +TypeCheckContext::insert_operator_overload (HirId id, TyTy::FnType *call_site) +{ + auto it = operator_overloads.find (id); + rust_assert (it == operator_overloads.end ()); + + operator_overloads[id] = call_site; +} + +bool +TypeCheckContext::lookup_operator_overload (HirId id, TyTy::FnType **call) +{ + auto it = operator_overloads.find (id); + if (it == operator_overloads.end ()) + return false; + + *call = it->second; + return true; +} + +void +TypeCheckContext::insert_unconstrained_check_marker (HirId id, bool status) +{ + unconstrained[id] = status; +} + +bool +TypeCheckContext::have_checked_for_unconstrained (HirId id, bool *result) +{ + auto it = unconstrained.find (id); + bool found = it != unconstrained.end (); + if (!found) + return false; + + *result = it->second; + return true; +} + +void +TypeCheckContext::insert_resolved_predicate (HirId id, + TyTy::TypeBoundPredicate predicate) +{ + auto it = predicates.find (id); + rust_assert (it == predicates.end ()); + + predicates.insert ({id, predicate}); +} + +bool +TypeCheckContext::lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result) +{ + auto it = predicates.find (id); + bool found = it != predicates.end (); + if (!found) + return false; + + *result = it->second; + return true; +} + +void +TypeCheckContext::insert_query (HirId id) +{ + querys_in_progress.insert (id); +} + +void +TypeCheckContext::query_completed (HirId id) +{ + querys_in_progress.erase (id); +} + +bool +TypeCheckContext::query_in_progress (HirId id) const +{ + return querys_in_progress.find (id) != querys_in_progress.end (); +} + +void +TypeCheckContext::insert_trait_query (DefId id) +{ + trait_queries_in_progress.insert (id); +} + +void +TypeCheckContext::trait_query_completed (DefId id) +{ + trait_queries_in_progress.erase (id); +} + +bool +TypeCheckContext::trait_query_in_progress (DefId id) const +{ + return trait_queries_in_progress.find (id) + != trait_queries_in_progress.end (); +} + // TypeCheckContextItem +TypeCheckContextItem::Item::Item (HIR::Function *item) : item (item) {} + +TypeCheckContextItem::Item::Item (HIR::ImplBlock *impl_block, + HIR::Function *item) + : impl_item ({impl_block, item}) +{} + +TypeCheckContextItem::Item::Item (HIR::TraitItemFunc *trait_item) + : trait_item (trait_item) +{} + +TypeCheckContextItem::TypeCheckContextItem (HIR::Function *item) + : type (ItemType::ITEM), item (item) +{} + +TypeCheckContextItem::TypeCheckContextItem (HIR::ImplBlock *impl_block, + HIR::Function *item) + : type (ItemType::IMPL_ITEM), item (impl_block, item) +{} + +TypeCheckContextItem::TypeCheckContextItem (HIR::TraitItemFunc *trait_item) + : type (ItemType::TRAIT_ITEM), item (trait_item) +{} + +HIR::Function * +TypeCheckContextItem::get_item () +{ + rust_assert (get_type () == ItemType::ITEM); + return item.item; +} + +std::pair & +TypeCheckContextItem::get_impl_item () +{ + rust_assert (get_type () == ItemType::IMPL_ITEM); + return item.impl_item; +} + +HIR::TraitItemFunc * +TypeCheckContextItem::get_trait_item () +{ + rust_assert (get_type () == ItemType::TRAIT_ITEM); + return item.trait_item; +} + +TypeCheckContextItem::ItemType +TypeCheckContextItem::get_type () const +{ + return type; +} + TyTy::FnType * TypeCheckContextItem::get_context_type () { diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 86d19ee..c16c216 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -17,17 +17,22 @@ // . #include "rust-tyty.h" -#include "rust-tyty-visitor.h" -#include "rust-tyty-call.h" + #include "rust-hir-type-check-expr.h" #include "rust-hir-type-check-type.h" -#include "rust-tyty-rules.h" -#include "rust-tyty-cmp.h" +#include "rust-tyty-visitor.h" +#include "rust-tyty-call.h" #include "rust-hir-map.h" +#include "rust-location.h" +#include "rust-linemap.h" + #include "rust-substitution-mapper.h" #include "rust-hir-trait-ref.h" #include "rust-hir-type-bounds.h" #include "rust-hir-trait-resolve.h" +#include "rust-tyty-rules.h" +#include "rust-tyty-cmp.h" + #include "options.h" namespace Rust { @@ -658,6 +663,53 @@ ErrorType::monomorphized_clone () const // Struct Field type +StructFieldType::StructFieldType (HirId ref, std::string name, BaseType *ty, + Location locus) + : ref (ref), name (name), ty (ty), locus (locus) +{} + +HirId +StructFieldType::get_ref () const +{ + return ref; +} + +std::string +StructFieldType::get_name () const +{ + return name; +} + +BaseType * +StructFieldType::get_field_type () const +{ + return ty; +} + +void +StructFieldType::set_field_type (BaseType *fty) +{ + ty = fty; +} + +bool +StructFieldType::is_concrete () const +{ + return ty->is_concrete (); +} + +void +StructFieldType::debug () const +{ + rust_debug ("%s", as_string ().c_str ()); +} + +Location +StructFieldType::get_locus () const +{ + return locus; +} + std::string StructFieldType::as_string () const { @@ -695,6 +747,241 @@ StructFieldType::monomorphized_clone () const get_field_type ()->monomorphized_clone (), locus); } +// VariantDef + +std::string +VariantDef::variant_type_string (VariantType type) +{ + switch (type) + { + case NUM: + return "enumeral"; + case TUPLE: + return "tuple"; + case STRUCT: + return "struct"; + } + gcc_unreachable (); + return ""; +} + +VariantDef::VariantDef (HirId id, DefId defid, std::string identifier, + RustIdent ident, HIR::Expr *discriminant) + : id (id), defid (defid), identifier (identifier), ident (ident), + discriminant (discriminant) + +{ + type = VariantType::NUM; + fields = {}; +} + +VariantDef::VariantDef (HirId id, DefId defid, std::string identifier, + RustIdent ident, VariantType type, + HIR::Expr *discriminant, + std::vector fields) + : id (id), defid (defid), identifier (identifier), ident (ident), type (type), + discriminant (discriminant), fields (fields) +{ + rust_assert ((type == VariantType::NUM && fields.empty ()) + || (type == VariantType::TUPLE || type == VariantType::STRUCT)); +} + +VariantDef::VariantDef (const VariantDef &other) + : id (other.id), defid (other.defid), identifier (other.identifier), + ident (other.ident), type (other.type), discriminant (other.discriminant), + fields (other.fields) +{} + +VariantDef & +VariantDef::operator= (const VariantDef &other) +{ + id = other.id; + identifier = other.identifier; + type = other.type; + discriminant = other.discriminant; + fields = other.fields; + ident = other.ident; + + return *this; +} + +VariantDef & +VariantDef::get_error_node () +{ + static VariantDef node + = VariantDef (UNKNOWN_HIRID, UNKNOWN_DEFID, "", + {Resolver::CanonicalPath::create_empty (), + Linemap::unknown_location ()}, + nullptr); + + return node; +} + +bool +VariantDef::is_error () const +{ + return get_id () == UNKNOWN_HIRID; +} + +HirId +VariantDef::get_id () const +{ + return id; +} + +DefId +VariantDef::get_defid () const +{ + return defid; +} + +VariantDef::VariantType +VariantDef::get_variant_type () const +{ + return type; +} + +bool +VariantDef::is_data_variant () const +{ + return type != VariantType::NUM; +} + +bool +VariantDef::is_dataless_variant () const +{ + return type == VariantType::NUM; +} + +std::string +VariantDef::get_identifier () const +{ + return identifier; +} + +size_t +VariantDef::num_fields () const +{ + return fields.size (); +} + +StructFieldType * +VariantDef::get_field_at_index (size_t index) +{ + rust_assert (index < fields.size ()); + return fields.at (index); +} + +std::vector & +VariantDef::get_fields () +{ + rust_assert (type != NUM); + return fields; +} + +bool +VariantDef::lookup_field (const std::string &lookup, + StructFieldType **field_lookup, size_t *index) const +{ + size_t i = 0; + for (auto &field : fields) + { + if (field->get_name ().compare (lookup) == 0) + { + if (index != nullptr) + *index = i; + + if (field_lookup != nullptr) + *field_lookup = field; + + return true; + } + i++; + } + return false; +} + +HIR::Expr * +VariantDef::get_discriminant () const +{ + rust_assert (discriminant != nullptr); + return discriminant; +} + +std::string +VariantDef::as_string () const +{ + if (type == VariantType::NUM) + return identifier + " = " + discriminant->as_string (); + + std::string buffer; + for (size_t i = 0; i < fields.size (); ++i) + { + buffer += fields.at (i)->as_string (); + if ((i + 1) < fields.size ()) + buffer += ", "; + } + + if (type == VariantType::TUPLE) + return identifier + " (" + buffer + ")"; + else + return identifier + " {" + buffer + "}"; +} + +bool +VariantDef::is_equal (const VariantDef &other) const +{ + if (type != other.type) + return false; + + if (identifier.compare (other.identifier) != 0) + return false; + + if (discriminant != other.discriminant) + return false; + + if (fields.size () != other.fields.size ()) + return false; + + for (size_t i = 0; i < fields.size (); i++) + { + if (!fields.at (i)->is_equal (*other.fields.at (i))) + return false; + } + + return true; +} + +VariantDef * +VariantDef::clone () const +{ + std::vector cloned_fields; + for (auto &f : fields) + cloned_fields.push_back ((StructFieldType *) f->clone ()); + + return new VariantDef (id, defid, identifier, ident, type, discriminant, + cloned_fields); +} + +VariantDef * +VariantDef::monomorphized_clone () const +{ + std::vector cloned_fields; + for (auto &f : fields) + cloned_fields.push_back ((StructFieldType *) f->monomorphized_clone ()); + + return new VariantDef (id, defid, identifier, ident, type, discriminant, + cloned_fields); +} + +const RustIdent & +VariantDef::get_ident () const +{ + return ident; +} + +// ADTType + void ADTType::accept_vis (TyVisitor &vis) { @@ -892,6 +1179,57 @@ ADTType::handle_substitions (SubstitutionArgumentMappings subst_mappings) return adt; } +// TupleType + +TupleType::TupleType (HirId ref, Location locus, std::vector fields, + std::set refs) + : BaseType (ref, ref, TypeKind::TUPLE, + {Resolver::CanonicalPath::create_empty (), locus}, refs), + fields (fields) +{} + +TupleType::TupleType (HirId ref, HirId ty_ref, Location locus, + std::vector fields, std::set refs) + : BaseType (ref, ty_ref, TypeKind::TUPLE, + {Resolver::CanonicalPath::create_empty (), locus}, refs), + fields (fields) +{} + +TupleType * +TupleType::get_unit_type (HirId ref) +{ + return new TupleType (ref, Linemap::predeclared_location ()); +} + +bool +TupleType::is_unit () const +{ + return this->fields.empty (); +} + +size_t +TupleType::num_fields () const +{ + return fields.size (); +} + +bool +TupleType::is_concrete () const +{ + for (size_t i = 0; i < num_fields (); i++) + { + if (!get_field (i)->is_concrete ()) + return false; + } + return true; +} + +const std::vector & +TupleType::get_fields () const +{ + return fields; +} + void TupleType::accept_vis (TyVisitor &vis) { @@ -1622,6 +1960,34 @@ SliceType::handle_substitions (SubstitutionArgumentMappings mappings) return ref; } +// BoolType + +BoolType::BoolType (HirId ref, std::set refs) + : BaseType (ref, ref, TypeKind::BOOL, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs) +{} + +BoolType::BoolType (HirId ref, HirId ty_ref, std::set refs) + : BaseType (ref, ty_ref, TypeKind::BOOL, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs) +{} + +std::string +BoolType::get_name () const +{ + return as_string (); +} + +bool +BoolType::is_concrete () const +{ + return true; +} + void BoolType::accept_vis (TyVisitor &vis) { @@ -1666,6 +2032,36 @@ BoolType::monomorphized_clone () const return clone (); } +// IntType + +IntType::IntType (HirId ref, IntKind kind, std::set refs) + : BaseType (ref, ref, TypeKind::INT, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs), + int_kind (kind) +{} + +IntType::IntType (HirId ref, HirId ty_ref, IntKind kind, std::set refs) + : BaseType (ref, ty_ref, TypeKind::INT, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs), + int_kind (kind) +{} + +std::string +IntType::get_name () const +{ + return as_string (); +} + +IntType::IntKind +IntType::get_int_kind () const +{ + return int_kind; +} + void IntType::accept_vis (TyVisitor &vis) { @@ -1735,6 +2131,43 @@ IntType::is_equal (const BaseType &other) const return get_int_kind () == o.get_int_kind (); } +bool +IntType::is_concrete () const +{ + return true; +} + +// UintType + +UintType::UintType (HirId ref, UintKind kind, std::set refs) + : BaseType (ref, ref, TypeKind::UINT, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs), + uint_kind (kind) +{} + +UintType::UintType (HirId ref, HirId ty_ref, UintKind kind, + std::set refs) + : BaseType (ref, ty_ref, TypeKind::UINT, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs), + uint_kind (kind) +{} + +std::string +UintType::get_name () const +{ + return as_string (); +} + +UintType::UintKind +UintType::get_uint_kind () const +{ + return uint_kind; +} + void UintType::accept_vis (TyVisitor &vis) { @@ -1804,6 +2237,49 @@ UintType::is_equal (const BaseType &other) const return get_uint_kind () == o.get_uint_kind (); } +bool +UintType::is_concrete () const +{ + return true; +} + +// FloatType + +FloatType::FloatType (HirId ref, FloatKind kind, std::set refs) + : BaseType (ref, ref, TypeKind::FLOAT, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs), + float_kind (kind) +{} + +FloatType::FloatType (HirId ref, HirId ty_ref, FloatKind kind, + std::set refs) + : BaseType (ref, ty_ref, TypeKind::FLOAT, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs), + float_kind (kind) +{} + +std::string +FloatType::get_name () const +{ + return as_string (); +} + +FloatType::FloatKind +FloatType::get_float_kind () const +{ + return float_kind; +} + +bool +FloatType::is_concrete () const +{ + return true; +} + void FloatType::accept_vis (TyVisitor &vis) { @@ -1867,6 +2343,34 @@ FloatType::is_equal (const BaseType &other) const return get_float_kind () == o.get_float_kind (); } +// UsizeType + +USizeType::USizeType (HirId ref, std::set refs) + : BaseType (ref, ref, TypeKind::USIZE, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs) +{} + +USizeType::USizeType (HirId ref, HirId ty_ref, std::set refs) + : BaseType (ref, ty_ref, TypeKind::USIZE, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs) +{} + +std::string +USizeType::get_name () const +{ + return as_string (); +} + +bool +USizeType::is_concrete () const +{ + return true; +} + void USizeType::accept_vis (TyVisitor &vis) { @@ -1911,6 +2415,34 @@ USizeType::monomorphized_clone () const return clone (); } +// ISizeType + +ISizeType::ISizeType (HirId ref, std::set refs) + : BaseType (ref, ref, TypeKind::ISIZE, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs) +{} + +ISizeType::ISizeType (HirId ref, HirId ty_ref, std::set refs) + : BaseType (ref, ty_ref, TypeKind::ISIZE, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs) +{} + +std::string +ISizeType::get_name () const +{ + return as_string (); +} + +bool +ISizeType::is_concrete () const +{ + return true; +} + void ISizeType::accept_vis (TyVisitor &vis) { @@ -1955,6 +2487,34 @@ ISizeType::monomorphized_clone () const return clone (); } +// Char Type + +CharType::CharType (HirId ref, std::set refs) + : BaseType (ref, ref, TypeKind::CHAR, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs) +{} + +CharType::CharType (HirId ref, HirId ty_ref, std::set refs) + : BaseType (ref, ty_ref, TypeKind::CHAR, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs) +{} + +bool +CharType::is_concrete () const +{ + return true; +} + +std::string +CharType::get_name () const +{ + return as_string (); +} + void CharType::accept_vis (TyVisitor &vis) { @@ -1999,6 +2559,76 @@ CharType::monomorphized_clone () const return clone (); } +// Reference Type + +ReferenceType::ReferenceType (HirId ref, TyVar base, Mutability mut, + std::set refs) + : BaseType (ref, ref, TypeKind::REF, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs), + base (base), mut (mut) +{} + +ReferenceType::ReferenceType (HirId ref, HirId ty_ref, TyVar base, + Mutability mut, std::set refs) + : BaseType (ref, ty_ref, TypeKind::REF, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs), + base (base), mut (mut) +{} + +bool +ReferenceType::is_concrete () const +{ + return get_base ()->is_concrete (); +} + +Mutability +ReferenceType::mutability () const +{ + return mut; +} + +bool +ReferenceType::is_mutable () const +{ + return mut == Mutability::Mut; +} + +bool +ReferenceType::is_dyn_object () const +{ + return is_dyn_slice_type () || is_dyn_str_type (); +} + +bool +ReferenceType::is_dyn_slice_type (const TyTy::SliceType **slice) const +{ + const TyTy::BaseType *element = get_base ()->destructure (); + if (element->get_kind () != TyTy::TypeKind::SLICE) + return false; + if (slice == nullptr) + return true; + + *slice = static_cast (element); + return true; +} + +bool +ReferenceType::is_dyn_str_type (const TyTy::StrType **str) const +{ + const TyTy::BaseType *element = get_base ()->destructure (); + if (element->get_kind () != TyTy::TypeKind::STR) + return false; + if (str == nullptr) + return true; + + *str = static_cast (element); + return true; +} + void ReferenceType::accept_vis (TyVisitor &vis) { @@ -2089,6 +2719,82 @@ ReferenceType::handle_substitions (SubstitutionArgumentMappings mappings) return ref; } +// PointerType + +PointerType::PointerType (HirId ref, TyVar base, Mutability mut, + std::set refs) + : BaseType (ref, ref, TypeKind::POINTER, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs), + base (base), mut (mut) +{} + +PointerType::PointerType (HirId ref, HirId ty_ref, TyVar base, Mutability mut, + std::set refs) + : BaseType (ref, ty_ref, TypeKind::POINTER, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs), + base (base), mut (mut) +{} + +bool +PointerType::is_concrete () const +{ + return get_base ()->is_concrete (); +} + +Mutability +PointerType::mutability () const +{ + return mut; +} + +bool +PointerType::is_mutable () const +{ + return mut == Mutability::Mut; +} + +bool +PointerType::is_const () const +{ + return mut == Mutability::Imm; +} + +bool +PointerType::is_dyn_object () const +{ + return is_dyn_slice_type () || is_dyn_str_type (); +} + +bool +PointerType::is_dyn_slice_type (const TyTy::SliceType **slice) const +{ + const TyTy::BaseType *element = get_base ()->destructure (); + if (element->get_kind () != TyTy::TypeKind::SLICE) + return false; + if (slice == nullptr) + return true; + + *slice = static_cast (element); + return true; +} + +bool +PointerType::is_dyn_str_type (const TyTy::StrType **str) const +{ + const TyTy::BaseType *element = get_base ()->destructure (); + if (element->get_kind () != TyTy::TypeKind::STR) + return false; + if (str == nullptr) + return true; + + *str = static_cast (element); + return true; +} + void PointerType::accept_vis (TyVisitor &vis) { @@ -2179,6 +2885,52 @@ PointerType::handle_substitions (SubstitutionArgumentMappings mappings) return ref; } +// PARAM Type + +ParamType::ParamType (std::string symbol, Location locus, HirId ref, + HIR::GenericParam ¶m, + std::vector specified_bounds, + std::set refs) + : BaseType (ref, ref, TypeKind::PARAM, + {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol), + locus}, + specified_bounds, refs), + symbol (symbol), param (param) +{} + +ParamType::ParamType (std::string symbol, Location locus, HirId ref, + HirId ty_ref, HIR::GenericParam ¶m, + std::vector specified_bounds, + std::set refs) + : BaseType (ref, ty_ref, TypeKind::PARAM, + {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol), + locus}, + specified_bounds, refs), + symbol (symbol), param (param) +{} + +HIR::GenericParam & +ParamType::get_generic_param () +{ + return param; +} + +bool +ParamType::can_resolve () const +{ + return get_ref () != get_ty_ref (); +} + +bool +ParamType::is_concrete () const +{ + auto r = resolve (); + if (r == this) + return false; + + return r->is_concrete (); +} + void ParamType::accept_vis (TyVisitor &vis) { @@ -2320,6 +3072,34 @@ ParamType::handle_substitions (SubstitutionArgumentMappings subst_mappings) return p; } +// StrType + +StrType::StrType (HirId ref, std::set refs) + : BaseType (ref, ref, TypeKind::STR, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs) +{} + +StrType::StrType (HirId ref, HirId ty_ref, std::set refs) + : BaseType (ref, ty_ref, TypeKind::STR, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs) +{} + +std::string +StrType::get_name () const +{ + return as_string (); +} + +bool +StrType::is_concrete () const +{ + return true; +} + BaseType * StrType::clone () const { @@ -2370,6 +3150,40 @@ StrType::is_equal (const BaseType &other) const return get_kind () == other.get_kind (); } +// Never Type + +NeverType::NeverType (HirId ref, std::set refs) + : BaseType (ref, ref, TypeKind::NEVER, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs) +{} + +NeverType::NeverType (HirId ref, HirId ty_ref, std::set refs) + : BaseType (ref, ty_ref, TypeKind::NEVER, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs) +{} + +std::string +NeverType::get_name () const +{ + return as_string (); +} + +bool +NeverType::is_unit () const +{ + return true; +} + +bool +NeverType::is_concrete () const +{ + return true; +} + void NeverType::accept_vis (TyVisitor &vis) { @@ -2416,6 +3230,52 @@ NeverType::monomorphized_clone () const // placeholder type +PlaceholderType::PlaceholderType (std::string symbol, HirId ref, + std::set refs) + : BaseType (ref, ref, TypeKind::PLACEHOLDER, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs), + symbol (symbol) +{} + +PlaceholderType::PlaceholderType (std::string symbol, HirId ref, HirId ty_ref, + std::set refs) + : BaseType (ref, ty_ref, TypeKind::PLACEHOLDER, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs), + symbol (symbol) +{} + +std::string +PlaceholderType::get_name () const +{ + return as_string (); +} + +bool +PlaceholderType::is_unit () const +{ + rust_assert (can_resolve ()); + return resolve ()->is_unit (); +} + +std::string +PlaceholderType::get_symbol () const +{ + return symbol; +} + +bool +PlaceholderType::is_concrete () const +{ + if (!can_resolve ()) + return true; + + return resolve ()->is_concrete (); +} + void PlaceholderType::accept_vis (TyVisitor &vis) { @@ -2515,6 +3375,78 @@ PlaceholderType::is_equal (const BaseType &other) const // Projection type +ProjectionType::ProjectionType ( + HirId ref, BaseType *base, const Resolver::TraitReference *trait, DefId item, + std::vector subst_refs, + SubstitutionArgumentMappings generic_arguments, std::set refs) + : BaseType (ref, ref, TypeKind::PROJECTION, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs), + SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)), + base (base), trait (trait), item (item) +{} + +ProjectionType::ProjectionType ( + HirId ref, HirId ty_ref, BaseType *base, + const Resolver::TraitReference *trait, DefId item, + std::vector subst_refs, + SubstitutionArgumentMappings generic_arguments, std::set refs) + : BaseType (ref, ty_ref, TypeKind::PROJECTION, + {Resolver::CanonicalPath::create_empty (), + Linemap::predeclared_location ()}, + refs), + SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)), + base (base), trait (trait), item (item) +{} + +bool +ProjectionType::is_unit () const +{ + return false; +} + +std::string +ProjectionType::get_name () const +{ + return as_string (); +} + +bool +ProjectionType::needs_generic_substitutions () const +{ + return needs_substitution (); +} + +bool +ProjectionType::supports_substitutions () const +{ + return true; +} + +bool +ProjectionType::has_subsititions_defined () const +{ + return has_substitutions (); +} + +const BaseType * +ProjectionType::get () const +{ + return base; +} +BaseType * +ProjectionType::get () +{ + return base; +} + +bool +ProjectionType::is_concrete () const +{ + return base->is_concrete (); +} + void ProjectionType::accept_vis (TyVisitor &vis) { @@ -2631,6 +3563,26 @@ ProjectionType::handle_substitions (SubstitutionArgumentMappings subst_mappings) return projection; } +// DynObjectType + +DynamicObjectType::DynamicObjectType ( + HirId ref, RustIdent ident, std::vector specified_bounds, + std::set refs) + : BaseType (ref, ref, TypeKind::DYNAMIC, ident, specified_bounds, refs) +{} + +DynamicObjectType::DynamicObjectType ( + HirId ref, HirId ty_ref, RustIdent ident, + std::vector specified_bounds, std::set refs) + : BaseType (ref, ty_ref, TypeKind::DYNAMIC, ident, specified_bounds, refs) +{} + +bool +DynamicObjectType::is_concrete () const +{ + return true; +} + void DynamicObjectType::accept_vis (TyVisitor &vis) { diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 48058ba..3dd97ce 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -20,11 +20,9 @@ #define RUST_TYTY #include "rust-hir-map.h" -#include "rust-hir-full.h" -#include "rust-diagnostics.h" -#include "rust-abi.h" #include "rust-common.h" #include "rust-identifier.h" +#include "rust-abi.h" #include "rust-tyty-bounds.h" #include "rust-tyty-util.h" #include "rust-tyty-subst.h" @@ -274,24 +272,12 @@ public: ParamType (std::string symbol, Location locus, HirId ref, HIR::GenericParam ¶m, std::vector specified_bounds, - std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::PARAM, - {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol), - locus}, - specified_bounds, refs), - symbol (symbol), param (param) - {} + std::set refs = std::set ()); ParamType (std::string symbol, Location locus, HirId ref, HirId ty_ref, HIR::GenericParam ¶m, std::vector specified_bounds, - std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::PARAM, - {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol), - locus}, - specified_bounds, refs), - symbol (symbol), param (param) - {} + std::set refs = std::set ()); void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; @@ -306,9 +292,9 @@ public: std::string get_symbol () const; - HIR::GenericParam &get_generic_param () { return param; } + HIR::GenericParam &get_generic_param (); - bool can_resolve () const { return get_ref () != get_ty_ref (); } + bool can_resolve () const; BaseType *resolve () const; @@ -316,14 +302,7 @@ public: bool is_equal (const BaseType &other) const override; - bool is_concrete () const override final - { - auto r = resolve (); - if (r == this) - return false; - - return r->is_concrete (); - } + bool is_concrete () const override final; ParamType *handle_substitions (SubstitutionArgumentMappings mappings); @@ -335,31 +314,25 @@ private: class StructFieldType { public: - StructFieldType (HirId ref, std::string name, BaseType *ty, Location locus) - : ref (ref), name (name), ty (ty), locus (locus) - {} - - HirId get_ref () const { return ref; } + StructFieldType (HirId ref, std::string name, BaseType *ty, Location locus); - std::string as_string () const; + HirId get_ref () const; bool is_equal (const StructFieldType &other) const; - std::string get_name () const { return name; } - - BaseType *get_field_type () const { return ty; } + std::string get_name () const; - void set_field_type (BaseType *fty) { ty = fty; } + BaseType *get_field_type () const; + void set_field_type (BaseType *fty); StructFieldType *clone () const; - StructFieldType *monomorphized_clone () const; - bool is_concrete () const { return ty->is_concrete (); } - - void debug () const { rust_debug ("%s", as_string ().c_str ()); } + bool is_concrete () const; - Location get_locus () const { return locus; } + void debug () const; + Location get_locus () const; + std::string as_string () const; private: HirId ref; @@ -373,29 +346,18 @@ class TupleType : public BaseType public: TupleType (HirId ref, Location locus, std::vector fields = std::vector (), - std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::TUPLE, - {Resolver::CanonicalPath::create_empty (), locus}, refs), - fields (fields) - {} + std::set refs = std::set ()); TupleType (HirId ref, HirId ty_ref, Location locus, std::vector fields = std::vector (), - std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::TUPLE, - {Resolver::CanonicalPath::create_empty (), locus}, refs), - fields (fields) - {} + std::set refs = std::set ()); - static TupleType *get_unit_type (HirId ref) - { - return new TupleType (ref, Linemap::predeclared_location ()); - } + static TupleType *get_unit_type (HirId ref); void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; - bool is_unit () const override { return this->fields.empty (); } + bool is_unit () const override; std::string as_string () const override; @@ -404,24 +366,16 @@ public: bool is_equal (const BaseType &other) const override; - size_t num_fields () const { return fields.size (); } + size_t num_fields () const; BaseType *get_field (size_t index) const; BaseType *clone () const final override; BaseType *monomorphized_clone () const final override; - bool is_concrete () const override final - { - for (size_t i = 0; i < num_fields (); i++) - { - if (!get_field (i)->is_concrete ()) - return false; - } - return true; - } + bool is_concrete () const override final; - const std::vector &get_fields () const { return fields; } + const std::vector &get_fields () const; std::string get_name () const override final; @@ -507,185 +461,48 @@ public: STRUCT }; - static std::string variant_type_string (VariantType type) - { - switch (type) - { - case NUM: - return "enumeral"; - case TUPLE: - return "tuple"; - case STRUCT: - return "struct"; - } - gcc_unreachable (); - return ""; - } + static std::string variant_type_string (VariantType type); VariantDef (HirId id, DefId defid, std::string identifier, RustIdent ident, - HIR::Expr *discriminant) - : id (id), defid (defid), identifier (identifier), ident (ident), - discriminant (discriminant) - - { - type = VariantType::NUM; - fields = {}; - } + HIR::Expr *discriminant); VariantDef (HirId id, DefId defid, std::string identifier, RustIdent ident, VariantType type, HIR::Expr *discriminant, - std::vector fields) - : id (id), defid (defid), identifier (identifier), ident (ident), - type (type), discriminant (discriminant), fields (fields) - { - rust_assert ( - (type == VariantType::NUM && fields.empty ()) - || (type == VariantType::TUPLE || type == VariantType::STRUCT)); - } + std::vector fields); - VariantDef (const VariantDef &other) - : id (other.id), defid (other.defid), identifier (other.identifier), - ident (other.ident), type (other.type), discriminant (other.discriminant), - fields (other.fields) - {} + VariantDef (const VariantDef &other); - VariantDef &operator= (const VariantDef &other) - { - id = other.id; - identifier = other.identifier; - type = other.type; - discriminant = other.discriminant; - fields = other.fields; - ident = other.ident; - - return *this; - } + VariantDef &operator= (const VariantDef &other); - static VariantDef &get_error_node () - { - static VariantDef node - = VariantDef (UNKNOWN_HIRID, UNKNOWN_DEFID, "", - {Resolver::CanonicalPath::create_empty (), - Linemap::unknown_location ()}, - nullptr); + static VariantDef &get_error_node (); + bool is_error () const; - return node; - } + HirId get_id () const; + DefId get_defid () const; - bool is_error () const { return get_id () == UNKNOWN_HIRID; } + VariantType get_variant_type () const; + bool is_data_variant () const; + bool is_dataless_variant () const; - HirId get_id () const { return id; } - DefId get_defid () const { return defid; } + std::string get_identifier () const; - VariantType get_variant_type () const { return type; } - bool is_data_variant () const { return type != VariantType::NUM; } - bool is_dataless_variant () const { return type == VariantType::NUM; } + size_t num_fields () const; + StructFieldType *get_field_at_index (size_t index); - std::string get_identifier () const { return identifier; } - - size_t num_fields () const { return fields.size (); } - StructFieldType *get_field_at_index (size_t index) - { - rust_assert (index < fields.size ()); - return fields.at (index); - } - - std::vector &get_fields () - { - rust_assert (type != NUM); - return fields; - } + std::vector &get_fields (); bool lookup_field (const std::string &lookup, StructFieldType **field_lookup, - size_t *index) const - { - size_t i = 0; - for (auto &field : fields) - { - if (field->get_name ().compare (lookup) == 0) - { - if (index != nullptr) - *index = i; - - if (field_lookup != nullptr) - *field_lookup = field; - - return true; - } - i++; - } - return false; - } - - HIR::Expr *get_discriminant () const - { - rust_assert (discriminant != nullptr); - return discriminant; - } - - std::string as_string () const - { - if (type == VariantType::NUM) - return identifier + " = " + discriminant->as_string (); - - std::string buffer; - for (size_t i = 0; i < fields.size (); ++i) - { - buffer += fields.at (i)->as_string (); - if ((i + 1) < fields.size ()) - buffer += ", "; - } - - if (type == VariantType::TUPLE) - return identifier + " (" + buffer + ")"; - else - return identifier + " {" + buffer + "}"; - } - - bool is_equal (const VariantDef &other) const - { - if (type != other.type) - return false; - - if (identifier.compare (other.identifier) != 0) - return false; + size_t *index) const; - if (discriminant != other.discriminant) - return false; - - if (fields.size () != other.fields.size ()) - return false; - - for (size_t i = 0; i < fields.size (); i++) - { - if (!fields.at (i)->is_equal (*other.fields.at (i))) - return false; - } - - return true; - } - - VariantDef *clone () const - { - std::vector cloned_fields; - for (auto &f : fields) - cloned_fields.push_back ((StructFieldType *) f->clone ()); + HIR::Expr *get_discriminant () const; - return new VariantDef (id, defid, identifier, ident, type, discriminant, - cloned_fields); - } + std::string as_string () const; - VariantDef *monomorphized_clone () const - { - std::vector cloned_fields; - for (auto &f : fields) - cloned_fields.push_back ((StructFieldType *) f->monomorphized_clone ()); + bool is_equal (const VariantDef &other) const; + VariantDef *clone () const; + VariantDef *monomorphized_clone () const; - return new VariantDef (id, defid, identifier, ident, type, discriminant, - cloned_fields); - } - - const RustIdent &get_ident () const { return ident; } + const RustIdent &get_ident () const; private: HirId id; @@ -1262,33 +1079,22 @@ private: class BoolType : public BaseType { public: - BoolType (HirId ref, std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::BOOL, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs) - {} - - BoolType (HirId ref, HirId ty_ref, std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::BOOL, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs) - {} + BoolType (HirId ref, std::set refs = std::set ()); + BoolType (HirId ref, HirId ty_ref, std::set refs = std::set ()); void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; std::string as_string () const override; - std::string get_name () const override final { return as_string (); } + std::string get_name () const override final; BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; BaseType *clone () const final override; BaseType *monomorphized_clone () const final override; - bool is_concrete () const override final { return true; } + bool is_concrete () const override final; }; class IntType : public BaseType @@ -1303,40 +1109,27 @@ public: I128 }; - IntType (HirId ref, IntKind kind, std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::INT, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs), - int_kind (kind) - {} - + IntType (HirId ref, IntKind kind, std::set refs = std::set ()); IntType (HirId ref, HirId ty_ref, IntKind kind, - std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::INT, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs), - int_kind (kind) - {} + std::set refs = std::set ()); void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; std::string as_string () const override; - std::string get_name () const override final { return as_string (); } + std::string get_name () const override final; BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; - IntKind get_int_kind () const { return int_kind; } + IntKind get_int_kind () const; BaseType *clone () const final override; BaseType *monomorphized_clone () const final override; bool is_equal (const BaseType &other) const override; - bool is_concrete () const override final { return true; } + bool is_concrete () const override final; private: IntKind int_kind; @@ -1354,40 +1147,28 @@ public: U128 }; - UintType (HirId ref, UintKind kind, std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::UINT, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs), - uint_kind (kind) - {} - + UintType (HirId ref, UintKind kind, + std::set refs = std::set ()); UintType (HirId ref, HirId ty_ref, UintKind kind, - std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::UINT, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs), - uint_kind (kind) - {} + std::set refs = std::set ()); void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; std::string as_string () const override; - std::string get_name () const override final { return as_string (); } + std::string get_name () const override final; BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; - UintKind get_uint_kind () const { return uint_kind; } + UintKind get_uint_kind () const; BaseType *clone () const final override; BaseType *monomorphized_clone () const final override; bool is_equal (const BaseType &other) const override; - bool is_concrete () const override final { return true; } + bool is_concrete () const override final; private: UintKind uint_kind; @@ -1403,40 +1184,26 @@ public: }; FloatType (HirId ref, FloatKind kind, - std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::FLOAT, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs), - float_kind (kind) - {} - + std::set refs = std::set ()); FloatType (HirId ref, HirId ty_ref, FloatKind kind, - std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::FLOAT, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs), - float_kind (kind) - {} + std::set refs = std::set ()); void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; std::string as_string () const override; - - std::string get_name () const override final { return as_string (); } + std::string get_name () const override final; BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; - FloatKind get_float_kind () const { return float_kind; } + FloatKind get_float_kind () const; BaseType *clone () const final override; BaseType *monomorphized_clone () const final override; bool is_equal (const BaseType &other) const override; - bool is_concrete () const override final { return true; } + bool is_concrete () const override final; private: FloatKind float_kind; @@ -1445,117 +1212,72 @@ private: class USizeType : public BaseType { public: - USizeType (HirId ref, std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::USIZE, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs) - {} - - USizeType (HirId ref, HirId ty_ref, std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::USIZE, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs) - {} + USizeType (HirId ref, std::set refs = std::set ()); + USizeType (HirId ref, HirId ty_ref, + std::set refs = std::set ()); void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; std::string as_string () const override; - - std::string get_name () const override final { return as_string (); } + std::string get_name () const override final; BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; BaseType *clone () const final override; BaseType *monomorphized_clone () const final override; - bool is_concrete () const override final { return true; } + bool is_concrete () const override final; }; class ISizeType : public BaseType { public: - ISizeType (HirId ref, std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::ISIZE, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs) - {} - - ISizeType (HirId ref, HirId ty_ref, std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::ISIZE, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs) - {} + ISizeType (HirId ref, std::set refs = std::set ()); + ISizeType (HirId ref, HirId ty_ref, + std::set refs = std::set ()); void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; std::string as_string () const override; - - std::string get_name () const override final { return as_string (); } + std::string get_name () const override final; BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; BaseType *clone () const final override; BaseType *monomorphized_clone () const final override; - bool is_concrete () const override final { return true; } + bool is_concrete () const override final; }; class CharType : public BaseType { public: - CharType (HirId ref, std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::CHAR, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs) - {} - - CharType (HirId ref, HirId ty_ref, std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::CHAR, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs) - {} + CharType (HirId ref, std::set refs = std::set ()); + CharType (HirId ref, HirId ty_ref, std::set refs = std::set ()); void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; std::string as_string () const override; - - std::string get_name () const override final { return as_string (); } + std::string get_name () const override final; BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; BaseType *clone () const final override; BaseType *monomorphized_clone () const final override; - bool is_concrete () const override final { return true; } + bool is_concrete () const override final; }; class StrType : public BaseType { public: - StrType (HirId ref, std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::STR, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs) - {} - - StrType (HirId ref, HirId ty_ref, std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::STR, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs) - {} + StrType (HirId ref, std::set refs = std::set ()); + StrType (HirId ref, HirId ty_ref, std::set refs = std::set ()); - std::string get_name () const override final { return as_string (); } + std::string get_name () const override final; void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; @@ -1569,29 +1291,16 @@ public: BaseType *clone () const final override; BaseType *monomorphized_clone () const final override; - bool is_concrete () const override final { return true; } + bool is_concrete () const override final; }; class ReferenceType : public BaseType { public: ReferenceType (HirId ref, TyVar base, Mutability mut, - std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::REF, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs), - base (base), mut (mut) - {} - + std::set refs = std::set ()); ReferenceType (HirId ref, HirId ty_ref, TyVar base, Mutability mut, - std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::REF, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs), - base (base), mut (mut) - {} + std::set refs = std::set ()); BaseType *get_base () const; @@ -1610,45 +1319,19 @@ public: BaseType *clone () const final override; BaseType *monomorphized_clone () const final override; - bool is_concrete () const override final - { - return get_base ()->is_concrete (); - } + bool is_concrete () const override final; ReferenceType *handle_substitions (SubstitutionArgumentMappings mappings); - Mutability mutability () const { return mut; } + Mutability mutability () const; - bool is_mutable () const { return mut == Mutability::Mut; } + bool is_mutable () const; - bool is_dyn_object () const - { - return is_dyn_slice_type () || is_dyn_str_type (); - } + bool is_dyn_object () const; - bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const - { - const TyTy::BaseType *element = get_base ()->destructure (); - if (element->get_kind () != TyTy::TypeKind::SLICE) - return false; - if (slice == nullptr) - return true; + bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const; - *slice = static_cast (element); - return true; - } - - bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const - { - const TyTy::BaseType *element = get_base ()->destructure (); - if (element->get_kind () != TyTy::TypeKind::STR) - return false; - if (str == nullptr) - return true; - - *str = static_cast (element); - return true; - } + bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const; private: TyVar base; @@ -1659,22 +1342,9 @@ class PointerType : public BaseType { public: PointerType (HirId ref, TyVar base, Mutability mut, - std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::POINTER, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs), - base (base), mut (mut) - {} - + std::set refs = std::set ()); PointerType (HirId ref, HirId ty_ref, TyVar base, Mutability mut, - std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::POINTER, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs), - base (base), mut (mut) - {} + std::set refs = std::set ()); BaseType *get_base () const; @@ -1692,47 +1362,17 @@ public: BaseType *clone () const final override; BaseType *monomorphized_clone () const final override; - bool is_concrete () const override final - { - return get_base ()->is_concrete (); - } + bool is_concrete () const override final; PointerType *handle_substitions (SubstitutionArgumentMappings mappings); - Mutability mutability () const { return mut; } - - bool is_mutable () const { return mut == Mutability::Mut; } - - bool is_const () const { return mut == Mutability::Imm; } - - bool is_dyn_object () const - { - return is_dyn_slice_type () || is_dyn_str_type (); - } - - bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const - { - const TyTy::BaseType *element = get_base ()->destructure (); - if (element->get_kind () != TyTy::TypeKind::SLICE) - return false; - if (slice == nullptr) - return true; + Mutability mutability () const; + bool is_mutable () const; + bool is_const () const; + bool is_dyn_object () const; - *slice = static_cast (element); - return true; - } - - bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const - { - const TyTy::BaseType *element = get_base ()->destructure (); - if (element->get_kind () != TyTy::TypeKind::STR) - return false; - if (str == nullptr) - return true; - - *str = static_cast (element); - return true; - } + bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const; + bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const; private: TyVar base; @@ -1752,19 +1392,9 @@ private: class NeverType : public BaseType { public: - NeverType (HirId ref, std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::NEVER, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs) - {} - - NeverType (HirId ref, HirId ty_ref, std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::NEVER, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs) - {} + NeverType (HirId ref, std::set refs = std::set ()); + NeverType (HirId ref, HirId ty_ref, + std::set refs = std::set ()); void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; @@ -1777,10 +1407,10 @@ public: BaseType *clone () const final override; BaseType *monomorphized_clone () const final override; - std::string get_name () const override final { return as_string (); } + std::string get_name () const override final; - bool is_unit () const override { return true; } - bool is_concrete () const override final { return true; } + bool is_unit () const override; + bool is_concrete () const override final; }; // used at the type in associated types in traits @@ -1789,22 +1419,9 @@ class PlaceholderType : public BaseType { public: PlaceholderType (std::string symbol, HirId ref, - std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::PLACEHOLDER, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs), - symbol (symbol) - {} - + std::set refs = std::set ()); PlaceholderType (std::string symbol, HirId ref, HirId ty_ref, - std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::PLACEHOLDER, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs), - symbol (symbol) - {} + std::set refs = std::set ()); void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; @@ -1817,15 +1434,11 @@ public: BaseType *clone () const final override; BaseType *monomorphized_clone () const final override; - std::string get_name () const override final { return as_string (); } + std::string get_name () const override final; - bool is_unit () const override - { - rust_assert (can_resolve ()); - return resolve ()->is_unit (); - } + bool is_unit () const override; - std::string get_symbol () const { return symbol; } + std::string get_symbol () const; void set_associated_type (HirId ref); @@ -1837,13 +1450,7 @@ public: bool is_equal (const BaseType &other) const override; - bool is_concrete () const override final - { - if (!can_resolve ()) - return true; - - return resolve ()->is_concrete (); - } + bool is_concrete () const override final; private: std::string symbol; @@ -1857,28 +1464,14 @@ public: std::vector subst_refs, SubstitutionArgumentMappings generic_arguments = SubstitutionArgumentMappings::error (), - std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::PROJECTION, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs), - SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)), - base (base), trait (trait), item (item) - {} + std::set refs = std::set ()); ProjectionType (HirId ref, HirId ty_ref, BaseType *base, const Resolver::TraitReference *trait, DefId item, std::vector subst_refs, SubstitutionArgumentMappings generic_arguments = SubstitutionArgumentMappings::error (), - std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::PROJECTION, - {Resolver::CanonicalPath::create_empty (), - Linemap::predeclared_location ()}, - refs), - SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)), - base (base), trait (trait), item (item) - {} + std::set refs = std::set ()); void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; @@ -1891,26 +1484,20 @@ public: BaseType *clone () const final override; BaseType *monomorphized_clone () const final override; - std::string get_name () const override final { return as_string (); } + std::string get_name () const override final; - bool is_unit () const override { return false; } + bool is_unit () const override; - bool needs_generic_substitutions () const override final - { - return needs_substitution (); - } + bool needs_generic_substitutions () const override final; - bool supports_substitutions () const override final { return true; } + bool supports_substitutions () const override final; - bool has_subsititions_defined () const override final - { - return has_substitutions (); - } + bool has_subsititions_defined () const override final; - const BaseType *get () const { return base; } - BaseType *get () { return base; } + const BaseType *get () const; + BaseType *get (); - bool is_concrete () const override final { return base->is_concrete (); } + bool is_concrete () const override final; ProjectionType * handle_substitions (SubstitutionArgumentMappings mappings) override final; @@ -1926,15 +1513,11 @@ class DynamicObjectType : public BaseType public: DynamicObjectType (HirId ref, RustIdent ident, std::vector specified_bounds, - std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::DYNAMIC, ident, specified_bounds, refs) - {} + std::set refs = std::set ()); DynamicObjectType (HirId ref, HirId ty_ref, RustIdent ident, std::vector specified_bounds, - std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::DYNAMIC, ident, specified_bounds, refs) - {} + std::set refs = std::set ()); void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; @@ -1951,7 +1534,7 @@ public: std::string get_name () const override final; - bool is_concrete () const override final { return true; } + bool is_concrete () const override final; // this returns a flat list of items including super trait bounds const std::vector< -- cgit v1.1 From 56a21f487f4ae2203727d4940812bff160f5f85c Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 16 Jan 2023 19:31:11 +0000 Subject: gccrs: Rename rust-tyctx.cc to rust-typecheck-context.cc Signed-off-by: Philip Herron gcc/rust/ChangeLog: * Make-lang.in: update name * typecheck/rust-tyctx.cc: Moved to... * typecheck/rust-typecheck-context.cc: ...here. --- gcc/rust/Make-lang.in | 2 +- gcc/rust/typecheck/rust-tyctx.cc | 569 --------------------------- gcc/rust/typecheck/rust-typecheck-context.cc | 569 +++++++++++++++++++++++++++ 3 files changed, 570 insertions(+), 570 deletions(-) delete mode 100644 gcc/rust/typecheck/rust-tyctx.cc create mode 100644 gcc/rust/typecheck/rust-typecheck-context.cc (limited to 'gcc') diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 82d5c5d..5f5cee7 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -118,7 +118,7 @@ GRS_OBJS = \ rust/rust-tyty-util.o \ rust/rust-tyty-call.o \ rust/rust-tyty-subst.o \ - rust/rust-tyctx.o \ + rust/rust-typecheck-context.o \ rust/rust-tyty-bounds.o \ rust/rust-hir-type-check-util.o \ rust/rust-hir-trait-resolve.o \ diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc deleted file mode 100644 index ba4d322..0000000 --- a/gcc/rust/typecheck/rust-tyctx.cc +++ /dev/null @@ -1,569 +0,0 @@ -// Copyright (C) 2020-2022 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#include "rust-hir-type-check.h" - -namespace Rust { -namespace Resolver { - -TypeCheckContext * -TypeCheckContext::get () -{ - static TypeCheckContext *instance; - if (instance == nullptr) - instance = new TypeCheckContext (); - - return instance; -} - -TypeCheckContext::TypeCheckContext () {} - -TypeCheckContext::~TypeCheckContext () {} - -bool -TypeCheckContext::lookup_builtin (NodeId id, TyTy::BaseType **type) -{ - auto ref_it = node_id_refs.find (id); - if (ref_it == node_id_refs.end ()) - return false; - - auto it = resolved.find (ref_it->second); - if (it == resolved.end ()) - return false; - - *type = it->second; - return true; -} - -bool -TypeCheckContext::lookup_builtin (std::string name, TyTy::BaseType **type) -{ - for (auto &builtin : builtins) - { - if (name.compare (builtin->as_string ()) == 0) - { - *type = builtin.get (); - return true; - } - } - return false; -} - -void -TypeCheckContext::insert_builtin (HirId id, NodeId ref, TyTy::BaseType *type) -{ - node_id_refs[ref] = id; - resolved[id] = type; - builtins.push_back (std::unique_ptr (type)); -} - -void -TypeCheckContext::insert_type (const Analysis::NodeMapping &mappings, - TyTy::BaseType *type) -{ - rust_assert (type != nullptr); - NodeId ref = mappings.get_nodeid (); - HirId id = mappings.get_hirid (); - node_id_refs[ref] = id; - resolved[id] = type; -} - -void -TypeCheckContext::insert_implicit_type (TyTy::BaseType *type) -{ - rust_assert (type != nullptr); - resolved[type->get_ref ()] = type; -} - -void -TypeCheckContext::insert_implicit_type (HirId id, TyTy::BaseType *type) -{ - rust_assert (type != nullptr); - resolved[id] = type; -} - -bool -TypeCheckContext::lookup_type (HirId id, TyTy::BaseType **type) const -{ - auto it = resolved.find (id); - if (it == resolved.end ()) - return false; - - *type = it->second; - return true; -} - -void -TypeCheckContext::insert_type_by_node_id (NodeId ref, HirId id) -{ - rust_assert (node_id_refs.find (ref) == node_id_refs.end ()); - node_id_refs[ref] = id; -} - -bool -TypeCheckContext::lookup_type_by_node_id (NodeId ref, HirId *id) -{ - auto it = node_id_refs.find (ref); - if (it == node_id_refs.end ()) - return false; - - *id = it->second; - return true; -} - -TyTy::BaseType * -TypeCheckContext::peek_return_type () -{ - rust_assert (!return_type_stack.empty ()); - return return_type_stack.back ().second; -} - -void -TypeCheckContext::push_return_type (TypeCheckContextItem item, - TyTy::BaseType *return_type) -{ - return_type_stack.push_back ({std::move (item), return_type}); -} - -void -TypeCheckContext::pop_return_type () -{ - rust_assert (!return_type_stack.empty ()); - return_type_stack.pop_back (); -} - -TypeCheckContextItem & -TypeCheckContext::peek_context () -{ - rust_assert (!return_type_stack.empty ()); - return return_type_stack.back ().first; -} - -void -TypeCheckContext::iterate (std::function cb) -{ - for (auto it = resolved.begin (); it != resolved.end (); it++) - { - if (!cb (it->first, it->second)) - return; - } -} - -bool -TypeCheckContext::have_loop_context () const -{ - return !loop_type_stack.empty (); -} - -void -TypeCheckContext::push_new_loop_context (HirId id, Location locus) -{ - TyTy::BaseType *infer_var - = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL, locus); - loop_type_stack.push_back (infer_var); -} - -void -TypeCheckContext::push_new_while_loop_context (HirId id) -{ - TyTy::BaseType *infer_var = new TyTy::ErrorType (id); - loop_type_stack.push_back (infer_var); -} - -TyTy::BaseType * -TypeCheckContext::peek_loop_context () -{ - return loop_type_stack.back (); -} - -TyTy::BaseType * -TypeCheckContext::pop_loop_context () -{ - auto back = peek_loop_context (); - loop_type_stack.pop_back (); - return back; -} - -void -TypeCheckContext::swap_head_loop_context (TyTy::BaseType *val) -{ - loop_type_stack.pop_back (); - loop_type_stack.push_back (val); -} - -void -TypeCheckContext::insert_trait_reference (DefId id, TraitReference &&ref) -{ - rust_assert (trait_context.find (id) == trait_context.end ()); - trait_context.emplace (id, std::move (ref)); -} - -bool -TypeCheckContext::lookup_trait_reference (DefId id, TraitReference **ref) -{ - auto it = trait_context.find (id); - if (it == trait_context.end ()) - return false; - - *ref = &it->second; - return true; -} - -void -TypeCheckContext::insert_receiver (HirId id, TyTy::BaseType *t) -{ - receiver_context[id] = t; -} - -bool -TypeCheckContext::lookup_receiver (HirId id, TyTy::BaseType **ref) -{ - auto it = receiver_context.find (id); - if (it == receiver_context.end ()) - return false; - - *ref = it->second; - return true; -} - -void -TypeCheckContext::insert_associated_trait_impl ( - HirId id, AssociatedImplTrait &&associated) -{ - rust_assert (associated_impl_traits.find (id) - == associated_impl_traits.end ()); - associated_impl_traits.emplace (id, std::move (associated)); -} - -bool -TypeCheckContext::lookup_associated_trait_impl ( - HirId id, AssociatedImplTrait **associated) -{ - auto it = associated_impl_traits.find (id); - if (it == associated_impl_traits.end ()) - return false; - - *associated = &it->second; - return true; -} - -void -TypeCheckContext::insert_associated_type_mapping (HirId id, HirId mapping) -{ - associated_type_mappings[id] = mapping; -} - -void -TypeCheckContext::clear_associated_type_mapping (HirId id) -{ - auto it = associated_type_mappings.find (id); - if (it != associated_type_mappings.end ()) - associated_type_mappings.erase (it); -} - -// lookup any associated type mappings, the out parameter of mapping is -// allowed to be nullptr which allows this interface to do a simple does exist -// check -bool -TypeCheckContext::lookup_associated_type_mapping (HirId id, HirId *mapping) -{ - auto it = associated_type_mappings.find (id); - if (it == associated_type_mappings.end ()) - return false; - - if (mapping != nullptr) - *mapping = it->second; - - return true; -} - -void -TypeCheckContext::insert_associated_impl_mapping ( - HirId trait_id, const TyTy::BaseType *impl_type, HirId impl_id) -{ - auto it = associated_traits_to_impls.find (trait_id); - if (it == associated_traits_to_impls.end ()) - { - associated_traits_to_impls[trait_id] = {}; - } - - associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id}); -} - -bool -TypeCheckContext::lookup_associated_impl_mapping_for_self ( - HirId trait_id, const TyTy::BaseType *self, HirId *mapping) -{ - auto it = associated_traits_to_impls.find (trait_id); - if (it == associated_traits_to_impls.end ()) - return false; - - for (auto &item : it->second) - { - if (item.first->can_eq (self, false)) - { - *mapping = item.second; - return true; - } - } - return false; -} - -void -TypeCheckContext::insert_autoderef_mappings ( - HirId id, std::vector &&adjustments) -{ - rust_assert (autoderef_mappings.find (id) == autoderef_mappings.end ()); - autoderef_mappings.emplace (id, std::move (adjustments)); -} - -bool -TypeCheckContext::lookup_autoderef_mappings ( - HirId id, std::vector **adjustments) -{ - auto it = autoderef_mappings.find (id); - if (it == autoderef_mappings.end ()) - return false; - - *adjustments = &it->second; - return true; -} - -void -TypeCheckContext::insert_cast_autoderef_mappings ( - HirId id, std::vector &&adjustments) -{ - rust_assert (cast_autoderef_mappings.find (id) - == cast_autoderef_mappings.end ()); - cast_autoderef_mappings.emplace (id, std::move (adjustments)); -} - -bool -TypeCheckContext::lookup_cast_autoderef_mappings ( - HirId id, std::vector **adjustments) -{ - auto it = cast_autoderef_mappings.find (id); - if (it == cast_autoderef_mappings.end ()) - return false; - - *adjustments = &it->second; - return true; -} - -void -TypeCheckContext::insert_variant_definition (HirId id, HirId variant) -{ - auto it = variants.find (id); - rust_assert (it == variants.end ()); - - variants[id] = variant; -} - -bool -TypeCheckContext::lookup_variant_definition (HirId id, HirId *variant) -{ - auto it = variants.find (id); - if (it == variants.end ()) - return false; - - *variant = it->second; - return true; -} - -void -TypeCheckContext::insert_operator_overload (HirId id, TyTy::FnType *call_site) -{ - auto it = operator_overloads.find (id); - rust_assert (it == operator_overloads.end ()); - - operator_overloads[id] = call_site; -} - -bool -TypeCheckContext::lookup_operator_overload (HirId id, TyTy::FnType **call) -{ - auto it = operator_overloads.find (id); - if (it == operator_overloads.end ()) - return false; - - *call = it->second; - return true; -} - -void -TypeCheckContext::insert_unconstrained_check_marker (HirId id, bool status) -{ - unconstrained[id] = status; -} - -bool -TypeCheckContext::have_checked_for_unconstrained (HirId id, bool *result) -{ - auto it = unconstrained.find (id); - bool found = it != unconstrained.end (); - if (!found) - return false; - - *result = it->second; - return true; -} - -void -TypeCheckContext::insert_resolved_predicate (HirId id, - TyTy::TypeBoundPredicate predicate) -{ - auto it = predicates.find (id); - rust_assert (it == predicates.end ()); - - predicates.insert ({id, predicate}); -} - -bool -TypeCheckContext::lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result) -{ - auto it = predicates.find (id); - bool found = it != predicates.end (); - if (!found) - return false; - - *result = it->second; - return true; -} - -void -TypeCheckContext::insert_query (HirId id) -{ - querys_in_progress.insert (id); -} - -void -TypeCheckContext::query_completed (HirId id) -{ - querys_in_progress.erase (id); -} - -bool -TypeCheckContext::query_in_progress (HirId id) const -{ - return querys_in_progress.find (id) != querys_in_progress.end (); -} - -void -TypeCheckContext::insert_trait_query (DefId id) -{ - trait_queries_in_progress.insert (id); -} - -void -TypeCheckContext::trait_query_completed (DefId id) -{ - trait_queries_in_progress.erase (id); -} - -bool -TypeCheckContext::trait_query_in_progress (DefId id) const -{ - return trait_queries_in_progress.find (id) - != trait_queries_in_progress.end (); -} - -// TypeCheckContextItem - -TypeCheckContextItem::Item::Item (HIR::Function *item) : item (item) {} - -TypeCheckContextItem::Item::Item (HIR::ImplBlock *impl_block, - HIR::Function *item) - : impl_item ({impl_block, item}) -{} - -TypeCheckContextItem::Item::Item (HIR::TraitItemFunc *trait_item) - : trait_item (trait_item) -{} - -TypeCheckContextItem::TypeCheckContextItem (HIR::Function *item) - : type (ItemType::ITEM), item (item) -{} - -TypeCheckContextItem::TypeCheckContextItem (HIR::ImplBlock *impl_block, - HIR::Function *item) - : type (ItemType::IMPL_ITEM), item (impl_block, item) -{} - -TypeCheckContextItem::TypeCheckContextItem (HIR::TraitItemFunc *trait_item) - : type (ItemType::TRAIT_ITEM), item (trait_item) -{} - -HIR::Function * -TypeCheckContextItem::get_item () -{ - rust_assert (get_type () == ItemType::ITEM); - return item.item; -} - -std::pair & -TypeCheckContextItem::get_impl_item () -{ - rust_assert (get_type () == ItemType::IMPL_ITEM); - return item.impl_item; -} - -HIR::TraitItemFunc * -TypeCheckContextItem::get_trait_item () -{ - rust_assert (get_type () == ItemType::TRAIT_ITEM); - return item.trait_item; -} - -TypeCheckContextItem::ItemType -TypeCheckContextItem::get_type () const -{ - return type; -} - -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-typecheck-context.cc b/gcc/rust/typecheck/rust-typecheck-context.cc new file mode 100644 index 0000000..ba4d322 --- /dev/null +++ b/gcc/rust/typecheck/rust-typecheck-context.cc @@ -0,0 +1,569 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#include "rust-hir-type-check.h" + +namespace Rust { +namespace Resolver { + +TypeCheckContext * +TypeCheckContext::get () +{ + static TypeCheckContext *instance; + if (instance == nullptr) + instance = new TypeCheckContext (); + + return instance; +} + +TypeCheckContext::TypeCheckContext () {} + +TypeCheckContext::~TypeCheckContext () {} + +bool +TypeCheckContext::lookup_builtin (NodeId id, TyTy::BaseType **type) +{ + auto ref_it = node_id_refs.find (id); + if (ref_it == node_id_refs.end ()) + return false; + + auto it = resolved.find (ref_it->second); + if (it == resolved.end ()) + return false; + + *type = it->second; + return true; +} + +bool +TypeCheckContext::lookup_builtin (std::string name, TyTy::BaseType **type) +{ + for (auto &builtin : builtins) + { + if (name.compare (builtin->as_string ()) == 0) + { + *type = builtin.get (); + return true; + } + } + return false; +} + +void +TypeCheckContext::insert_builtin (HirId id, NodeId ref, TyTy::BaseType *type) +{ + node_id_refs[ref] = id; + resolved[id] = type; + builtins.push_back (std::unique_ptr (type)); +} + +void +TypeCheckContext::insert_type (const Analysis::NodeMapping &mappings, + TyTy::BaseType *type) +{ + rust_assert (type != nullptr); + NodeId ref = mappings.get_nodeid (); + HirId id = mappings.get_hirid (); + node_id_refs[ref] = id; + resolved[id] = type; +} + +void +TypeCheckContext::insert_implicit_type (TyTy::BaseType *type) +{ + rust_assert (type != nullptr); + resolved[type->get_ref ()] = type; +} + +void +TypeCheckContext::insert_implicit_type (HirId id, TyTy::BaseType *type) +{ + rust_assert (type != nullptr); + resolved[id] = type; +} + +bool +TypeCheckContext::lookup_type (HirId id, TyTy::BaseType **type) const +{ + auto it = resolved.find (id); + if (it == resolved.end ()) + return false; + + *type = it->second; + return true; +} + +void +TypeCheckContext::insert_type_by_node_id (NodeId ref, HirId id) +{ + rust_assert (node_id_refs.find (ref) == node_id_refs.end ()); + node_id_refs[ref] = id; +} + +bool +TypeCheckContext::lookup_type_by_node_id (NodeId ref, HirId *id) +{ + auto it = node_id_refs.find (ref); + if (it == node_id_refs.end ()) + return false; + + *id = it->second; + return true; +} + +TyTy::BaseType * +TypeCheckContext::peek_return_type () +{ + rust_assert (!return_type_stack.empty ()); + return return_type_stack.back ().second; +} + +void +TypeCheckContext::push_return_type (TypeCheckContextItem item, + TyTy::BaseType *return_type) +{ + return_type_stack.push_back ({std::move (item), return_type}); +} + +void +TypeCheckContext::pop_return_type () +{ + rust_assert (!return_type_stack.empty ()); + return_type_stack.pop_back (); +} + +TypeCheckContextItem & +TypeCheckContext::peek_context () +{ + rust_assert (!return_type_stack.empty ()); + return return_type_stack.back ().first; +} + +void +TypeCheckContext::iterate (std::function cb) +{ + for (auto it = resolved.begin (); it != resolved.end (); it++) + { + if (!cb (it->first, it->second)) + return; + } +} + +bool +TypeCheckContext::have_loop_context () const +{ + return !loop_type_stack.empty (); +} + +void +TypeCheckContext::push_new_loop_context (HirId id, Location locus) +{ + TyTy::BaseType *infer_var + = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL, locus); + loop_type_stack.push_back (infer_var); +} + +void +TypeCheckContext::push_new_while_loop_context (HirId id) +{ + TyTy::BaseType *infer_var = new TyTy::ErrorType (id); + loop_type_stack.push_back (infer_var); +} + +TyTy::BaseType * +TypeCheckContext::peek_loop_context () +{ + return loop_type_stack.back (); +} + +TyTy::BaseType * +TypeCheckContext::pop_loop_context () +{ + auto back = peek_loop_context (); + loop_type_stack.pop_back (); + return back; +} + +void +TypeCheckContext::swap_head_loop_context (TyTy::BaseType *val) +{ + loop_type_stack.pop_back (); + loop_type_stack.push_back (val); +} + +void +TypeCheckContext::insert_trait_reference (DefId id, TraitReference &&ref) +{ + rust_assert (trait_context.find (id) == trait_context.end ()); + trait_context.emplace (id, std::move (ref)); +} + +bool +TypeCheckContext::lookup_trait_reference (DefId id, TraitReference **ref) +{ + auto it = trait_context.find (id); + if (it == trait_context.end ()) + return false; + + *ref = &it->second; + return true; +} + +void +TypeCheckContext::insert_receiver (HirId id, TyTy::BaseType *t) +{ + receiver_context[id] = t; +} + +bool +TypeCheckContext::lookup_receiver (HirId id, TyTy::BaseType **ref) +{ + auto it = receiver_context.find (id); + if (it == receiver_context.end ()) + return false; + + *ref = it->second; + return true; +} + +void +TypeCheckContext::insert_associated_trait_impl ( + HirId id, AssociatedImplTrait &&associated) +{ + rust_assert (associated_impl_traits.find (id) + == associated_impl_traits.end ()); + associated_impl_traits.emplace (id, std::move (associated)); +} + +bool +TypeCheckContext::lookup_associated_trait_impl ( + HirId id, AssociatedImplTrait **associated) +{ + auto it = associated_impl_traits.find (id); + if (it == associated_impl_traits.end ()) + return false; + + *associated = &it->second; + return true; +} + +void +TypeCheckContext::insert_associated_type_mapping (HirId id, HirId mapping) +{ + associated_type_mappings[id] = mapping; +} + +void +TypeCheckContext::clear_associated_type_mapping (HirId id) +{ + auto it = associated_type_mappings.find (id); + if (it != associated_type_mappings.end ()) + associated_type_mappings.erase (it); +} + +// lookup any associated type mappings, the out parameter of mapping is +// allowed to be nullptr which allows this interface to do a simple does exist +// check +bool +TypeCheckContext::lookup_associated_type_mapping (HirId id, HirId *mapping) +{ + auto it = associated_type_mappings.find (id); + if (it == associated_type_mappings.end ()) + return false; + + if (mapping != nullptr) + *mapping = it->second; + + return true; +} + +void +TypeCheckContext::insert_associated_impl_mapping ( + HirId trait_id, const TyTy::BaseType *impl_type, HirId impl_id) +{ + auto it = associated_traits_to_impls.find (trait_id); + if (it == associated_traits_to_impls.end ()) + { + associated_traits_to_impls[trait_id] = {}; + } + + associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id}); +} + +bool +TypeCheckContext::lookup_associated_impl_mapping_for_self ( + HirId trait_id, const TyTy::BaseType *self, HirId *mapping) +{ + auto it = associated_traits_to_impls.find (trait_id); + if (it == associated_traits_to_impls.end ()) + return false; + + for (auto &item : it->second) + { + if (item.first->can_eq (self, false)) + { + *mapping = item.second; + return true; + } + } + return false; +} + +void +TypeCheckContext::insert_autoderef_mappings ( + HirId id, std::vector &&adjustments) +{ + rust_assert (autoderef_mappings.find (id) == autoderef_mappings.end ()); + autoderef_mappings.emplace (id, std::move (adjustments)); +} + +bool +TypeCheckContext::lookup_autoderef_mappings ( + HirId id, std::vector **adjustments) +{ + auto it = autoderef_mappings.find (id); + if (it == autoderef_mappings.end ()) + return false; + + *adjustments = &it->second; + return true; +} + +void +TypeCheckContext::insert_cast_autoderef_mappings ( + HirId id, std::vector &&adjustments) +{ + rust_assert (cast_autoderef_mappings.find (id) + == cast_autoderef_mappings.end ()); + cast_autoderef_mappings.emplace (id, std::move (adjustments)); +} + +bool +TypeCheckContext::lookup_cast_autoderef_mappings ( + HirId id, std::vector **adjustments) +{ + auto it = cast_autoderef_mappings.find (id); + if (it == cast_autoderef_mappings.end ()) + return false; + + *adjustments = &it->second; + return true; +} + +void +TypeCheckContext::insert_variant_definition (HirId id, HirId variant) +{ + auto it = variants.find (id); + rust_assert (it == variants.end ()); + + variants[id] = variant; +} + +bool +TypeCheckContext::lookup_variant_definition (HirId id, HirId *variant) +{ + auto it = variants.find (id); + if (it == variants.end ()) + return false; + + *variant = it->second; + return true; +} + +void +TypeCheckContext::insert_operator_overload (HirId id, TyTy::FnType *call_site) +{ + auto it = operator_overloads.find (id); + rust_assert (it == operator_overloads.end ()); + + operator_overloads[id] = call_site; +} + +bool +TypeCheckContext::lookup_operator_overload (HirId id, TyTy::FnType **call) +{ + auto it = operator_overloads.find (id); + if (it == operator_overloads.end ()) + return false; + + *call = it->second; + return true; +} + +void +TypeCheckContext::insert_unconstrained_check_marker (HirId id, bool status) +{ + unconstrained[id] = status; +} + +bool +TypeCheckContext::have_checked_for_unconstrained (HirId id, bool *result) +{ + auto it = unconstrained.find (id); + bool found = it != unconstrained.end (); + if (!found) + return false; + + *result = it->second; + return true; +} + +void +TypeCheckContext::insert_resolved_predicate (HirId id, + TyTy::TypeBoundPredicate predicate) +{ + auto it = predicates.find (id); + rust_assert (it == predicates.end ()); + + predicates.insert ({id, predicate}); +} + +bool +TypeCheckContext::lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result) +{ + auto it = predicates.find (id); + bool found = it != predicates.end (); + if (!found) + return false; + + *result = it->second; + return true; +} + +void +TypeCheckContext::insert_query (HirId id) +{ + querys_in_progress.insert (id); +} + +void +TypeCheckContext::query_completed (HirId id) +{ + querys_in_progress.erase (id); +} + +bool +TypeCheckContext::query_in_progress (HirId id) const +{ + return querys_in_progress.find (id) != querys_in_progress.end (); +} + +void +TypeCheckContext::insert_trait_query (DefId id) +{ + trait_queries_in_progress.insert (id); +} + +void +TypeCheckContext::trait_query_completed (DefId id) +{ + trait_queries_in_progress.erase (id); +} + +bool +TypeCheckContext::trait_query_in_progress (DefId id) const +{ + return trait_queries_in_progress.find (id) + != trait_queries_in_progress.end (); +} + +// TypeCheckContextItem + +TypeCheckContextItem::Item::Item (HIR::Function *item) : item (item) {} + +TypeCheckContextItem::Item::Item (HIR::ImplBlock *impl_block, + HIR::Function *item) + : impl_item ({impl_block, item}) +{} + +TypeCheckContextItem::Item::Item (HIR::TraitItemFunc *trait_item) + : trait_item (trait_item) +{} + +TypeCheckContextItem::TypeCheckContextItem (HIR::Function *item) + : type (ItemType::ITEM), item (item) +{} + +TypeCheckContextItem::TypeCheckContextItem (HIR::ImplBlock *impl_block, + HIR::Function *item) + : type (ItemType::IMPL_ITEM), item (impl_block, item) +{} + +TypeCheckContextItem::TypeCheckContextItem (HIR::TraitItemFunc *trait_item) + : type (ItemType::TRAIT_ITEM), item (trait_item) +{} + +HIR::Function * +TypeCheckContextItem::get_item () +{ + rust_assert (get_type () == ItemType::ITEM); + return item.item; +} + +std::pair & +TypeCheckContextItem::get_impl_item () +{ + rust_assert (get_type () == ItemType::IMPL_ITEM); + return item.impl_item; +} + +HIR::TraitItemFunc * +TypeCheckContextItem::get_trait_item () +{ + rust_assert (get_type () == ItemType::TRAIT_ITEM); + return item.trait_item; +} + +TypeCheckContextItem::ItemType +TypeCheckContextItem::get_type () const +{ + return type; +} + +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 -- cgit v1.1 From 82d0550253b5524f0e612c4b576bf5889bbd2bb5 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 17 Jan 2023 22:45:52 +0000 Subject: gccrs: Rename header rust-hir-trait-ref.h to rust-hir-trait-reference.h Signed-off-by: Philip Herron gcc/rust/ChangeLog: * typecheck/rust-hir-trait-ref.h: Moved to... * typecheck/rust-hir-trait-reference.h: ...here. * typecheck/rust-hir-trait-resolve.cc: refactor * typecheck/rust-hir-trait-resolve.h (RUST_HIR_TRAIT_RESOLVE_H): likewise * typecheck/rust-hir-type-check.h: likewise * typecheck/rust-tyty.cc: likewise --- gcc/rust/typecheck/rust-hir-trait-ref.h | 515 -------------------------- gcc/rust/typecheck/rust-hir-trait-reference.h | 515 ++++++++++++++++++++++++++ gcc/rust/typecheck/rust-hir-trait-resolve.cc | 10 + gcc/rust/typecheck/rust-hir-trait-resolve.h | 9 +- gcc/rust/typecheck/rust-hir-type-check.h | 2 +- gcc/rust/typecheck/rust-tyty.cc | 2 +- 6 files changed, 528 insertions(+), 525 deletions(-) delete mode 100644 gcc/rust/typecheck/rust-hir-trait-ref.h create mode 100644 gcc/rust/typecheck/rust-hir-trait-reference.h (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-hir-trait-ref.h b/gcc/rust/typecheck/rust-hir-trait-ref.h deleted file mode 100644 index d0814f6..0000000 --- a/gcc/rust/typecheck/rust-hir-trait-ref.h +++ /dev/null @@ -1,515 +0,0 @@ -// Copyright (C) 2021-2022 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#ifndef RUST_HIR_TRAIT_REF_H -#define RUST_HIR_TRAIT_REF_H - -#include "rust-hir-full.h" -#include "rust-tyty-visitor.h" -#include "rust-hir-type-check-util.h" - -namespace Rust { -namespace Resolver { - -// Data Objects for the associated trait items in a structure we can work with -// https://doc.rust-lang.org/edition-guide/rust-2018/trait-system/associated-constants.html -class TypeCheckContext; -class TraitItemReference -{ -public: - enum TraitItemType - { - FN, - CONST, - TYPE, - ERROR - }; - - TraitItemReference (std::string identifier, bool optional, TraitItemType type, - HIR::TraitItem *hir_trait_item, TyTy::BaseType *self, - std::vector substitutions, - Location locus); - - TraitItemReference (TraitItemReference const &other); - - TraitItemReference &operator= (TraitItemReference const &other); - - static TraitItemReference error () - { - return TraitItemReference ("", false, ERROR, nullptr, nullptr, {}, - Location ()); - } - - static TraitItemReference &error_node () - { - static TraitItemReference error = TraitItemReference::error (); - return error; - } - - bool is_error () const { return type == ERROR; } - - std::string as_string () const - { - return "(" + trait_item_type_as_string (type) + " " + identifier + " " - + ")"; - } - - static std::string trait_item_type_as_string (TraitItemType ty) - { - switch (ty) - { - case FN: - return "FN"; - case CONST: - return "CONST"; - case TYPE: - return "TYPE"; - case ERROR: - return "ERROR"; - } - return "ERROR"; - } - - bool is_optional () const { return optional_flag; } - - std::string get_identifier () const { return identifier; } - - TraitItemType get_trait_item_type () const { return type; } - - HIR::TraitItem *get_hir_trait_item () const { return hir_trait_item; } - - Location get_locus () const { return locus; } - - const Analysis::NodeMapping get_mappings () const - { - return hir_trait_item->get_mappings (); - } - - TyTy::BaseType *get_tyty () const - { - rust_assert (hir_trait_item != nullptr); - - switch (type) - { - case CONST: - return get_type_from_constant ( - static_cast (*hir_trait_item)); - break; - - case TYPE: - return get_type_from_typealias ( - static_cast (*hir_trait_item)); - - case FN: - return get_type_from_fn ( - static_cast (*hir_trait_item)); - break; - - default: - return get_error (); - } - - gcc_unreachable (); - return get_error (); - } - - Analysis::NodeMapping get_parent_trait_mappings () const; - - // this is called when the trait is completed resolution and gives the items a - // chance to run their specific type resolution passes. If we call their - // resolution on construction it can lead to a case where the trait being - // resolved recursively trying to resolve the trait itself infinitely since - // the trait will not be stored in its own map yet - void on_resolved (); - - void associated_type_set (TyTy::BaseType *ty) const; - - void associated_type_reset () const; - - bool is_object_safe () const; - -private: - TyTy::ErrorType *get_error () const - { - return new TyTy::ErrorType (get_mappings ().get_hirid ()); - } - - TyTy::BaseType *get_type_from_typealias (/*const*/ - HIR::TraitItemType &type) const; - - TyTy::BaseType * - get_type_from_constant (/*const*/ HIR::TraitItemConst &constant) const; - - TyTy::BaseType *get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const; - - bool is_item_resolved () const; - void resolve_item (HIR::TraitItemType &type); - void resolve_item (HIR::TraitItemConst &constant); - void resolve_item (HIR::TraitItemFunc &func); - - std::string identifier; - bool optional_flag; - TraitItemType type; - HIR::TraitItem *hir_trait_item; - std::vector inherited_substitutions; - Location locus; - - TyTy::BaseType - *self; // this is the implict Self TypeParam required for methods - Resolver::TypeCheckContext *context; -}; - -// this wraps up the HIR::Trait so we can do analysis on it - -class TraitReference -{ -public: - TraitReference (const HIR::Trait *hir_trait_ref, - std::vector item_refs, - std::vector super_traits, - std::vector substs) - : hir_trait_ref (hir_trait_ref), item_refs (item_refs), - super_traits (super_traits) - { - trait_substs.clear (); - trait_substs.reserve (substs.size ()); - for (const auto &p : substs) - trait_substs.push_back (p.clone ()); - } - - TraitReference (TraitReference const &other) - : hir_trait_ref (other.hir_trait_ref), item_refs (other.item_refs), - super_traits (other.super_traits) - { - trait_substs.clear (); - trait_substs.reserve (other.trait_substs.size ()); - for (const auto &p : other.trait_substs) - trait_substs.push_back (p.clone ()); - } - - TraitReference &operator= (TraitReference const &other) - { - hir_trait_ref = other.hir_trait_ref; - item_refs = other.item_refs; - super_traits = other.super_traits; - - trait_substs.clear (); - trait_substs.reserve (other.trait_substs.size ()); - for (const auto &p : other.trait_substs) - trait_substs.push_back (p.clone ()); - - return *this; - } - - TraitReference (TraitReference &&other) = default; - TraitReference &operator= (TraitReference &&other) = default; - - static TraitReference error () - { - return TraitReference (nullptr, {}, {}, {}); - } - - bool is_error () const { return hir_trait_ref == nullptr; } - - static TraitReference &error_node () - { - static TraitReference trait_error_node = TraitReference::error (); - return trait_error_node; - } - - Location get_locus () const { return hir_trait_ref->get_locus (); } - - std::string get_name () const - { - rust_assert (!is_error ()); - return hir_trait_ref->get_name (); - } - - std::string as_string () const - { - if (is_error ()) - return ""; - - std::string item_buf; - for (auto &item : item_refs) - { - item_buf += item.as_string () + ", "; - } - return "HIR Trait: " + get_name () + "->" - + hir_trait_ref->get_mappings ().as_string () + " [" + item_buf - + "]"; - } - - const HIR::Trait *get_hir_trait_ref () const { return hir_trait_ref; } - - const Analysis::NodeMapping &get_mappings () const - { - return hir_trait_ref->get_mappings (); - } - - DefId get_defid () const { return get_mappings ().get_defid (); } - - bool lookup_hir_trait_item (const HIR::TraitItem &item, - TraitItemReference **ref) - { - return lookup_trait_item (item.trait_identifier (), ref); - } - - bool lookup_trait_item (const std::string &ident, TraitItemReference **ref) - { - for (auto &item : item_refs) - { - if (ident.compare (item.get_identifier ()) == 0) - { - *ref = &item; - return true; - } - } - return false; - } - - bool lookup_trait_item_by_type (const std::string &ident, - TraitItemReference::TraitItemType type, - TraitItemReference **ref) - { - for (auto &item : item_refs) - { - if (item.get_trait_item_type () != type) - continue; - - if (ident.compare (item.get_identifier ()) == 0) - { - *ref = &item; - return true; - } - } - return false; - } - - bool lookup_trait_item_by_type (const std::string &ident, - TraitItemReference::TraitItemType type, - const TraitItemReference **ref) const - { - for (auto &item : item_refs) - { - if (item.get_trait_item_type () != type) - continue; - - if (ident.compare (item.get_identifier ()) == 0) - { - *ref = &item; - return true; - } - } - return false; - } - - bool lookup_hir_trait_item (const HIR::TraitItem &item, - const TraitItemReference **ref) const - { - return lookup_trait_item (item.trait_identifier (), ref); - } - - bool lookup_trait_item (const std::string &ident, - const TraitItemReference **ref) const - { - for (auto &item : item_refs) - { - if (ident.compare (item.get_identifier ()) == 0) - { - *ref = &item; - return true; - } - } - - // lookup super traits - for (const auto &super_trait : super_traits) - { - bool found = super_trait->lookup_trait_item (ident, ref); - if (found) - return true; - } - - return false; - } - - const TraitItemReference * - lookup_trait_item (const std::string &ident, - TraitItemReference::TraitItemType type) const - { - for (auto &item : item_refs) - { - if (item.get_trait_item_type () != type) - continue; - - if (ident.compare (item.get_identifier ()) == 0) - return &item; - } - - // lookup super traits - for (const auto &super_trait : super_traits) - { - const TraitItemReference *res - = super_trait->lookup_trait_item (ident, type); - if (!res->is_error ()) - return res; - } - - return &TraitItemReference::error_node (); - } - - size_t size () const { return item_refs.size (); } - - const std::vector &get_trait_items () const - { - return item_refs; - } - - void get_trait_items_and_supers ( - std::vector &result) const - { - for (const auto &item : item_refs) - result.push_back (&item); - - for (const auto &super_trait : super_traits) - super_trait->get_trait_items_and_supers (result); - } - - void on_resolved () - { - for (auto &item : item_refs) - { - item.on_resolved (); - } - } - - void clear_associated_types () - { - for (auto &item : item_refs) - { - bool is_assoc_type = item.get_trait_item_type () - == TraitItemReference::TraitItemType::TYPE; - if (is_assoc_type) - item.associated_type_reset (); - } - } - - bool is_equal (const TraitReference &other) const - { - DefId this_id = get_mappings ().get_defid (); - DefId other_id = other.get_mappings ().get_defid (); - return this_id == other_id; - } - - const std::vector get_super_traits () const - { - return super_traits; - } - - bool is_object_safe (bool emit_error, Location locus) const - { - // https: // doc.rust-lang.org/reference/items/traits.html#object-safety - std::vector non_object_super_traits; - for (auto &item : super_traits) - { - if (!item->is_object_safe (false, Location ())) - non_object_super_traits.push_back (item); - } - - std::vector non_object_safe_items; - for (auto &item : get_trait_items ()) - { - if (!item.is_object_safe ()) - non_object_safe_items.push_back (&item); - } - - bool is_safe - = non_object_super_traits.empty () && non_object_safe_items.empty (); - if (emit_error && !is_safe) - { - RichLocation r (locus); - for (auto &item : non_object_super_traits) - r.add_range (item->get_locus ()); - for (auto &item : non_object_safe_items) - r.add_range (item->get_locus ()); - - rust_error_at (r, "trait bound is not object safe"); - } - - return is_safe; - } - - bool trait_has_generics () const { return !trait_substs.empty (); } - - std::vector get_trait_substs () const - { - return trait_substs; - } - - bool satisfies_bound (const TraitReference &reference) const - { - if (is_equal (reference)) - return true; - - for (const auto &super_trait : super_traits) - { - if (super_trait->satisfies_bound (reference)) - return true; - } - - return false; - } - -private: - const HIR::Trait *hir_trait_ref; - std::vector item_refs; - std::vector super_traits; - std::vector trait_substs; -}; - -class AssociatedImplTrait -{ -public: - AssociatedImplTrait (TraitReference *trait, HIR::ImplBlock *impl, - TyTy::BaseType *self, - Resolver::TypeCheckContext *context) - : trait (trait), impl (impl), self (self), context (context) - {} - - TraitReference *get_trait () { return trait; } - - HIR::ImplBlock *get_impl_block () { return impl; } - - TyTy::BaseType *get_self () { return self; } - - void setup_associated_types (const TyTy::BaseType *self, - const TyTy::TypeBoundPredicate &bound); - - void reset_associated_types (); - -private: - TraitReference *trait; - HIR::ImplBlock *impl; - TyTy::BaseType *self; - Resolver::TypeCheckContext *context; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_HIR_TRAIT_REF_H diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h new file mode 100644 index 0000000..d0814f6 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-trait-reference.h @@ -0,0 +1,515 @@ +// Copyright (C) 2021-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_HIR_TRAIT_REF_H +#define RUST_HIR_TRAIT_REF_H + +#include "rust-hir-full.h" +#include "rust-tyty-visitor.h" +#include "rust-hir-type-check-util.h" + +namespace Rust { +namespace Resolver { + +// Data Objects for the associated trait items in a structure we can work with +// https://doc.rust-lang.org/edition-guide/rust-2018/trait-system/associated-constants.html +class TypeCheckContext; +class TraitItemReference +{ +public: + enum TraitItemType + { + FN, + CONST, + TYPE, + ERROR + }; + + TraitItemReference (std::string identifier, bool optional, TraitItemType type, + HIR::TraitItem *hir_trait_item, TyTy::BaseType *self, + std::vector substitutions, + Location locus); + + TraitItemReference (TraitItemReference const &other); + + TraitItemReference &operator= (TraitItemReference const &other); + + static TraitItemReference error () + { + return TraitItemReference ("", false, ERROR, nullptr, nullptr, {}, + Location ()); + } + + static TraitItemReference &error_node () + { + static TraitItemReference error = TraitItemReference::error (); + return error; + } + + bool is_error () const { return type == ERROR; } + + std::string as_string () const + { + return "(" + trait_item_type_as_string (type) + " " + identifier + " " + + ")"; + } + + static std::string trait_item_type_as_string (TraitItemType ty) + { + switch (ty) + { + case FN: + return "FN"; + case CONST: + return "CONST"; + case TYPE: + return "TYPE"; + case ERROR: + return "ERROR"; + } + return "ERROR"; + } + + bool is_optional () const { return optional_flag; } + + std::string get_identifier () const { return identifier; } + + TraitItemType get_trait_item_type () const { return type; } + + HIR::TraitItem *get_hir_trait_item () const { return hir_trait_item; } + + Location get_locus () const { return locus; } + + const Analysis::NodeMapping get_mappings () const + { + return hir_trait_item->get_mappings (); + } + + TyTy::BaseType *get_tyty () const + { + rust_assert (hir_trait_item != nullptr); + + switch (type) + { + case CONST: + return get_type_from_constant ( + static_cast (*hir_trait_item)); + break; + + case TYPE: + return get_type_from_typealias ( + static_cast (*hir_trait_item)); + + case FN: + return get_type_from_fn ( + static_cast (*hir_trait_item)); + break; + + default: + return get_error (); + } + + gcc_unreachable (); + return get_error (); + } + + Analysis::NodeMapping get_parent_trait_mappings () const; + + // this is called when the trait is completed resolution and gives the items a + // chance to run their specific type resolution passes. If we call their + // resolution on construction it can lead to a case where the trait being + // resolved recursively trying to resolve the trait itself infinitely since + // the trait will not be stored in its own map yet + void on_resolved (); + + void associated_type_set (TyTy::BaseType *ty) const; + + void associated_type_reset () const; + + bool is_object_safe () const; + +private: + TyTy::ErrorType *get_error () const + { + return new TyTy::ErrorType (get_mappings ().get_hirid ()); + } + + TyTy::BaseType *get_type_from_typealias (/*const*/ + HIR::TraitItemType &type) const; + + TyTy::BaseType * + get_type_from_constant (/*const*/ HIR::TraitItemConst &constant) const; + + TyTy::BaseType *get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const; + + bool is_item_resolved () const; + void resolve_item (HIR::TraitItemType &type); + void resolve_item (HIR::TraitItemConst &constant); + void resolve_item (HIR::TraitItemFunc &func); + + std::string identifier; + bool optional_flag; + TraitItemType type; + HIR::TraitItem *hir_trait_item; + std::vector inherited_substitutions; + Location locus; + + TyTy::BaseType + *self; // this is the implict Self TypeParam required for methods + Resolver::TypeCheckContext *context; +}; + +// this wraps up the HIR::Trait so we can do analysis on it + +class TraitReference +{ +public: + TraitReference (const HIR::Trait *hir_trait_ref, + std::vector item_refs, + std::vector super_traits, + std::vector substs) + : hir_trait_ref (hir_trait_ref), item_refs (item_refs), + super_traits (super_traits) + { + trait_substs.clear (); + trait_substs.reserve (substs.size ()); + for (const auto &p : substs) + trait_substs.push_back (p.clone ()); + } + + TraitReference (TraitReference const &other) + : hir_trait_ref (other.hir_trait_ref), item_refs (other.item_refs), + super_traits (other.super_traits) + { + trait_substs.clear (); + trait_substs.reserve (other.trait_substs.size ()); + for (const auto &p : other.trait_substs) + trait_substs.push_back (p.clone ()); + } + + TraitReference &operator= (TraitReference const &other) + { + hir_trait_ref = other.hir_trait_ref; + item_refs = other.item_refs; + super_traits = other.super_traits; + + trait_substs.clear (); + trait_substs.reserve (other.trait_substs.size ()); + for (const auto &p : other.trait_substs) + trait_substs.push_back (p.clone ()); + + return *this; + } + + TraitReference (TraitReference &&other) = default; + TraitReference &operator= (TraitReference &&other) = default; + + static TraitReference error () + { + return TraitReference (nullptr, {}, {}, {}); + } + + bool is_error () const { return hir_trait_ref == nullptr; } + + static TraitReference &error_node () + { + static TraitReference trait_error_node = TraitReference::error (); + return trait_error_node; + } + + Location get_locus () const { return hir_trait_ref->get_locus (); } + + std::string get_name () const + { + rust_assert (!is_error ()); + return hir_trait_ref->get_name (); + } + + std::string as_string () const + { + if (is_error ()) + return ""; + + std::string item_buf; + for (auto &item : item_refs) + { + item_buf += item.as_string () + ", "; + } + return "HIR Trait: " + get_name () + "->" + + hir_trait_ref->get_mappings ().as_string () + " [" + item_buf + + "]"; + } + + const HIR::Trait *get_hir_trait_ref () const { return hir_trait_ref; } + + const Analysis::NodeMapping &get_mappings () const + { + return hir_trait_ref->get_mappings (); + } + + DefId get_defid () const { return get_mappings ().get_defid (); } + + bool lookup_hir_trait_item (const HIR::TraitItem &item, + TraitItemReference **ref) + { + return lookup_trait_item (item.trait_identifier (), ref); + } + + bool lookup_trait_item (const std::string &ident, TraitItemReference **ref) + { + for (auto &item : item_refs) + { + if (ident.compare (item.get_identifier ()) == 0) + { + *ref = &item; + return true; + } + } + return false; + } + + bool lookup_trait_item_by_type (const std::string &ident, + TraitItemReference::TraitItemType type, + TraitItemReference **ref) + { + for (auto &item : item_refs) + { + if (item.get_trait_item_type () != type) + continue; + + if (ident.compare (item.get_identifier ()) == 0) + { + *ref = &item; + return true; + } + } + return false; + } + + bool lookup_trait_item_by_type (const std::string &ident, + TraitItemReference::TraitItemType type, + const TraitItemReference **ref) const + { + for (auto &item : item_refs) + { + if (item.get_trait_item_type () != type) + continue; + + if (ident.compare (item.get_identifier ()) == 0) + { + *ref = &item; + return true; + } + } + return false; + } + + bool lookup_hir_trait_item (const HIR::TraitItem &item, + const TraitItemReference **ref) const + { + return lookup_trait_item (item.trait_identifier (), ref); + } + + bool lookup_trait_item (const std::string &ident, + const TraitItemReference **ref) const + { + for (auto &item : item_refs) + { + if (ident.compare (item.get_identifier ()) == 0) + { + *ref = &item; + return true; + } + } + + // lookup super traits + for (const auto &super_trait : super_traits) + { + bool found = super_trait->lookup_trait_item (ident, ref); + if (found) + return true; + } + + return false; + } + + const TraitItemReference * + lookup_trait_item (const std::string &ident, + TraitItemReference::TraitItemType type) const + { + for (auto &item : item_refs) + { + if (item.get_trait_item_type () != type) + continue; + + if (ident.compare (item.get_identifier ()) == 0) + return &item; + } + + // lookup super traits + for (const auto &super_trait : super_traits) + { + const TraitItemReference *res + = super_trait->lookup_trait_item (ident, type); + if (!res->is_error ()) + return res; + } + + return &TraitItemReference::error_node (); + } + + size_t size () const { return item_refs.size (); } + + const std::vector &get_trait_items () const + { + return item_refs; + } + + void get_trait_items_and_supers ( + std::vector &result) const + { + for (const auto &item : item_refs) + result.push_back (&item); + + for (const auto &super_trait : super_traits) + super_trait->get_trait_items_and_supers (result); + } + + void on_resolved () + { + for (auto &item : item_refs) + { + item.on_resolved (); + } + } + + void clear_associated_types () + { + for (auto &item : item_refs) + { + bool is_assoc_type = item.get_trait_item_type () + == TraitItemReference::TraitItemType::TYPE; + if (is_assoc_type) + item.associated_type_reset (); + } + } + + bool is_equal (const TraitReference &other) const + { + DefId this_id = get_mappings ().get_defid (); + DefId other_id = other.get_mappings ().get_defid (); + return this_id == other_id; + } + + const std::vector get_super_traits () const + { + return super_traits; + } + + bool is_object_safe (bool emit_error, Location locus) const + { + // https: // doc.rust-lang.org/reference/items/traits.html#object-safety + std::vector non_object_super_traits; + for (auto &item : super_traits) + { + if (!item->is_object_safe (false, Location ())) + non_object_super_traits.push_back (item); + } + + std::vector non_object_safe_items; + for (auto &item : get_trait_items ()) + { + if (!item.is_object_safe ()) + non_object_safe_items.push_back (&item); + } + + bool is_safe + = non_object_super_traits.empty () && non_object_safe_items.empty (); + if (emit_error && !is_safe) + { + RichLocation r (locus); + for (auto &item : non_object_super_traits) + r.add_range (item->get_locus ()); + for (auto &item : non_object_safe_items) + r.add_range (item->get_locus ()); + + rust_error_at (r, "trait bound is not object safe"); + } + + return is_safe; + } + + bool trait_has_generics () const { return !trait_substs.empty (); } + + std::vector get_trait_substs () const + { + return trait_substs; + } + + bool satisfies_bound (const TraitReference &reference) const + { + if (is_equal (reference)) + return true; + + for (const auto &super_trait : super_traits) + { + if (super_trait->satisfies_bound (reference)) + return true; + } + + return false; + } + +private: + const HIR::Trait *hir_trait_ref; + std::vector item_refs; + std::vector super_traits; + std::vector trait_substs; +}; + +class AssociatedImplTrait +{ +public: + AssociatedImplTrait (TraitReference *trait, HIR::ImplBlock *impl, + TyTy::BaseType *self, + Resolver::TypeCheckContext *context) + : trait (trait), impl (impl), self (self), context (context) + {} + + TraitReference *get_trait () { return trait; } + + HIR::ImplBlock *get_impl_block () { return impl; } + + TyTy::BaseType *get_self () { return self; } + + void setup_associated_types (const TyTy::BaseType *self, + const TyTy::TypeBoundPredicate &bound); + + void reset_associated_types (); + +private: + TraitReference *trait; + HIR::ImplBlock *impl; + TyTy::BaseType *self; + Resolver::TypeCheckContext *context; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TRAIT_REF_H diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc index cc6693f..b293279 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc @@ -22,6 +22,16 @@ namespace Rust { namespace Resolver { +TraitItemReference +ResolveTraitItemToRef::Resolve ( + HIR::TraitItem &item, TyTy::BaseType *self, + std::vector substitutions) +{ + ResolveTraitItemToRef resolver (self, std::move (substitutions)); + item.accept_vis (resolver); + return std::move (resolver.resolved); +} + void ResolveTraitItemToRef::visit (HIR::TraitItemType &type) { diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h b/gcc/rust/typecheck/rust-hir-trait-resolve.h index 468f429..39365e0 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.h +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h @@ -19,9 +19,7 @@ #ifndef RUST_HIR_TRAIT_RESOLVE_H #define RUST_HIR_TRAIT_RESOLVE_H -#include "rust-hir-type-check-base.h" #include "rust-hir-type-check-type.h" -#include "rust-hir-trait-ref.h" namespace Rust { namespace Resolver { @@ -32,12 +30,7 @@ class ResolveTraitItemToRef : public TypeCheckBase, public: static TraitItemReference Resolve (HIR::TraitItem &item, TyTy::BaseType *self, - std::vector substitutions) - { - ResolveTraitItemToRef resolver (self, std::move (substitutions)); - item.accept_vis (resolver); - return std::move (resolver.resolved); - } + std::vector substitutions); void visit (HIR::TraitItemType &type) override; diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index 8e5c8f6..ee77497 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -22,7 +22,7 @@ #include "rust-hir-full-decls.h" #include "rust-hir-map.h" #include "rust-tyty.h" -#include "rust-hir-trait-ref.h" +#include "rust-hir-trait-reference.h" #include "rust-autoderef.h" namespace Rust { diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index c16c216..7465b6f 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -27,7 +27,7 @@ #include "rust-linemap.h" #include "rust-substitution-mapper.h" -#include "rust-hir-trait-ref.h" +#include "rust-hir-trait-reference.h" #include "rust-hir-type-bounds.h" #include "rust-hir-trait-resolve.h" #include "rust-tyty-rules.h" -- cgit v1.1 From 50856ddba4689710dd53865e96cc7da9885b7b51 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 27 Jan 2023 18:28:06 +0000 Subject: gccrs: Refactor handle_substitutions to take a reference This patch changes the recusive substitution code to take a reference instead of a copy. This is important as the callback field is going to be made non-copyable in a future patch and this pipeline is for recursive substitutions so its ok to reuse the same mappings here. Signed-off-by: Philip Herron gcc/rust/ChangeLog: * typecheck/rust-tyty-bounds.cc: refactor to take a reference * typecheck/rust-tyty-subst.cc: likewise (SubstitutionRef::get_substitution_arguments): likewise (SubstitutionRef::infer_substitions): likewise * typecheck/rust-tyty-subst.h: likewise * typecheck/rust-tyty.cc (ADTType::handle_substitions): likewise (TupleType::handle_substitions): likewise (FnType::handle_substitions): likewise (ClosureType::handle_substitions): likewise (ArrayType::handle_substitions): likewise (SliceType::handle_substitions): likewise (ReferenceType::handle_substitions): likewise (PointerType::handle_substitions): likewise (ParamType::handle_substitions): likewise (ProjectionType::handle_substitions): likewise * typecheck/rust-tyty.h: likewise --- gcc/rust/typecheck/rust-tyty-bounds.cc | 2 +- gcc/rust/typecheck/rust-tyty-subst.cc | 10 ++++++++-- gcc/rust/typecheck/rust-tyty-subst.h | 5 +++-- gcc/rust/typecheck/rust-tyty.cc | 21 +++++++++++---------- gcc/rust/typecheck/rust-tyty.h | 22 +++++++++++----------- 5 files changed, 34 insertions(+), 26 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index a307dd3..414111c 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -444,7 +444,7 @@ TypeBoundPredicate::is_error () const BaseType * TypeBoundPredicate::handle_substitions ( - SubstitutionArgumentMappings subst_mappings) + SubstitutionArgumentMappings &subst_mappings) { for (auto &sub : get_substs ()) { diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc index aceed29..a5d7387 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.cc +++ b/gcc/rust/typecheck/rust-tyty-subst.cc @@ -488,7 +488,13 @@ SubstitutionRef::was_substituted () const return !needs_substitution (); } -SubstitutionArgumentMappings +SubstitutionArgumentMappings & +SubstitutionRef::get_substitution_arguments () +{ + return used_arguments; +} + +const SubstitutionArgumentMappings & SubstitutionRef::get_substitution_arguments () const { return used_arguments; @@ -697,7 +703,7 @@ SubstitutionRef::infer_substitions (Location locus) SubstitutionArgumentMappings infer_arguments (std::move (args), {} /* binding_arguments */, locus); - return handle_substitions (std::move (infer_arguments)); + return handle_substitions (infer_arguments); } SubstitutionArgumentMappings diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h index 4d09a30..039eb36 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.h +++ b/gcc/rust/typecheck/rust-tyty-subst.h @@ -199,7 +199,8 @@ public: bool was_substituted () const; - SubstitutionArgumentMappings get_substitution_arguments () const; + SubstitutionArgumentMappings &get_substitution_arguments (); + const SubstitutionArgumentMappings &get_substitution_arguments () const; // this is the count of type params that are not substituted fuly size_t num_required_substitutions () const; @@ -301,7 +302,7 @@ public: bool monomorphize (); // TODO comment - virtual BaseType *handle_substitions (SubstitutionArgumentMappings mappings) + virtual BaseType *handle_substitions (SubstitutionArgumentMappings &mappings) = 0; SubstitutionArgumentMappings get_used_arguments () const; diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 7465b6f..3a642b6 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -1148,7 +1148,7 @@ handle_substitions (SubstitutionArgumentMappings &subst_mappings, } ADTType * -ADTType::handle_substitions (SubstitutionArgumentMappings subst_mappings) +ADTType::handle_substitions (SubstitutionArgumentMappings &subst_mappings) { ADTType *adt = static_cast (clone ()); adt->set_ty_ref (mappings->get_next_hir_id ()); @@ -1333,7 +1333,7 @@ TupleType::monomorphized_clone () const } TupleType * -TupleType::handle_substitions (SubstitutionArgumentMappings mappings) +TupleType::handle_substitions (SubstitutionArgumentMappings &mappings) { auto mappings_table = Analysis::Mappings::get (); @@ -1474,7 +1474,7 @@ FnType::monomorphized_clone () const } FnType * -FnType::handle_substitions (SubstitutionArgumentMappings subst_mappings) +FnType::handle_substitions (SubstitutionArgumentMappings &subst_mappings) { FnType *fn = static_cast (clone ()); fn->set_ty_ref (mappings->get_next_hir_id ()); @@ -1742,7 +1742,7 @@ ClosureType::monomorphized_clone () const } ClosureType * -ClosureType::handle_substitions (SubstitutionArgumentMappings mappings) +ClosureType::handle_substitions (SubstitutionArgumentMappings &mappings) { gcc_unreachable (); return nullptr; @@ -1862,7 +1862,7 @@ ArrayType::monomorphized_clone () const } ArrayType * -ArrayType::handle_substitions (SubstitutionArgumentMappings mappings) +ArrayType::handle_substitions (SubstitutionArgumentMappings &mappings) { auto mappings_table = Analysis::Mappings::get (); @@ -1945,7 +1945,7 @@ SliceType::monomorphized_clone () const } SliceType * -SliceType::handle_substitions (SubstitutionArgumentMappings mappings) +SliceType::handle_substitions (SubstitutionArgumentMappings &mappings) { auto mappings_table = Analysis::Mappings::get (); @@ -2704,7 +2704,7 @@ ReferenceType::monomorphized_clone () const } ReferenceType * -ReferenceType::handle_substitions (SubstitutionArgumentMappings mappings) +ReferenceType::handle_substitions (SubstitutionArgumentMappings &mappings) { auto mappings_table = Analysis::Mappings::get (); @@ -2870,7 +2870,7 @@ PointerType::monomorphized_clone () const } PointerType * -PointerType::handle_substitions (SubstitutionArgumentMappings mappings) +PointerType::handle_substitions (SubstitutionArgumentMappings &mappings) { auto mappings_table = Analysis::Mappings::get (); @@ -3047,7 +3047,7 @@ ParamType::is_equal (const BaseType &other) const } ParamType * -ParamType::handle_substitions (SubstitutionArgumentMappings subst_mappings) +ParamType::handle_substitions (SubstitutionArgumentMappings &subst_mappings) { SubstitutionArg arg = SubstitutionArg::error (); bool ok = subst_mappings.get_argument_for_symbol (this, &arg); @@ -3492,7 +3492,8 @@ ProjectionType::monomorphized_clone () const } ProjectionType * -ProjectionType::handle_substitions (SubstitutionArgumentMappings subst_mappings) +ProjectionType::handle_substitions ( + SubstitutionArgumentMappings &subst_mappings) { // // do we really need to substitute this? // if (base->needs_generic_substitutions () || base->contains_type_parameters diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 3dd97ce..900b64d 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -304,7 +304,7 @@ public: bool is_concrete () const override final; - ParamType *handle_substitions (SubstitutionArgumentMappings mappings); + ParamType *handle_substitions (SubstitutionArgumentMappings &mappings); private: std::string symbol; @@ -379,7 +379,7 @@ public: std::string get_name () const override final; - TupleType *handle_substitions (SubstitutionArgumentMappings mappings); + TupleType *handle_substitions (SubstitutionArgumentMappings &mappings); private: std::vector fields; @@ -427,7 +427,7 @@ public: // WARNING THIS WILL ALWAYS RETURN NULLPTR BaseType * - handle_substitions (SubstitutionArgumentMappings mappings) override final; + handle_substitions (SubstitutionArgumentMappings &mappings) override final; bool is_error () const; @@ -682,7 +682,7 @@ public: } ADTType * - handle_substitions (SubstitutionArgumentMappings mappings) override final; + handle_substitions (SubstitutionArgumentMappings &mappings) override final; private: std::string identifier; @@ -815,7 +815,7 @@ public: } FnType * - handle_substitions (SubstitutionArgumentMappings mappings) override final; + handle_substitions (SubstitutionArgumentMappings &mappings) override final; ABI get_abi () const { return abi; } @@ -965,7 +965,7 @@ public: } ClosureType * - handle_substitions (SubstitutionArgumentMappings mappings) override final; + handle_substitions (SubstitutionArgumentMappings &mappings) override final; TyTy::TupleType &get_parameters () const { return *parameters; } TyTy::BaseType &get_result_type () const { return *result_type.get_tyty (); } @@ -1024,7 +1024,7 @@ public: HIR::Expr &get_capacity_expr () const { return capacity_expr; } - ArrayType *handle_substitions (SubstitutionArgumentMappings mappings); + ArrayType *handle_substitions (SubstitutionArgumentMappings &mappings); private: TyVar element_type; @@ -1070,7 +1070,7 @@ public: return get_element_type ()->is_concrete (); } - SliceType *handle_substitions (SubstitutionArgumentMappings mappings); + SliceType *handle_substitions (SubstitutionArgumentMappings &mappings); private: TyVar element_type; @@ -1321,7 +1321,7 @@ public: bool is_concrete () const override final; - ReferenceType *handle_substitions (SubstitutionArgumentMappings mappings); + ReferenceType *handle_substitions (SubstitutionArgumentMappings &mappings); Mutability mutability () const; @@ -1364,7 +1364,7 @@ public: bool is_concrete () const override final; - PointerType *handle_substitions (SubstitutionArgumentMappings mappings); + PointerType *handle_substitions (SubstitutionArgumentMappings &mappings); Mutability mutability () const; bool is_mutable () const; @@ -1500,7 +1500,7 @@ public: bool is_concrete () const override final; ProjectionType * - handle_substitions (SubstitutionArgumentMappings mappings) override final; + handle_substitions (SubstitutionArgumentMappings &mappings) override final; private: BaseType *base; -- cgit v1.1 From fc6c5f7dc2062d222a99157fb514d71ad87b1b45 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 27 Jan 2023 18:31:11 +0000 Subject: gccrs: Clear the substitution callbacks when copying ArgumentMappings When we set the callback on substitutions this is not safe to be copied around since we store the used argument mappings and can reuse them in different contexts. This clears the callback on copy's to make it safer. Signed-off-by: Philip Herron gcc/rust/ChangeLog: * typecheck/rust-tyty-subst.cc: update copy constructors --- gcc/rust/typecheck/rust-tyty-subst.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc index a5d7387..0e181ef 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.cc +++ b/gcc/rust/typecheck/rust-tyty-subst.cc @@ -241,7 +241,7 @@ SubstitutionArgumentMappings::SubstitutionArgumentMappings ( SubstitutionArgumentMappings::SubstitutionArgumentMappings ( const SubstitutionArgumentMappings &other) : mappings (other.mappings), binding_args (other.binding_args), - locus (other.locus), param_subst_cb (other.param_subst_cb), + locus (other.locus), param_subst_cb (nullptr), trait_item_flag (other.trait_item_flag) {} @@ -252,7 +252,7 @@ SubstitutionArgumentMappings::operator= ( mappings = other.mappings; binding_args = other.binding_args; locus = other.locus; - param_subst_cb = other.param_subst_cb; + param_subst_cb = nullptr; trait_item_flag = other.trait_item_flag; return *this; -- cgit v1.1 From b5719d74b349bf96735851844158ea9b5d65db85 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 27 Jan 2023 18:49:53 +0000 Subject: gccrs: Add missing param subst callback Signed-off-by: Philip Herron gcc/rust/ChangeLog: * typecheck/rust-tyty-subst.cc: add missing callback --- gcc/rust/typecheck/rust-tyty-subst.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc index 0e181ef..7f5bb22 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.cc +++ b/gcc/rust/typecheck/rust-tyty-subst.cc @@ -141,6 +141,7 @@ SubstitutionParamMapping::fill_param_ty ( bound.handle_substitions (subst_mappings); param->set_ty_ref (type.get_ref ()); + subst_mappings.on_param_subst (*param, arg); } return true; -- cgit v1.1 From edcf5b63bf60c1aec18df315fffbcd3d59d23119 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 27 Jan 2023 15:38:58 +0000 Subject: gccrs: Remove monomorphization hack to setup possible associated types During CallExpr argument type checking we may be calling a default implementation of a trait function this will require any possible associated types to be resolved and setup. This monomoprhization call does this but it will premtivly do extra unification of types which will throw off type checking later on. This fix is required for my work into type bounds checking. Fixes #1773 Signed-off-by: Philip Herron gcc/rust/ChangeLog: * typecheck/rust-hir-trait-reference.h: change interface to return self * typecheck/rust-hir-trait-resolve.cc: likewise * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::resolve_segments): likewise * typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): remove monomorphization hack gcc/testsuite/ChangeLog: * rust/compile/issue-1773.rs: New test. --- gcc/rust/typecheck/rust-hir-trait-reference.h | 5 ++-- gcc/rust/typecheck/rust-hir-trait-resolve.cc | 10 +++---- gcc/rust/typecheck/rust-hir-type-check-path.cc | 36 ++++++++++++++++++++------ gcc/rust/typecheck/rust-tyty-call.cc | 1 - gcc/testsuite/rust/compile/issue-1773.rs | 20 ++++++++++++++ 5 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/rust/compile/issue-1773.rs (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h index d0814f6..0d4da3b 100644 --- a/gcc/rust/typecheck/rust-hir-trait-reference.h +++ b/gcc/rust/typecheck/rust-hir-trait-reference.h @@ -497,8 +497,9 @@ public: TyTy::BaseType *get_self () { return self; } - void setup_associated_types (const TyTy::BaseType *self, - const TyTy::TypeBoundPredicate &bound); + TyTy::BaseType * + setup_associated_types (const TyTy::BaseType *self, + const TyTy::TypeBoundPredicate &bound); void reset_associated_types (); diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc index b293279..a7e0735 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc @@ -377,13 +377,10 @@ TraitItemReference::associated_type_reset () const placeholder->clear_associated_type (); } -void +TyTy::BaseType * AssociatedImplTrait::setup_associated_types ( const TyTy::BaseType *self, const TyTy::TypeBoundPredicate &bound) { - if (!bound.contains_associated_types ()) - return; - // compute the constrained impl block generic arguments based on self and the // higher ranked trait bound TyTy::BaseType *receiver = self->clone (); @@ -486,6 +483,7 @@ AssociatedImplTrait::setup_associated_types ( TyTy::TyWithLocation (receiver), TyTy::TyWithLocation (impl_self_infer), impl_predicate.get_locus ()); rust_assert (result->get_kind () != TyTy::TypeKind::ERROR); + TyTy::BaseType *self_result = result; // unify the bounds arguments std::vector hrtb_bound_arguments; @@ -500,7 +498,7 @@ AssociatedImplTrait::setup_associated_types ( } if (impl_trait_predicate_args.size () != hrtb_bound_arguments.size ()) - return; + return self_result; for (size_t i = 0; i < impl_trait_predicate_args.size (); i++) { @@ -554,6 +552,8 @@ AssociatedImplTrait::setup_associated_types ( resolved_trait_item->associated_type_set (substituted); }); iter.go (); + + return self_result; } void diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index 4e765ad..1625eda 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -379,16 +379,36 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id, if (associated_impl_block != nullptr) { - // get the type of the parent Self - HirId impl_ty_id - = associated_impl_block->get_type ()->get_mappings ().get_hirid (); + // associated types + HirId impl_block_id + = associated_impl_block->get_mappings ().get_hirid (); + + AssociatedImplTrait *associated = nullptr; + bool found_impl_trait + = context->lookup_associated_trait_impl (impl_block_id, + &associated); TyTy::BaseType *impl_block_ty = nullptr; - bool ok = query_type (impl_ty_id, &impl_block_ty); - rust_assert (ok); + if (found_impl_trait) + { + TyTy::TypeBoundPredicate predicate (*associated->get_trait (), + seg.get_locus ()); + impl_block_ty + = associated->setup_associated_types (prev_segment, predicate); + } + else + { + // get the type of the parent Self + HirId impl_ty_id = associated_impl_block->get_type () + ->get_mappings () + .get_hirid (); - if (impl_block_ty->needs_generic_substitutions ()) - impl_block_ty - = SubstMapper::InferSubst (impl_block_ty, seg.get_locus ()); + bool ok = query_type (impl_ty_id, &impl_block_ty); + rust_assert (ok); + + if (impl_block_ty->needs_generic_substitutions ()) + impl_block_ty + = SubstMapper::InferSubst (impl_block_ty, seg.get_locus ()); + } prev_segment = unify_site (seg.get_mappings ().get_hirid (), TyTy::TyWithLocation (prev_segment), diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc index 6334b69..6ff0113 100644 --- a/gcc/rust/typecheck/rust-tyty-call.cc +++ b/gcc/rust/typecheck/rust-tyty-call.cc @@ -85,7 +85,6 @@ TypeCheckCallExpr::visit (ADTType &type) void TypeCheckCallExpr::visit (FnType &type) { - type.monomorphize (); if (call.num_params () != type.num_params ()) { if (type.is_varadic ()) diff --git a/gcc/testsuite/rust/compile/issue-1773.rs b/gcc/testsuite/rust/compile/issue-1773.rs new file mode 100644 index 0000000..c627ac0 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-1773.rs @@ -0,0 +1,20 @@ +trait Foo { + type A; + + fn test(a: Self::A) -> Self::A { + a + } +} + +struct Bar(T); +impl Foo for Bar { + type A = T; +} + +fn main() { + let a; + a = Bar(123); + + let b; + b = Bar::test(a.0); +} -- cgit v1.1 From 95fa967f5c5ce9445fa3f08195c01138338fd0bd Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 30 Jan 2023 18:19:07 +0000 Subject: gccrs: Refactor the type unification code This refactors the unification systems to be a consistent interface using switch statements and simple functions instead of the old clunky visitor system. This is more maintainable as it is harder to miss cases when we can take advantages of switch statements. Signed-off-by: Philip Herron gcc/rust/ChangeLog: * Make-lang.in: update names * backend/rust-compile-expr.cc (CompileExpr::resolve_method_address): update to use new interface * typecheck/rust-coercion.cc (TypeCoercionRules::coerce_borrowed_pointer): likewise * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::unify_site): likewise * typecheck/rust-tyty.cc (BaseType::destructure): likewise (InferType::unify): removed old unify interface (ErrorType::unify): likewise (ADTType::unify): likewise (TupleType::unify): likewise (FnType::unify): likewise (FnPtr::unify): likewise (ClosureType::unify): likewise (ArrayType::unify): likewise (SliceType::unify): likewise (BoolType::unify): likewise (IntType::unify): likewise (UintType::unify): likewise (FloatType::unify): likewise (USizeType::unify): likewise (ISizeType::unify): likewise (CharType::unify): likewise (ReferenceType::unify): likewise (PointerType::unify): likewise (ParamType::unify): likewise (StrType::unify): likewise (NeverType::unify): likewise (PlaceholderType::unify): likewise (ProjectionType::unify): likewise (DynamicObjectType::unify): likewise * typecheck/rust-tyty.h: update destructure interface * typecheck/rust-tyty-rules.h: Removed. * typecheck/rust-unify.cc: New file. * typecheck/rust-unify.h: New file. gcc/testsuite/ChangeLog: * rust/compile/never_type_err1.rs: Moved to... * rust/compile/never_type1.rs: ...here. It now works --- gcc/rust/Make-lang.in | 1 + gcc/rust/backend/rust-compile-expr.cc | 6 +- gcc/rust/typecheck/rust-coercion.cc | 6 +- gcc/rust/typecheck/rust-hir-type-check-base.cc | 15 +- gcc/rust/typecheck/rust-tyty-rules.h | 1406 -------------------- gcc/rust/typecheck/rust-tyty.cc | 229 +--- gcc/rust/typecheck/rust-tyty.h | 31 +- gcc/rust/typecheck/rust-unify.cc | 1640 ++++++++++++++++++++++++ gcc/rust/typecheck/rust-unify.h | 91 ++ gcc/testsuite/rust/compile/never_type1.rs | 13 + gcc/testsuite/rust/compile/never_type_err1.rs | 14 - 11 files changed, 1819 insertions(+), 1633 deletions(-) delete mode 100644 gcc/rust/typecheck/rust-tyty-rules.h create mode 100644 gcc/rust/typecheck/rust-unify.cc create mode 100644 gcc/rust/typecheck/rust-unify.h create mode 100644 gcc/testsuite/rust/compile/never_type1.rs delete mode 100644 gcc/testsuite/rust/compile/never_type_err1.rs (limited to 'gcc') diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 5f5cee7..6038c84 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -134,6 +134,7 @@ GRS_OBJS = \ rust/rust-hir-path-probe.o \ rust/rust-coercion.o \ rust/rust-casts.o \ + rust/rust-unify.o \ rust/rust-hir-type-check-base.o \ rust/rust-autoderef.o \ rust/rust-substitution-mapper.o \ diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 8b56be7..97df107 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -26,6 +26,7 @@ #include "rust-compile-block.h" #include "rust-compile-implitem.h" #include "rust-constexpr.h" +#include "rust-unify.h" #include "rust-gcc.h" #include "fold-const.h" @@ -2030,7 +2031,10 @@ CompileExpr::resolve_method_address (TyTy::FnType *fntype, HirId ref, { TyTy::BaseType *infer_impl_call = candidate_call->infer_substitions (expr_locus); - monomorphized = infer_impl_call->unify (fntype); + monomorphized = Resolver::UnifyRules::Resolve ( + TyTy::TyWithLocation (infer_impl_call), + TyTy::TyWithLocation (fntype), expr_locus, true /* commit */, + true /* emit_errors */); } return CompileInherentImplItem::Compile (impl_item, ctx, monomorphized); diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc index a361856..6236078 100644 --- a/gcc/rust/typecheck/rust-coercion.cc +++ b/gcc/rust/typecheck/rust-coercion.cc @@ -18,6 +18,7 @@ #include "rust-hir-type-check-base.h" #include "rust-coercion.h" +#include "rust-unify.h" namespace Rust { namespace Resolver { @@ -218,7 +219,10 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver, // we might be able to replace this with a can_eq because we default // back to a final unity anyway rust_debug ("coerce_borrowed_pointer -- unify"); - TyTy::BaseType *result = receiver->unify (expected); + TyTy::BaseType *result + = UnifyRules::Resolve (TyTy::TyWithLocation (receiver), + TyTy::TyWithLocation (expected), locus, + true /* commit */, true /* emit_errors */); return CoercionResult{{}, result}; } } diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc index 8107ef5..6a63132 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -22,6 +22,7 @@ #include "rust-hir-type-check-expr.h" #include "rust-hir-type-check-implitem.h" #include "rust-coercion.h" +#include "rust-unify.h" #include "rust-casts.h" namespace Rust { @@ -359,18 +360,8 @@ TypeCheckBase::unify_site (HirId id, TyTy::TyWithLocation lhs, rust_debug ("unify_site id={%u} expected={%s} expr={%s}", id, expected->debug_str ().c_str (), expr->debug_str ().c_str ()); - TyTy::BaseType *unified = expected->unify (expr); - if (unified->get_kind () == TyTy::TypeKind::ERROR) - { - RichLocation r (unify_locus); - r.add_range (lhs.get_locus ()); - r.add_range (rhs.get_locus ()); - rust_error_at (r, "expected %<%s%> got %<%s%>", - expected->get_name ().c_str (), - expr->get_name ().c_str ()); - } - - return unified; + return UnifyRules::Resolve (lhs, rhs, unify_locus, true /*commit*/, + true /*emit_error*/); } TyTy::BaseType * diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h deleted file mode 100644 index dbb808b..0000000 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ /dev/null @@ -1,1406 +0,0 @@ -// Copyright (C) 2020-2022 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#ifndef RUST_TYTY_RULES -#define RUST_TYTY_RULES - -#include "rust-diagnostics.h" -#include "rust-tyty.h" -#include "rust-tyty-visitor.h" -#include "rust-hir-map.h" -#include "rust-hir-type-check.h" - -namespace Rust { -namespace TyTy { - -/* Rules specify how to unify two Ty. For example, the result of unifying the - two tuples (u64, A) and (B, i64) would be (u64, i64). - - Performing a unification requires a double dispatch. To illustrate, suppose - we want to unify `ty1` and `ty2`. Here's what it looks like: - 1. The caller calls `ty1.unify(ty2)`. This is the first dispatch. - 2. `ty1` creates a rule specific to its type(e.g. TupleRules). - 3. The rule calls `ty2.accept_vis(rule)`. This is the second dispatch. - 4. `ty2` calls `rule.visit(*this)`, which will method-overload to the - correct implementation at compile time. - - The nice thing about Rules is that they seperate unification logic from the - representation of Ty. To support unifying a new Ty, implement its - `accept_vis` and `unify` method to pass the unification request to Rules. - Then, create a new `XXXRules` class and implement one `visit` method for - every Ty it can unify with. */ -class BaseRules : public TyVisitor -{ -public: - virtual ~BaseRules () {} - - /* Unify two ty. Returns a pointer to the newly-created unified ty, or nullptr - if the two types cannot be unified. The caller is responsible for releasing - the memory of the returned ty. - - This method is meant to be used internally by Ty. If you're trying to unify - two ty, you can simply call `unify` on ty themselves. */ - virtual BaseType *unify (BaseType *other) - { - if (other->get_kind () == TypeKind::PARAM) - { - ParamType *p = static_cast (other); - other = p->resolve (); - } - else if (other->get_kind () == TypeKind::PLACEHOLDER) - { - PlaceholderType *p = static_cast (other); - if (p->can_resolve ()) - { - other = p->resolve (); - return get_base ()->unify (other); - } - } - else if (other->get_kind () == TypeKind::PROJECTION) - { - ProjectionType *p = static_cast (other); - other = p->get (); - return get_base ()->unify (other); - } - - other->accept_vis (*this); - if (resolved->get_kind () == TyTy::TypeKind::ERROR) - return resolved; - - resolved->append_reference (get_base ()->get_ref ()); - resolved->append_reference (other->get_ref ()); - for (auto ref : get_base ()->get_combined_refs ()) - resolved->append_reference (ref); - for (auto ref : other->get_combined_refs ()) - resolved->append_reference (ref); - - other->append_reference (resolved->get_ref ()); - other->append_reference (get_base ()->get_ref ()); - get_base ()->append_reference (resolved->get_ref ()); - get_base ()->append_reference (other->get_ref ()); - - bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER; - bool result_is_infer_var = resolved->get_kind () == TyTy::TypeKind::INFER; - bool results_is_non_general_infer_var - = (result_is_infer_var - && (static_cast (resolved))->get_infer_kind () - != TyTy::InferType::GENERAL); - if (result_resolved || results_is_non_general_infer_var) - { - for (auto &ref : resolved->get_combined_refs ()) - { - TyTy::BaseType *ref_tyty = nullptr; - bool ok = context->lookup_type (ref, &ref_tyty); - if (!ok) - continue; - - // if any of the types are inference variables lets fix them - if (ref_tyty->get_kind () == TyTy::TypeKind::INFER) - { - context->insert_type ( - Analysis::NodeMapping (mappings->get_current_crate (), - UNKNOWN_NODEID, ref, - UNKNOWN_LOCAL_DEFID), - resolved->clone ()); - } - } - } - return resolved; - } - - virtual void visit (TupleType &) override {} - - virtual void visit (ADTType &) override {} - - virtual void visit (InferType &) override {} - - virtual void visit (FnType &) override {} - - virtual void visit (FnPtr &) override {} - - virtual void visit (ArrayType &) override {} - - virtual void visit (SliceType &) override {} - - virtual void visit (BoolType &) override {} - - virtual void visit (IntType &) override {} - - virtual void visit (UintType &) override {} - - virtual void visit (USizeType &) override {} - - virtual void visit (ISizeType &) override {} - - virtual void visit (FloatType &) override {} - - virtual void visit (ErrorType &) override {} - - virtual void visit (CharType &) override {} - - virtual void visit (ReferenceType &) override {} - - virtual void visit (PointerType &) override {} - - virtual void visit (ParamType &) override {} - - virtual void visit (StrType &) override {} - - virtual void visit (NeverType &) override {} - - virtual void visit (PlaceholderType &) override {} - - virtual void visit (ProjectionType &) override {} - - virtual void visit (DynamicObjectType &) override {} - - virtual void visit (ClosureType &) override {} - -protected: - BaseRules (BaseType *base) - : mappings (Analysis::Mappings::get ()), - context (Resolver::TypeCheckContext::get ()), - resolved (new ErrorType (base->get_ref (), base->get_ref ())) - {} - - Analysis::Mappings *mappings; - Resolver::TypeCheckContext *context; - - /* Temporary storage for the result of a unification. - We could return the result directly instead of storing it in the rule - object, but that involves modifying the visitor pattern to accommodate - the return value, which is too complex. */ - BaseType *resolved; - -private: - /* Returns a pointer to the ty that created this rule. */ - virtual BaseType *get_base () = 0; -}; - -class InferRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - InferRules (InferType *base) : BaseRules (base), base (base) {} - - void visit (BoolType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - resolved = type.clone (); - return; - } - - BaseRules::visit (type); - } - - void visit (IntType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) - || (base->get_infer_kind () - == TyTy::InferType::InferTypeKind::INTEGRAL); - if (is_valid) - { - resolved = type.clone (); - return; - } - - BaseRules::visit (type); - } - - void visit (UintType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) - || (base->get_infer_kind () - == TyTy::InferType::InferTypeKind::INTEGRAL); - if (is_valid) - { - resolved = type.clone (); - return; - } - - BaseRules::visit (type); - } - - void visit (USizeType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) - || (base->get_infer_kind () - == TyTy::InferType::InferTypeKind::INTEGRAL); - if (is_valid) - { - resolved = type.clone (); - return; - } - - BaseRules::visit (type); - } - - void visit (ISizeType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) - || (base->get_infer_kind () - == TyTy::InferType::InferTypeKind::INTEGRAL); - if (is_valid) - { - resolved = type.clone (); - return; - } - - BaseRules::visit (type); - } - - void visit (FloatType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) - || (base->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT); - if (is_valid) - { - resolved = type.clone (); - return; - } - - BaseRules::visit (type); - } - - void visit (ArrayType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - resolved = type.clone (); - return; - } - - BaseRules::visit (type); - } - - void visit (SliceType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - resolved = type.clone (); - return; - } - - BaseRules::visit (type); - } - - void visit (ADTType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - resolved = type.clone (); - return; - } - - BaseRules::visit (type); - } - - void visit (TupleType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - resolved = type.clone (); - return; - } - - BaseRules::visit (type); - } - - void visit (InferType &type) override - { - switch (base->get_infer_kind ()) - { - case InferType::InferTypeKind::GENERAL: - resolved = type.clone (); - return; - - case InferType::InferTypeKind::INTEGRAL: { - if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL) - { - resolved = type.clone (); - return; - } - else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL) - { - resolved = base->clone (); - return; - } - } - break; - - case InferType::InferTypeKind::FLOAT: { - if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) - { - resolved = type.clone (); - return; - } - else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL) - { - resolved = base->clone (); - return; - } - } - break; - } - - BaseRules::visit (type); - } - - void visit (CharType &type) override - { - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - resolved = type.clone (); - return; - } - - BaseRules::visit (type); - } - } - - void visit (ReferenceType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - resolved = type.clone (); - return; - } - - BaseRules::visit (type); - } - - void visit (PointerType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - resolved = type.clone (); - return; - } - - BaseRules::visit (type); - } - - void visit (ParamType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - resolved = type.clone (); - return; - } - - BaseRules::visit (type); - } - - void visit (DynamicObjectType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - resolved = type.clone (); - return; - } - - BaseRules::visit (type); - } - - void visit (ClosureType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - resolved = type.clone (); - return; - } - - BaseRules::visit (type); - } - -private: - BaseType *get_base () override { return base; } - - InferType *base; -}; - -class FnRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - FnRules (FnType *base) : BaseRules (base), base (base) {} - - 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 (FnType &type) override - { - if (base->num_params () != type.num_params ()) - { - BaseRules::visit (type); - return; - } - - for (size_t i = 0; i < base->num_params (); i++) - { - auto a = base->param_at (i).second; - auto b = type.param_at (i).second; - - auto unified_param = a->unify (b); - if (unified_param == nullptr) - { - BaseRules::visit (type); - return; - } - } - - auto unified_return - = base->get_return_type ()->unify (type.get_return_type ()); - if (unified_return == nullptr) - { - BaseRules::visit (type); - return; - } - - resolved = base->clone (); - resolved->set_ref (type.get_ref ()); - } - -private: - BaseType *get_base () override { return base; } - - FnType *base; -}; - -class FnptrRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - FnptrRules (FnPtr *base) : BaseRules (base), base (base) {} - - 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 (FnPtr &type) override - { - auto this_ret_type = base->get_return_type (); - auto other_ret_type = type.get_return_type (); - auto unified_result = this_ret_type->unify (other_ret_type); - if (unified_result == nullptr - || unified_result->get_kind () == TypeKind::ERROR) - { - BaseRules::visit (type); - return; - } - - if (base->num_params () != type.num_params ()) - { - BaseRules::visit (type); - return; - } - - for (size_t i = 0; i < base->num_params (); i++) - { - auto this_param = base->param_at (i); - auto other_param = type.param_at (i); - auto unified_param = this_param->unify (other_param); - if (unified_param == nullptr - || unified_param->get_kind () == TypeKind::ERROR) - { - BaseRules::visit (type); - return; - } - } - - resolved = base->clone (); - resolved->set_ref (type.get_ref ()); - } - - void visit (FnType &type) override - { - auto this_ret_type = base->get_return_type (); - auto other_ret_type = type.get_return_type (); - auto unified_result = this_ret_type->unify (other_ret_type); - if (unified_result == nullptr - || unified_result->get_kind () == TypeKind::ERROR) - { - BaseRules::visit (type); - return; - } - - if (base->num_params () != type.num_params ()) - { - BaseRules::visit (type); - return; - } - - for (size_t i = 0; i < base->num_params (); i++) - { - auto this_param = base->param_at (i); - auto other_param = type.param_at (i).second; - auto unified_param = this_param->unify (other_param); - if (unified_param == nullptr - || unified_param->get_kind () == TypeKind::ERROR) - { - BaseRules::visit (type); - return; - } - } - - resolved = base->clone (); - resolved->set_ref (type.get_ref ()); - } - -private: - BaseType *get_base () override { return base; } - - FnPtr *base; -}; - -class ClosureRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - ClosureRules (ClosureType *base) : BaseRules (base), base (base) {} - - 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; } - - ClosureType *base; -}; - -class ArrayRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - ArrayRules (ArrayType *base) : BaseRules (base), base (base) {} - - void visit (ArrayType &type) override - { - // check base type - auto base_resolved - = base->get_element_type ()->unify (type.get_element_type ()); - if (base_resolved == nullptr) - { - BaseRules::visit (type); - return; - } - - resolved - = new ArrayType (type.get_ref (), type.get_ty_ref (), - type.get_ident ().locus, type.get_capacity_expr (), - TyVar (base_resolved->get_ref ())); - } - - 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 ()); - } - -private: - BaseType *get_base () override { return base; } - - ArrayType *base; -}; - -class SliceRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - SliceRules (SliceType *base) : BaseRules (base), base (base) {} - - void visit (SliceType &type) override - { - // check base type - auto base_resolved - = base->get_element_type ()->unify (type.get_element_type ()); - if (base_resolved == nullptr) - { - BaseRules::visit (type); - return; - } - - resolved = new SliceType (type.get_ref (), type.get_ty_ref (), - type.get_ident ().locus, - TyVar (base_resolved->get_ref ())); - } - - 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 ()); - } - -private: - BaseType *get_base () override { return base; } - - SliceType *base; -}; - -class BoolRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - BoolRules (BoolType *base) : BaseRules (base), base (base) {} - - void visit (BoolType &type) override - { - resolved = new BoolType (type.get_ref (), type.get_ty_ref ()); - } - - void visit (InferType &type) override - { - switch (type.get_infer_kind ()) - { - case InferType::InferTypeKind::GENERAL: - resolved = base->clone (); - break; - - default: - BaseRules::visit (type); - break; - } - } - -private: - BaseType *get_base () override { return base; } - - BoolType *base; -}; - -class IntRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - IntRules (IntType *base) : BaseRules (base), base (base) {} - - void visit (InferType &type) override - { - // cant assign a float inference variable - if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) - { - BaseRules::visit (type); - return; - } - - resolved = base->clone (); - resolved->set_ref (type.get_ref ()); - } - - void visit (IntType &type) override - { - if (type.get_int_kind () != base->get_int_kind ()) - { - BaseRules::visit (type); - return; - } - - resolved - = new IntType (type.get_ref (), type.get_ty_ref (), type.get_int_kind ()); - } - -private: - BaseType *get_base () override { return base; } - - IntType *base; -}; - -class UintRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - UintRules (UintType *base) : BaseRules (base), base (base) {} - - void visit (InferType &type) override - { - // cant assign a float inference variable - if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) - { - BaseRules::visit (type); - return; - } - - resolved = base->clone (); - resolved->set_ref (type.get_ref ()); - } - - void visit (UintType &type) override - { - if (type.get_uint_kind () != base->get_uint_kind ()) - { - BaseRules::visit (type); - return; - } - - resolved = new UintType (type.get_ref (), type.get_ty_ref (), - type.get_uint_kind ()); - } - -private: - BaseType *get_base () override { return base; } - - UintType *base; -}; - -class FloatRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - FloatRules (FloatType *base) : BaseRules (base), base (base) {} - - void visit (InferType &type) override - { - if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL) - { - BaseRules::visit (type); - return; - } - - resolved = base->clone (); - resolved->set_ref (type.get_ref ()); - } - - void visit (FloatType &type) override - { - if (type.get_float_kind () != base->get_float_kind ()) - { - BaseRules::visit (type); - return; - } - - resolved = new FloatType (type.get_ref (), type.get_ty_ref (), - type.get_float_kind ()); - } - -private: - BaseType *get_base () override { return base; } - - FloatType *base; -}; - -class ADTRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - ADTRules (ADTType *base) : BaseRules (base), base (base) {} - - void visit (ADTType &type) override - { - if (base->get_adt_kind () != type.get_adt_kind ()) - { - BaseRules::visit (type); - return; - } - - if (base->get_identifier ().compare (type.get_identifier ()) != 0) - { - BaseRules::visit (type); - return; - } - - if (base->number_of_variants () != type.number_of_variants ()) - { - BaseRules::visit (type); - return; - } - - for (size_t i = 0; i < type.number_of_variants (); ++i) - { - TyTy::VariantDef *a = base->get_variants ().at (i); - TyTy::VariantDef *b = type.get_variants ().at (i); - - if (a->num_fields () != b->num_fields ()) - { - BaseRules::visit (type); - return; - } - - for (size_t j = 0; j < a->num_fields (); j++) - { - TyTy::StructFieldType *base_field = a->get_field_at_index (j); - TyTy::StructFieldType *other_field = b->get_field_at_index (j); - - TyTy::BaseType *this_field_ty = base_field->get_field_type (); - TyTy::BaseType *other_field_ty = other_field->get_field_type (); - - BaseType *unified_ty = this_field_ty->unify (other_field_ty); - if (unified_ty->get_kind () == TyTy::TypeKind::ERROR) - return; - } - } - - // generic args for the unit-struct case - if (type.is_unit () && base->is_unit ()) - { - rust_assert (type.get_num_substitutions () - == base->get_num_substitutions ()); - - for (size_t i = 0; i < type.get_num_substitutions (); i++) - { - auto &a = base->get_substs ().at (i); - auto &b = type.get_substs ().at (i); - - auto pa = a.get_param_ty (); - auto pb = b.get_param_ty (); - - auto res = pa->unify (pb); - if (res->get_kind () == TyTy::TypeKind::ERROR) - { - return; - } - } - } - - resolved = type.clone (); - } - - 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 ()); - } - -private: - BaseType *get_base () override { return base; } - - ADTType *base; -}; - -class TupleRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - TupleRules (TupleType *base) : BaseRules (base), base (base) {} - - void visit (TupleType &type) override - { - if (base->num_fields () != type.num_fields ()) - { - BaseRules::visit (type); - return; - } - - std::vector fields; - for (size_t i = 0; i < base->num_fields (); i++) - { - BaseType *bo = base->get_field (i); - BaseType *fo = type.get_field (i); - - BaseType *unified_ty = bo->unify (fo); - if (unified_ty->get_kind () == TyTy::TypeKind::ERROR) - return; - - fields.push_back (TyVar (unified_ty->get_ref ())); - } - - resolved = new TyTy::TupleType (type.get_ref (), type.get_ty_ref (), - type.get_ident ().locus, fields); - } - - 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 ()); - } - -private: - BaseType *get_base () override { return base; } - - TupleType *base; -}; - -class USizeRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - USizeRules (USizeType *base) : BaseRules (base), base (base) {} - - void visit (InferType &type) override - { - // cant assign a float inference variable - if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) - { - BaseRules::visit (type); - return; - } - - resolved = base->clone (); - resolved->set_ref (type.get_ref ()); - } - - void visit (USizeType &type) override { resolved = type.clone (); } - -private: - BaseType *get_base () override { return base; } - - USizeType *base; -}; - -class ISizeRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - ISizeRules (ISizeType *base) : BaseRules (base), base (base) {} - - void visit (InferType &type) override - { - // cant assign a float inference variable - if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) - { - BaseRules::visit (type); - return; - } - - resolved = base->clone (); - resolved->set_ref (type.get_ref ()); - } - - void visit (ISizeType &type) override { resolved = type.clone (); } - -private: - BaseType *get_base () override { return base; } - - ISizeType *base; -}; - -class CharRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - CharRules (CharType *base) : BaseRules (base), base (base) {} - - 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 (CharType &type) override { resolved = type.clone (); } - -private: - BaseType *get_base () override { return base; } - - CharType *base; -}; - -class ReferenceRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - ReferenceRules (ReferenceType *base) : BaseRules (base), base (base) {} - - void visit (ReferenceType &type) override - { - auto base_type = base->get_base (); - auto other_base_type = type.get_base (); - - TyTy::BaseType *base_resolved = base_type->unify (other_base_type); - if (base_resolved == nullptr - || base_resolved->get_kind () == TypeKind::ERROR) - { - BaseRules::visit (type); - return; - } - - // rust is permissive about mutablity here you can always go from mutable to - // immutable but not the otherway round - bool mutability_ok = base->is_mutable () ? type.is_mutable () : true; - if (!mutability_ok) - { - BaseRules::visit (type); - return; - } - - resolved = new ReferenceType (base->get_ref (), base->get_ty_ref (), - TyVar (base_resolved->get_ref ()), - base->mutability ()); - } - - 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 ()); - } - -private: - BaseType *get_base () override { return base; } - - ReferenceType *base; -}; - -class PointerRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - PointerRules (PointerType *base) : BaseRules (base), base (base) {} - - void visit (PointerType &type) override - { - auto base_type = base->get_base (); - auto other_base_type = type.get_base (); - - TyTy::BaseType *base_resolved = base_type->unify (other_base_type); - if (base_resolved == nullptr - || base_resolved->get_kind () == TypeKind::ERROR) - { - BaseRules::visit (type); - return; - } - - // rust is permissive about mutablity here you can always go from mutable to - // immutable but not the otherway round - bool mutability_ok = base->is_mutable () ? type.is_mutable () : true; - if (!mutability_ok) - { - BaseRules::visit (type); - return; - } - - resolved = new PointerType (base->get_ref (), base->get_ty_ref (), - TyVar (base_resolved->get_ref ()), - base->mutability ()); - } - - 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 ()); - } - -private: - BaseType *get_base () override { return base; } - - PointerType *base; -}; - -class ParamRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - ParamRules (ParamType *base) : BaseRules (base), base (base) {} - - // param types are a placeholder we shouldn't have cases where we unify - // against it. eg: struct foo { a: T }; When we invoke it we can do either: - // - // foo{ a: 123 }. - // Then this enforces the i32 type to be referenced on the - // field via an hirid. - // - // rust also allows for a = foo{a:123}; Where we can use an Inference Variable - // to handle the typing of the struct - BaseType *unify (BaseType *other) override final - { - if (!base->can_resolve ()) - return BaseRules::unify (other); - - auto lookup = base->resolve (); - return lookup->unify (other); - } - - void visit (ParamType &type) override - { - if (base->get_symbol ().compare (type.get_symbol ()) != 0) - { - BaseRules::visit (type); - return; - } - - resolved = type.clone (); - } - - void visit (InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseRules::visit (type); - return; - } - - resolved = base->clone (); - } - -private: - BaseType *get_base () override { return base; } - - ParamType *base; -}; - -class StrRules : public BaseRules -{ - // FIXME we will need a enum for the StrType like ByteBuf etc.. - using Rust::TyTy::BaseRules::visit; - -public: - StrRules (StrType *base) : BaseRules (base), base (base) {} - - void visit (StrType &type) override { resolved = type.clone (); } - -private: - BaseType *get_base () override { return base; } - - StrType *base; -}; - -class NeverRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - NeverRules (NeverType *base) : BaseRules (base), base (base) {} - - void visit (NeverType &type) override { resolved = type.clone (); } - -private: - BaseType *get_base () override { return base; } - - NeverType *base; -}; - -class PlaceholderRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - PlaceholderRules (PlaceholderType *base) : BaseRules (base), base (base) {} - - BaseType *unify (BaseType *other) override final - { - if (!base->can_resolve ()) - return BaseRules::unify (other); - - BaseType *lookup = base->resolve (); - return lookup->unify (other); - } - - void visit (PlaceholderType &type) override - { - if (base->get_symbol ().compare (type.get_symbol ()) != 0) - { - BaseRules::visit (type); - return; - } - - resolved = type.clone (); - } - - void visit (InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseRules::visit (type); - return; - } - - resolved = base->clone (); - } - -private: - BaseType *get_base () override { return base; } - - PlaceholderType *base; -}; - -class DynamicRules : public BaseRules -{ - using Rust::TyTy::BaseRules::visit; - -public: - DynamicRules (DynamicObjectType *base) : BaseRules (base), base (base) {} - - void visit (InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseRules::visit (type); - return; - } - - resolved = base->clone (); - } - - void visit (DynamicObjectType &type) override - { - if (base->num_specified_bounds () != type.num_specified_bounds ()) - { - BaseRules::visit (type); - return; - } - - Location ref_locus = mappings->lookup_location (type.get_ref ()); - if (!base->bounds_compatible (type, ref_locus, true)) - { - BaseRules::visit (type); - return; - } - - resolved = base->clone (); - } - -private: - BaseType *get_base () override { return base; } - - DynamicObjectType *base; -}; - -} // namespace TyTy -} // namespace Rust - -#endif // RUST_TYTY_RULES diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 3a642b6..8c3bed4 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -30,7 +30,6 @@ #include "rust-hir-trait-reference.h" #include "rust-hir-type-bounds.h" #include "rust-hir-trait-resolve.h" -#include "rust-tyty-rules.h" #include "rust-tyty-cmp.h" #include "options.h" @@ -376,6 +375,58 @@ BaseType::get_root () const return root; } +BaseType * +BaseType::destructure () +{ + int recurisve_ops = 0; + BaseType *x = this; + while (true) + { + if (recurisve_ops++ >= rust_max_recursion_depth) + { + rust_error_at ( + Location (), + "% count exceeds limit of %i (use " + "% to increase the limit)", + rust_max_recursion_depth); + return new ErrorType (get_ref ()); + } + + switch (x->get_kind ()) + { + case TyTy::TypeKind::PARAM: { + TyTy::ParamType *p = static_cast (x); + TyTy::BaseType *pr = p->resolve (); + if (pr == x) + return pr; + + x = pr; + } + break; + + case TyTy::TypeKind::PLACEHOLDER: { + TyTy::PlaceholderType *p = static_cast (x); + if (!p->can_resolve ()) + return p; + + x = p->resolve (); + } + break; + + case TyTy::TypeKind::PROJECTION: { + TyTy::ProjectionType *p = static_cast (x); + x = p->get (); + } + break; + + default: + return x; + } + } + + return x; +} + const BaseType * BaseType::destructure () const { @@ -397,14 +448,20 @@ BaseType::destructure () const { case TyTy::TypeKind::PARAM: { const TyTy::ParamType *p = static_cast (x); - x = p->resolve (); + const TyTy::BaseType *pr = p->resolve (); + if (pr == x) + return pr; + + x = pr; } break; case TyTy::TypeKind::PLACEHOLDER: { const TyTy::PlaceholderType *p = static_cast (x); - rust_assert (p->can_resolve ()); + if (!p->can_resolve ()) + return p; + x = p->resolve (); } break; @@ -512,13 +569,6 @@ InferType::as_string () const return ""; } -BaseType * -InferType::unify (BaseType *other) -{ - InferRules r (this); - return r.unify (other); -} - bool InferType::can_eq (const BaseType *other, bool emit_errors) const { @@ -637,12 +687,6 @@ ErrorType::as_string () const return ""; } -BaseType * -ErrorType::unify (BaseType *other) -{ - return this; -} - bool ErrorType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1009,13 +1053,6 @@ ADTType::as_string () const return identifier + subst_as_string () + "{" + variants_buffer + "}"; } -BaseType * -ADTType::unify (BaseType *other) -{ - ADTRules r (this); - return r.unify (other); -} - bool ADTType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1278,13 +1315,6 @@ TupleType::get_field (size_t index) const return fields.at (index).get_tyty (); } -BaseType * -TupleType::unify (BaseType *other) -{ - TupleRules r (this); - return r.unify (other); -} - bool TupleType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1385,13 +1415,6 @@ FnType::as_string () const return "fn" + subst_as_string () + " (" + params_str + ") -> " + ret_str; } -BaseType * -FnType::unify (BaseType *other) -{ - FnRules r (this); - return r.unify (other); -} - bool FnType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1616,13 +1639,6 @@ FnPtr::as_string () const return "fnptr (" + params_str + ") -> " + get_return_type ()->as_string (); } -BaseType * -FnPtr::unify (BaseType *other) -{ - FnptrRules r (this); - return r.unify (other); -} - bool FnPtr::can_eq (const BaseType *other, bool emit_errors) const { @@ -1696,13 +1712,6 @@ ClosureType::as_string () const return "|" + params_buf + "| {" + result_type.get_tyty ()->as_string () + "}"; } -BaseType * -ClosureType::unify (BaseType *other) -{ - ClosureRules r (this); - return r.unify (other); -} - bool ClosureType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1812,13 +1821,6 @@ ArrayType::as_string () const return "[" + get_element_type ()->as_string () + ":" + "CAPACITY" + "]"; } -BaseType * -ArrayType::unify (BaseType *other) -{ - ArrayRules r (this); - return r.unify (other); -} - bool ArrayType::can_eq (const BaseType *other, bool emit_errors) const { @@ -1895,13 +1897,6 @@ SliceType::as_string () const return "[" + get_element_type ()->as_string () + "]"; } -BaseType * -SliceType::unify (BaseType *other) -{ - SliceRules r (this); - return r.unify (other); -} - bool SliceType::can_eq (const BaseType *other, bool emit_errors) const { @@ -2006,13 +2001,6 @@ BoolType::as_string () const return "bool"; } -BaseType * -BoolType::unify (BaseType *other) -{ - BoolRules r (this); - return r.unify (other); -} - bool BoolType::can_eq (const BaseType *other, bool emit_errors) const { @@ -2094,13 +2082,6 @@ IntType::as_string () const return "__unknown_int_type"; } -BaseType * -IntType::unify (BaseType *other) -{ - IntRules r (this); - return r.unify (other); -} - bool IntType::can_eq (const BaseType *other, bool emit_errors) const { @@ -2200,13 +2181,6 @@ UintType::as_string () const return "__unknown_uint_type"; } -BaseType * -UintType::unify (BaseType *other) -{ - UintRules r (this); - return r.unify (other); -} - bool UintType::can_eq (const BaseType *other, bool emit_errors) const { @@ -2306,13 +2280,6 @@ FloatType::as_string () const return "__unknown_float_type"; } -BaseType * -FloatType::unify (BaseType *other) -{ - FloatRules r (this); - return r.unify (other); -} - bool FloatType::can_eq (const BaseType *other, bool emit_errors) const { @@ -2389,13 +2356,6 @@ USizeType::as_string () const return "usize"; } -BaseType * -USizeType::unify (BaseType *other) -{ - USizeRules r (this); - return r.unify (other); -} - bool USizeType::can_eq (const BaseType *other, bool emit_errors) const { @@ -2461,13 +2421,6 @@ ISizeType::as_string () const return "isize"; } -BaseType * -ISizeType::unify (BaseType *other) -{ - ISizeRules r (this); - return r.unify (other); -} - bool ISizeType::can_eq (const BaseType *other, bool emit_errors) const { @@ -2533,13 +2486,6 @@ CharType::as_string () const return "char"; } -BaseType * -CharType::unify (BaseType *other) -{ - CharRules r (this); - return r.unify (other); -} - bool CharType::can_eq (const BaseType *other, bool emit_errors) const { @@ -2655,13 +2601,6 @@ ReferenceType::get_name () const + get_base ()->get_name (); } -BaseType * -ReferenceType::unify (BaseType *other) -{ - ReferenceRules r (this); - return r.unify (other); -} - bool ReferenceType::can_eq (const BaseType *other, bool emit_errors) const { @@ -2821,13 +2760,6 @@ PointerType::get_name () const + get_base ()->get_name (); } -BaseType * -PointerType::unify (BaseType *other) -{ - PointerRules r (this); - return r.unify (other); -} - bool PointerType::can_eq (const BaseType *other, bool emit_errors) const { @@ -2964,13 +2896,6 @@ ParamType::get_name () const return resolve ()->get_name (); } -BaseType * -ParamType::unify (BaseType *other) -{ - ParamRules r (this); - return r.unify (other); -} - bool ParamType::can_eq (const BaseType *other, bool emit_errors) const { @@ -3130,13 +3055,6 @@ StrType::as_string () const return "str"; } -BaseType * -StrType::unify (BaseType *other) -{ - StrRules r (this); - return r.unify (other); -} - bool StrType::can_eq (const BaseType *other, bool emit_errors) const { @@ -3202,13 +3120,6 @@ NeverType::as_string () const return "!"; } -BaseType * -NeverType::unify (BaseType *other) -{ - NeverRules r (this); - return r.unify (other); -} - bool NeverType::can_eq (const BaseType *other, bool emit_errors) const { @@ -3295,13 +3206,6 @@ PlaceholderType::as_string () const + ">"; } -BaseType * -PlaceholderType::unify (BaseType *other) -{ - PlaceholderRules r (this); - return r.unify (other); -} - bool PlaceholderType::can_eq (const BaseType *other, bool emit_errors) const { @@ -3465,12 +3369,6 @@ ProjectionType::as_string () const return "as_string () + ">"; } -BaseType * -ProjectionType::unify (BaseType *other) -{ - return base->unify (other); -} - bool ProjectionType::can_eq (const BaseType *other, bool emit_errors) const { @@ -3602,13 +3500,6 @@ DynamicObjectType::as_string () const return "dyn [" + raw_bounds_as_string () + "]"; } -BaseType * -DynamicObjectType::unify (BaseType *other) -{ - DynamicRules r (this); - return r.unify (other); -} - bool DynamicObjectType::can_eq (const BaseType *other, bool emit_errors) const { diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 900b64d..89c3209 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -105,11 +105,6 @@ public: virtual std::string get_name () const = 0; - // Unify two types. Returns a pointer to the newly-created unified ty, or - // nullptr if the two ty cannot be unified. The caller is responsible for - // releasing the memory of the returned ty. - virtual BaseType *unify (BaseType *other) = 0; - // similar to unify but does not actually perform type unification but // determines whether they are compatible. Consider the following // @@ -177,6 +172,7 @@ public: // This will get the monomorphized type from Params, Placeholders or // Projections if available or error + BaseType *destructure (); const BaseType *destructure () const; const RustIdent &get_ident () const; @@ -221,8 +217,6 @@ public: std::string as_string () const override; - BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; BaseType *clone () const final override; @@ -255,7 +249,6 @@ public: std::string as_string () const override; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; BaseType *clone () const final override; @@ -284,7 +277,6 @@ public: std::string as_string () const override; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; BaseType *clone () const final override; @@ -361,7 +353,6 @@ public: std::string as_string () const override; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; bool is_equal (const BaseType &other) const override; @@ -598,7 +589,6 @@ public: std::string as_string () const override; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; bool is_equal (const BaseType &other) const override; @@ -738,7 +728,6 @@ public: std::string get_identifier () const { return identifier; } - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; bool is_equal (const BaseType &other) const override; @@ -858,7 +847,6 @@ public: std::string as_string () const override; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; bool is_equal (const BaseType &other) const override; @@ -938,7 +926,6 @@ public: std::string as_string () const override; std::string get_name () const override final { return as_string (); } - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; bool is_equal (const BaseType &other) const override; @@ -1007,7 +994,6 @@ public: std::string get_name () const override final { return as_string (); } - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; bool is_equal (const BaseType &other) const override; @@ -1055,7 +1041,6 @@ public: std::string get_name () const override final { return as_string (); } - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; bool is_equal (const BaseType &other) const override; @@ -1089,7 +1074,6 @@ public: std::string get_name () const override final; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; BaseType *clone () const final override; @@ -1120,7 +1104,6 @@ public: std::string get_name () const override final; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; IntKind get_int_kind () const; @@ -1159,7 +1142,6 @@ public: std::string get_name () const override final; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; UintKind get_uint_kind () const; @@ -1194,7 +1176,6 @@ public: std::string as_string () const override; std::string get_name () const override final; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; FloatKind get_float_kind () const; @@ -1222,7 +1203,6 @@ public: std::string as_string () const override; std::string get_name () const override final; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; BaseType *clone () const final override; @@ -1243,7 +1223,6 @@ public: std::string as_string () const override; std::string get_name () const override final; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; BaseType *clone () const final override; @@ -1263,7 +1242,6 @@ public: std::string as_string () const override; std::string get_name () const override final; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; BaseType *clone () const final override; @@ -1284,7 +1262,6 @@ public: std::string as_string () const override; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; bool is_equal (const BaseType &other) const override; @@ -1311,7 +1288,6 @@ public: std::string get_name () const override final; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; bool is_equal (const BaseType &other) const override; @@ -1354,7 +1330,6 @@ public: std::string as_string () const override; std::string get_name () const override final; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; bool is_equal (const BaseType &other) const override; @@ -1401,7 +1376,6 @@ public: std::string as_string () const override; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; BaseType *clone () const final override; @@ -1428,7 +1402,6 @@ public: std::string as_string () const override; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; BaseType *clone () const final override; @@ -1478,7 +1451,6 @@ public: std::string as_string () const override; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; BaseType *clone () const final override; @@ -1524,7 +1496,6 @@ public: std::string as_string () const override; - BaseType *unify (BaseType *other) override; bool can_eq (const BaseType *other, bool emit_errors) const override final; bool is_equal (const BaseType &other) const override; diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc new file mode 100644 index 0000000..072f761 --- /dev/null +++ b/gcc/rust/typecheck/rust-unify.cc @@ -0,0 +1,1640 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#include "rust-unify.h" + +namespace Rust { +namespace Resolver { + +UnifyRules::UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, + Location locus, bool commit_flag, bool emit_error) + : lhs (lhs), rhs (rhs), locus (locus), commit_flag (commit_flag), + emit_error (emit_error), mappings (*Analysis::Mappings::get ()), + context (*TypeCheckContext::get ()) +{} + +TyTy::BaseType * +UnifyRules::Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, + Location locus, bool commit_flag, bool emit_error) +{ + UnifyRules r (lhs, rhs, locus, commit_flag, emit_error); + TyTy::BaseType *result = r.go (); + + if (r.commit_flag) + r.commit (result); + + bool failed = result->get_kind () == TyTy::TypeKind::ERROR; + if (failed && r.emit_error) + r.emit_type_mismatch (); + + return result; +} + +TyTy::BaseType * +UnifyRules::get_base () +{ + return lhs.get_ty ()->destructure (); +} + +TyTy::BaseType * +UnifyRules::get_other () +{ + return rhs.get_ty ()->destructure (); +} + +void +UnifyRules::commit (TyTy::BaseType *resolved) +{ + resolved->append_reference (get_base ()->get_ref ()); + resolved->append_reference (get_other ()->get_ref ()); + for (auto ref : get_base ()->get_combined_refs ()) + resolved->append_reference (ref); + for (auto ref : get_other ()->get_combined_refs ()) + resolved->append_reference (ref); + + get_other ()->append_reference (resolved->get_ref ()); + get_other ()->append_reference (get_base ()->get_ref ()); + get_base ()->append_reference (resolved->get_ref ()); + get_base ()->append_reference (get_other ()->get_ref ()); + + bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER; + bool result_is_infer_var = resolved->get_kind () == TyTy::TypeKind::INFER; + bool results_is_non_general_infer_var + = (result_is_infer_var + && (static_cast (resolved))->get_infer_kind () + != TyTy::InferType::GENERAL); + if (result_resolved || results_is_non_general_infer_var) + { + for (auto &ref : resolved->get_combined_refs ()) + { + TyTy::BaseType *ref_tyty = nullptr; + bool ok = context.lookup_type (ref, &ref_tyty); + if (!ok) + continue; + + // if any of the types are inference variables lets fix them + if (ref_tyty->get_kind () == TyTy::TypeKind::INFER) + { + auto node = Analysis::NodeMapping (mappings.get_current_crate (), + UNKNOWN_NODEID, ref, + UNKNOWN_LOCAL_DEFID); + context.insert_type (node, resolved->clone ()); + } + } + } +} + +void +UnifyRules::emit_type_mismatch () const +{ + TyTy::BaseType *expected = lhs.get_ty (); + TyTy::BaseType *expr = rhs.get_ty (); + + RichLocation r (locus); + r.add_range (lhs.get_locus ()); + r.add_range (rhs.get_locus ()); + rust_error_at (r, "expected %<%s%> got %<%s%>", + expected->get_name ().c_str (), expr->get_name ().c_str ()); +} + +TyTy::BaseType * +UnifyRules::go () +{ + TyTy::BaseType *ltype = lhs.get_ty (); + TyTy::BaseType *rtype = rhs.get_ty (); + + ltype = lhs.get_ty ()->destructure (); + rtype = rhs.get_ty ()->destructure (); + + rust_debug ("unify::go ltype={%s} rtype={%s}", ltype->debug_str ().c_str (), + rtype->debug_str ().c_str ()); + + switch (ltype->get_kind ()) + { + case TyTy::INFER: + return expect_inference_variable (static_cast (ltype), + rtype); + + case TyTy::ADT: + return expect_adt (static_cast (ltype), rtype); + + case TyTy::STR: + return expect_str (static_cast (ltype), rtype); + + case TyTy::REF: + return expect_reference (static_cast (ltype), + rtype); + + case TyTy::POINTER: + return expect_pointer (static_cast (ltype), rtype); + + case TyTy::PARAM: + return expect_param (static_cast (ltype), rtype); + + case TyTy::ARRAY: + return expect_array (static_cast (ltype), rtype); + + case TyTy::SLICE: + return expect_slice (static_cast (ltype), rtype); + + case TyTy::FNDEF: + return expect_fndef (static_cast (ltype), rtype); + + case TyTy::FNPTR: + return expect_fnptr (static_cast (ltype), rtype); + + case TyTy::TUPLE: + return expect_tuple (static_cast (ltype), rtype); + + case TyTy::BOOL: + return expect_bool (static_cast (ltype), rtype); + + case TyTy::CHAR: + return expect_char (static_cast (ltype), rtype); + + case TyTy::INT: + return expect_int (static_cast (ltype), rtype); + + case TyTy::UINT: + return expect_uint (static_cast (ltype), rtype); + + case TyTy::FLOAT: + return expect_float (static_cast (ltype), rtype); + + case TyTy::USIZE: + return expect_usize (static_cast (ltype), rtype); + + case TyTy::ISIZE: + return expect_isize (static_cast (ltype), rtype); + + case TyTy::NEVER: + return expect_never (static_cast (ltype), rtype); + + case TyTy::PLACEHOLDER: + return expect_placeholder (static_cast (ltype), + rtype); + + case TyTy::PROJECTION: + return expect_projection (static_cast (ltype), + rtype); + + case TyTy::DYNAMIC: + return expect_dyn (static_cast (ltype), rtype); + + case TyTy::CLOSURE: + return expect_closure (static_cast (ltype), rtype); + + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_inference_variable (TyTy::InferType *ltype, + TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + switch (ltype->get_infer_kind ()) + { + case TyTy::InferType::InferTypeKind::GENERAL: + return rtype->clone (); + + case TyTy::InferType::InferTypeKind::INTEGRAL: { + bool is_valid = r->get_infer_kind () + == TyTy::InferType::InferTypeKind::INTEGRAL + || r->get_infer_kind () + == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return rtype->clone (); + } + break; + + case TyTy::InferType::InferTypeKind::FLOAT: { + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT + || r->get_infer_kind () + == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return rtype->clone (); + } + break; + } + } + break; + + case TyTy::INT: + case TyTy::UINT: + case TyTy::USIZE: + case TyTy::ISIZE: { + bool is_valid = (ltype->get_infer_kind () + == TyTy::InferType::InferTypeKind::GENERAL) + || (ltype->get_infer_kind () + == TyTy::InferType::InferTypeKind::INTEGRAL); + if (is_valid) + return rtype->clone (); + } + break; + + case TyTy::FLOAT: { + bool is_valid = (ltype->get_infer_kind () + == TyTy::InferType::InferTypeKind::GENERAL) + || (ltype->get_infer_kind () + == TyTy::InferType::InferTypeKind::FLOAT); + if (is_valid) + return rtype->clone (); + } + break; + + case TyTy::ADT: + case TyTy::STR: + case TyTy::REF: + case TyTy::POINTER: + case TyTy::PARAM: + case TyTy::ARRAY: + case TyTy::SLICE: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: { + bool is_valid = (ltype->get_infer_kind () + == TyTy::InferType::InferTypeKind::GENERAL); + if (is_valid) + return rtype->clone (); + } + break; + + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::ADT: { + TyTy::ADTType &type = *static_cast (rtype); + if (ltype->get_adt_kind () != type.get_adt_kind ()) + { + return new TyTy::ErrorType (0); + } + + if (ltype->get_identifier ().compare (type.get_identifier ()) != 0) + { + return new TyTy::ErrorType (0); + } + + if (ltype->number_of_variants () != type.number_of_variants ()) + { + return new TyTy::ErrorType (0); + } + + for (size_t i = 0; i < type.number_of_variants (); ++i) + { + TyTy::VariantDef *a = ltype->get_variants ().at (i); + TyTy::VariantDef *b = type.get_variants ().at (i); + + if (a->num_fields () != b->num_fields ()) + { + return new TyTy::ErrorType (0); + } + + for (size_t j = 0; j < a->num_fields (); j++) + { + TyTy::StructFieldType *base_field = a->get_field_at_index (j); + TyTy::StructFieldType *other_field = b->get_field_at_index (j); + + TyTy::BaseType *this_field_ty = base_field->get_field_type (); + TyTy::BaseType *other_field_ty = other_field->get_field_type (); + + TyTy::BaseType *unified_ty + = UnifyRules::Resolve (TyTy::TyWithLocation (this_field_ty), + TyTy::TyWithLocation (other_field_ty), + locus, commit_flag, + false /* emit_error */); + if (unified_ty->get_kind () == TyTy::TypeKind::ERROR) + { + return new TyTy::ErrorType (0); + } + } + } + + // generic args for the unit-struct case + if (type.is_unit () && ltype->is_unit ()) + { + rust_assert (type.get_num_substitutions () + == ltype->get_num_substitutions ()); + + for (size_t i = 0; i < type.get_num_substitutions (); i++) + { + auto &a = ltype->get_substs ().at (i); + auto &b = type.get_substs ().at (i); + + auto pa = a.get_param_ty (); + auto pb = b.get_param_ty (); + + auto res + = UnifyRules::Resolve (TyTy::TyWithLocation (pa), + TyTy::TyWithLocation (pb), locus, + commit_flag, false /* emit_error */); + if (res->get_kind () == TyTy::TypeKind::ERROR) + { + return new TyTy::ErrorType (0); + } + } + } + + return type.clone (); + } + break; + + case TyTy::STR: + case TyTy::REF: + case TyTy::POINTER: + case TyTy::PARAM: + case TyTy::ARRAY: + case TyTy::SLICE: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::UINT: + case TyTy::FLOAT: + case TyTy::USIZE: + case TyTy::ISIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::STR: + return rtype->clone (); + + case TyTy::ADT: + case TyTy::REF: + case TyTy::POINTER: + case TyTy::PARAM: + case TyTy::ARRAY: + case TyTy::SLICE: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::UINT: + case TyTy::FLOAT: + case TyTy::USIZE: + case TyTy::ISIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::REF: { + TyTy::ReferenceType &type = *static_cast (rtype); + auto base_type = ltype->get_base (); + auto other_base_type = type.get_base (); + + TyTy::BaseType *base_resolved + = UnifyRules::Resolve (TyTy::TyWithLocation (base_type), + TyTy::TyWithLocation (other_base_type), locus, + commit_flag, false /* emit_error */); + if (base_resolved->get_kind () == TyTy::TypeKind::ERROR) + { + return new TyTy::ErrorType (0); + } + + // rust is permissive about mutablity here you can always go from + // mutable to immutable but not the otherway round + bool mutability_ok = ltype->is_mutable () ? type.is_mutable () : true; + if (!mutability_ok) + { + return new TyTy::ErrorType (0); + } + + return new TyTy::ReferenceType (ltype->get_ref (), ltype->get_ty_ref (), + TyTy::TyVar (base_resolved->get_ref ()), + ltype->mutability ()); + } + break; + + case TyTy::STR: + case TyTy::ADT: + case TyTy::POINTER: + case TyTy::PARAM: + case TyTy::ARRAY: + case TyTy::SLICE: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::UINT: + case TyTy::FLOAT: + case TyTy::USIZE: + case TyTy::ISIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::POINTER: { + TyTy::PointerType &type = *static_cast (rtype); + auto base_type = ltype->get_base (); + auto other_base_type = type.get_base (); + + TyTy::BaseType *base_resolved + = UnifyRules::Resolve (TyTy::TyWithLocation (base_type), + TyTy::TyWithLocation (other_base_type), locus, + commit_flag, false /* emit_error */); + if (base_resolved->get_kind () == TyTy::TypeKind::ERROR) + { + return new TyTy::ErrorType (0); + } + + // rust is permissive about mutablity here you can always go from + // mutable to immutable but not the otherway round + bool mutability_ok = ltype->is_mutable () ? type.is_mutable () : true; + if (!mutability_ok) + { + return new TyTy::ErrorType (0); + } + + return new TyTy::PointerType (ltype->get_ref (), ltype->get_ty_ref (), + TyTy::TyVar (base_resolved->get_ref ()), + ltype->mutability ()); + } + break; + + case TyTy::STR: + case TyTy::ADT: + case TyTy::REF: + case TyTy::PARAM: + case TyTy::ARRAY: + case TyTy::SLICE: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::UINT: + case TyTy::FLOAT: + case TyTy::USIZE: + case TyTy::ISIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::PARAM: { + TyTy::ParamType &type = *static_cast (rtype); + // bool symbol_matches + // = ltype->get_symbol ().compare (type.get_symbol ()) == 0; + // // TODO + // // I think rustc checks a debruinj index + // if (symbol_matches) + // { + // return type.clone (); + // } + + // matching symbol is not going to work when we mix symbol's and have + // nested generics + + // bounds match? FIXME + + return type.clone (); + } + break; + + case TyTy::POINTER: + case TyTy::STR: + case TyTy::ADT: + case TyTy::REF: + case TyTy::ARRAY: + case TyTy::SLICE: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::UINT: + case TyTy::FLOAT: + case TyTy::USIZE: + case TyTy::ISIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::ARRAY: { + TyTy::ArrayType &type = *static_cast (rtype); + TyTy::BaseType *element_unify = UnifyRules::Resolve ( + TyTy::TyWithLocation (ltype->get_element_type ()), + TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag, + false /* emit_error*/); + + if (element_unify->get_kind () != TyTy::TypeKind::ERROR) + { + return new TyTy::ArrayType (type.get_ref (), type.get_ty_ref (), + type.get_ident ().locus, + type.get_capacity_expr (), + TyTy::TyVar ( + element_unify->get_ref ())); + } + } + break; + + case TyTy::PARAM: + case TyTy::POINTER: + case TyTy::STR: + case TyTy::ADT: + case TyTy::REF: + case TyTy::SLICE: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::UINT: + case TyTy::FLOAT: + case TyTy::USIZE: + case TyTy::ISIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::SLICE: { + TyTy::SliceType &type = *static_cast (rtype); + TyTy::BaseType *element_unify = UnifyRules::Resolve ( + TyTy::TyWithLocation (ltype->get_element_type ()), + TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag, + false /* emit_error*/); + + if (element_unify->get_kind () != TyTy::TypeKind::ERROR) + { + return new TyTy::SliceType (type.get_ref (), type.get_ty_ref (), + type.get_ident ().locus, + TyTy::TyVar ( + element_unify->get_ref ())); + } + } + break; + + case TyTy::PARAM: + case TyTy::POINTER: + case TyTy::STR: + case TyTy::ADT: + case TyTy::REF: + case TyTy::ARRAY: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::UINT: + case TyTy::FLOAT: + case TyTy::USIZE: + case TyTy::ISIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::FNDEF: { + TyTy::FnType &type = *static_cast (rtype); + if (ltype->num_params () != type.num_params ()) + { + return new TyTy::ErrorType (0); + } + + for (size_t i = 0; i < ltype->num_params (); i++) + { + auto a = ltype->param_at (i).second; + auto b = type.param_at (i).second; + + auto unified_param + = UnifyRules::Resolve (TyTy::TyWithLocation (a), + TyTy::TyWithLocation (b), locus, + commit_flag, false /* emit_errors */); + if (unified_param->get_kind () == TyTy::TypeKind::ERROR) + { + return new TyTy::ErrorType (0); + } + } + + auto unified_return + = UnifyRules::Resolve (TyTy::TyWithLocation ( + ltype->get_return_type ()), + TyTy::TyWithLocation (type.get_return_type ()), + locus, commit_flag, false /* emit_errors */); + if (unified_return->get_kind () == TyTy::TypeKind::ERROR) + { + return new TyTy::ErrorType (0); + } + + return ltype->clone (); + } + break; + + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::FLOAT: + case TyTy::ISIZE: + case TyTy::ADT: + case TyTy::STR: + case TyTy::REF: + case TyTy::POINTER: + case TyTy::PARAM: + case TyTy::ARRAY: + case TyTy::SLICE: + case TyTy::FNPTR: + case TyTy::UINT: + case TyTy::USIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::FNPTR: { + TyTy::FnPtr &type = *static_cast (rtype); + if (ltype->num_params () != type.num_params ()) + { + return new TyTy::ErrorType (0); + } + + for (size_t i = 0; i < ltype->num_params (); i++) + { + auto a = ltype->param_at (i); + auto b = type.param_at (i); + + auto unified_param + = UnifyRules::Resolve (TyTy::TyWithLocation (a), + TyTy::TyWithLocation (b), locus, + commit_flag, false /* emit_errors */); + if (unified_param->get_kind () == TyTy::TypeKind::ERROR) + { + return new TyTy::ErrorType (0); + } + } + + auto unified_return + = UnifyRules::Resolve (TyTy::TyWithLocation ( + ltype->get_return_type ()), + TyTy::TyWithLocation (type.get_return_type ()), + locus, commit_flag, false /* emit_errors */); + if (unified_return->get_kind () == TyTy::TypeKind::ERROR) + { + return new TyTy::ErrorType (0); + } + + return ltype->clone (); + } + break; + + case TyTy::FNDEF: { + TyTy::FnType &type = *static_cast (rtype); + auto this_ret_type = ltype->get_return_type (); + auto other_ret_type = type.get_return_type (); + + auto unified_result + = UnifyRules::Resolve (TyTy::TyWithLocation (this_ret_type), + TyTy::TyWithLocation (other_ret_type), locus, + commit_flag, false /*emit_errors*/); + if (unified_result->get_kind () == TyTy::TypeKind::ERROR) + { + return new TyTy::ErrorType (0); + } + + if (ltype->num_params () != type.num_params ()) + { + return new TyTy::ErrorType (0); + } + + for (size_t i = 0; i < ltype->num_params (); i++) + { + auto this_param = ltype->param_at (i); + auto other_param = type.param_at (i).second; + + auto unified_param + = UnifyRules::Resolve (TyTy::TyWithLocation (this_param), + TyTy::TyWithLocation (other_param), locus, + commit_flag, false /* emit_errors */); + if (unified_param->get_kind () == TyTy::TypeKind::ERROR) + { + return new TyTy::ErrorType (0); + } + } + + return ltype->clone (); + } + break; + + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::FLOAT: + case TyTy::ISIZE: + case TyTy::ADT: + case TyTy::STR: + case TyTy::REF: + case TyTy::POINTER: + case TyTy::PARAM: + case TyTy::ARRAY: + case TyTy::SLICE: + case TyTy::UINT: + case TyTy::USIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::TUPLE: { + TyTy::TupleType &type = *static_cast (rtype); + if (ltype->num_fields () != type.num_fields ()) + { + return new TyTy::ErrorType (0); + } + + std::vector fields; + for (size_t i = 0; i < ltype->num_fields (); i++) + { + TyTy::BaseType *bo = ltype->get_field (i); + TyTy::BaseType *fo = type.get_field (i); + + TyTy::BaseType *unified_ty + = UnifyRules::Resolve (TyTy::TyWithLocation (bo), + TyTy::TyWithLocation (fo), locus, + commit_flag, false /* emit_errors */); + if (unified_ty->get_kind () == TyTy::TypeKind::ERROR) + return new TyTy::ErrorType (0); + + fields.push_back (TyTy::TyVar (unified_ty->get_ref ())); + } + + return new TyTy::TupleType (type.get_ref (), type.get_ty_ref (), + type.get_ident ().locus, fields); + } + break; + + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::FLOAT: + case TyTy::ISIZE: + case TyTy::ADT: + case TyTy::STR: + case TyTy::REF: + case TyTy::POINTER: + case TyTy::PARAM: + case TyTy::ARRAY: + case TyTy::SLICE: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::UINT: + case TyTy::USIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::BOOL: + return rtype->clone (); + + case TyTy::CHAR: + case TyTy::INT: + case TyTy::FLOAT: + case TyTy::ISIZE: + case TyTy::ADT: + case TyTy::STR: + case TyTy::REF: + case TyTy::POINTER: + case TyTy::PARAM: + case TyTy::ARRAY: + case TyTy::SLICE: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::UINT: + case TyTy::USIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::CHAR: + return rtype->clone (); + + case TyTy::INT: + case TyTy::FLOAT: + case TyTy::ISIZE: + case TyTy::ADT: + case TyTy::STR: + case TyTy::REF: + case TyTy::POINTER: + case TyTy::PARAM: + case TyTy::ARRAY: + case TyTy::SLICE: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::UINT: + case TyTy::USIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL + || r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::INT: { + TyTy::IntType &type = *static_cast (rtype); + bool is_valid = ltype->get_int_kind () == type.get_int_kind (); + if (is_valid) + return new TyTy::IntType (type.get_ref (), type.get_ty_ref (), + type.get_int_kind ()); + } + break; + + case TyTy::FLOAT: + case TyTy::ISIZE: + case TyTy::ADT: + case TyTy::STR: + case TyTy::REF: + case TyTy::POINTER: + case TyTy::PARAM: + case TyTy::ARRAY: + case TyTy::SLICE: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::UINT: + case TyTy::USIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL + || r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::UINT: { + TyTy::UintType &type = *static_cast (rtype); + bool is_valid = ltype->get_uint_kind () == type.get_uint_kind (); + if (is_valid) + return new TyTy::UintType (type.get_ref (), type.get_ty_ref (), + type.get_uint_kind ()); + } + break; + + case TyTy::FLOAT: + case TyTy::ISIZE: + case TyTy::ADT: + case TyTy::STR: + case TyTy::REF: + case TyTy::POINTER: + case TyTy::PARAM: + case TyTy::ARRAY: + case TyTy::SLICE: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::USIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL + || r->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::FLOAT: { + TyTy::FloatType &type = *static_cast (rtype); + bool is_valid = ltype->get_float_kind () == type.get_float_kind (); + if (is_valid) + return new TyTy::FloatType (type.get_ref (), type.get_ty_ref (), + type.get_float_kind ()); + } + break; + + case TyTy::ISIZE: + case TyTy::ADT: + case TyTy::STR: + case TyTy::REF: + case TyTy::POINTER: + case TyTy::PARAM: + case TyTy::ARRAY: + case TyTy::SLICE: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::UINT: + case TyTy::USIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::ISIZE: + return rtype->clone (); + + case TyTy::ADT: + case TyTy::STR: + case TyTy::REF: + case TyTy::POINTER: + case TyTy::PARAM: + case TyTy::ARRAY: + case TyTy::SLICE: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::UINT: + case TyTy::FLOAT: + case TyTy::USIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::USIZE: + return rtype->clone (); + + case TyTy::ADT: + case TyTy::STR: + case TyTy::REF: + case TyTy::POINTER: + case TyTy::PARAM: + case TyTy::ARRAY: + case TyTy::SLICE: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::UINT: + case TyTy::FLOAT: + case TyTy::ISIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_never (TyTy::NeverType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::NEVER: + return rtype->clone (); + + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::SLICE: + case TyTy::PARAM: + case TyTy::POINTER: + case TyTy::STR: + case TyTy::ADT: + case TyTy::REF: + case TyTy::ARRAY: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::UINT: + case TyTy::FLOAT: + case TyTy::USIZE: + case TyTy::ISIZE: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_placeholder (TyTy::PlaceholderType *ltype, + TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::PLACEHOLDER: { + TyTy::PlaceholderType &type + = *static_cast (rtype); + bool symbol_match + = ltype->get_symbol ().compare (type.get_symbol ()) == 0; + if (symbol_match) + { + return type.clone (); + } + } + break; + + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::SLICE: + case TyTy::PARAM: + case TyTy::POINTER: + case TyTy::STR: + case TyTy::ADT: + case TyTy::REF: + case TyTy::ARRAY: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::UINT: + case TyTy::FLOAT: + case TyTy::USIZE: + case TyTy::ISIZE: + case TyTy::NEVER: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_projection (TyTy::ProjectionType *ltype, + TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + // FIXME + case TyTy::PROJECTION: + gcc_unreachable (); + break; + + case TyTy::DYNAMIC: + case TyTy::CLOSURE: + case TyTy::SLICE: + case TyTy::PARAM: + case TyTy::POINTER: + case TyTy::STR: + case TyTy::ADT: + case TyTy::REF: + case TyTy::ARRAY: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::UINT: + case TyTy::FLOAT: + case TyTy::USIZE: + case TyTy::ISIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::DYNAMIC: { + TyTy::DynamicObjectType &type + = *static_cast (rtype); + if (ltype->num_specified_bounds () != type.num_specified_bounds ()) + { + return new TyTy::ErrorType (0); + } + + if (!ltype->bounds_compatible (type, locus, true)) + { + return new TyTy::ErrorType (0); + } + + return ltype->clone (); + } + break; + + case TyTy::CLOSURE: + case TyTy::SLICE: + case TyTy::PARAM: + case TyTy::POINTER: + case TyTy::STR: + case TyTy::ADT: + case TyTy::REF: + case TyTy::ARRAY: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::UINT: + case TyTy::FLOAT: + case TyTy::USIZE: + case TyTy::ISIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +TyTy::BaseType * +UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) +{ + switch (rtype->get_kind ()) + { + case TyTy::INFER: { + TyTy::InferType *r = static_cast (rtype); + bool is_valid + = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; + if (is_valid) + return ltype->clone (); + } + break; + + case TyTy::CLOSURE: { + TyTy::ClosureType &type = *static_cast (rtype); + if (ltype->get_def_id () != type.get_def_id ()) + { + return new TyTy::ErrorType (0); + } + + TyTy::BaseType *args_res + = UnifyRules::Resolve (TyTy::TyWithLocation ( + <ype->get_parameters ()), + TyTy::TyWithLocation (&type.get_parameters ()), + locus, commit_flag, false /* emit_error */); + if (args_res->get_kind () == TyTy::TypeKind::ERROR) + { + return new TyTy::ErrorType (0); + } + + TyTy::BaseType *res = UnifyRules::Resolve ( + TyTy::TyWithLocation (<ype->get_result_type ()), + TyTy::TyWithLocation (&type.get_result_type ()), locus, commit_flag, + false /* emit_error */); + if (res == nullptr || res->get_kind () == TyTy::TypeKind::ERROR) + { + return new TyTy::ErrorType (0); + } + + return ltype->clone (); + } + break; + + case TyTy::SLICE: + case TyTy::PARAM: + case TyTy::POINTER: + case TyTy::STR: + case TyTy::ADT: + case TyTy::REF: + case TyTy::ARRAY: + case TyTy::FNDEF: + case TyTy::FNPTR: + case TyTy::TUPLE: + case TyTy::BOOL: + case TyTy::CHAR: + case TyTy::INT: + case TyTy::UINT: + case TyTy::FLOAT: + case TyTy::USIZE: + case TyTy::ISIZE: + case TyTy::NEVER: + case TyTy::PLACEHOLDER: + case TyTy::PROJECTION: + case TyTy::DYNAMIC: + case TyTy::ERROR: + return new TyTy::ErrorType (0); + } + return new TyTy::ErrorType (0); +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h new file mode 100644 index 0000000..6e46b96 --- /dev/null +++ b/gcc/rust/typecheck/rust-unify.h @@ -0,0 +1,91 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_UNIFY +#define RUST_UNIFY + +#include "rust-tyty-util.h" +#include "rust-hir-type-check.h" + +namespace Rust { +namespace Resolver { + +class UnifyRules +{ +public: + static TyTy::BaseType *Resolve (TyTy::TyWithLocation lhs, + TyTy::TyWithLocation rhs, Location locus, + bool commit_flag, bool emit_error); + +protected: + TyTy::BaseType *expect_inference_variable (TyTy::InferType *ltype, + TyTy::BaseType *rtype); + TyTy::BaseType *expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_reference (TyTy::ReferenceType *ltype, + TyTy::BaseType *rtype); + TyTy::BaseType *expect_pointer (TyTy::PointerType *ltype, + TyTy::BaseType *rtype); + TyTy::BaseType *expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_never (TyTy::NeverType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_placeholder (TyTy::PlaceholderType *ltype, + TyTy::BaseType *rtype); + TyTy::BaseType *expect_projection (TyTy::ProjectionType *ltype, + TyTy::BaseType *rtype); + TyTy::BaseType *expect_dyn (TyTy::DynamicObjectType *ltype, + TyTy::BaseType *rtype); + TyTy::BaseType *expect_closure (TyTy::ClosureType *ltype, + TyTy::BaseType *rtype); + +private: + UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, + Location locus, bool commit_flag, bool emit_error); + + void emit_type_mismatch () const; + void commit (TyTy::BaseType *resolved); + TyTy::BaseType *go (); + + TyTy::BaseType *get_base (); + TyTy::BaseType *get_other (); + + TyTy::TyWithLocation lhs; + TyTy::TyWithLocation rhs; + Location locus; + bool commit_flag; + bool emit_error; + + Analysis::Mappings &mappings; + TypeCheckContext &context; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_UNIFY diff --git a/gcc/testsuite/rust/compile/never_type1.rs b/gcc/testsuite/rust/compile/never_type1.rs new file mode 100644 index 0000000..8d56176 --- /dev/null +++ b/gcc/testsuite/rust/compile/never_type1.rs @@ -0,0 +1,13 @@ +fn test() { + let a; + + a = if true { + return; + } else { + return; + }; +} + +fn main() { + test(); +} diff --git a/gcc/testsuite/rust/compile/never_type_err1.rs b/gcc/testsuite/rust/compile/never_type_err1.rs deleted file mode 100644 index 52b1283..0000000 --- a/gcc/testsuite/rust/compile/never_type_err1.rs +++ /dev/null @@ -1,14 +0,0 @@ -fn test() { - let a; - - // FIXME: Unimplemented features - a = if true { // { dg-error "expected .T.. got .!." } - return; - } else { - return; - }; -} - -fn main() { - test(); -} -- cgit v1.1 From e612713029296dac8429e4b00ec7659bcad5cffe Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 31 Jan 2023 14:27:49 +0000 Subject: gccrs: Fix nullptr dereference When we check if this is concrete the guard checks to ensure the argument is non null but the check here is wrongly returning early when the check is non null meaning when it is null and therefore not concrete it will end up doing a null dereference. Signed-off-by: Philip Herron gcc/rust/ChangeLog: * typecheck/rust-tyty-subst.cc (SubstitutionArg::is_conrete): fix check --- gcc/rust/typecheck/rust-tyty-subst.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc index 7f5bb22..996bbf2 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.cc +++ b/gcc/rust/typecheck/rust-tyty-subst.cc @@ -213,8 +213,8 @@ SubstitutionArg::is_error () const bool SubstitutionArg::is_conrete () const { - if (argument != nullptr) - return true; + if (argument == nullptr) + return false; if (argument->get_kind () == TyTy::TypeKind::PARAM) return false; -- cgit v1.1 From d4e6b64e7f9e23aeb5d3c40665f18091575921ed Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 31 Jan 2023 14:39:29 +0000 Subject: gccrs: Add missing Sized, Copy and Clone lang item mappings We need these lang items to be defined and later down the line the mappings will be used to implement proper copy and clone logic. Fixes #1786 Signed-off-by: Philip Herron gcc/rust/ChangeLog: * util/rust-lang-item.h: gcc/testsuite/ChangeLog: * rust/compile/issue-1786.rs: New test. --- gcc/rust/util/rust-lang-item.h | 24 ++++++++++++++++++++++++ gcc/testsuite/rust/compile/issue-1786.rs | 23 +++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 gcc/testsuite/rust/compile/issue-1786.rs (limited to 'gcc') diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h index 52f53fa..5bad08a 100644 --- a/gcc/rust/util/rust-lang-item.h +++ b/gcc/rust/util/rust-lang-item.h @@ -80,6 +80,12 @@ public: FN_ONCE, FN_ONCE_OUTPUT, + // markers + COPY, + CLONE, + SIZED, + + // delimiter UNKNOWN, }; @@ -237,6 +243,18 @@ public: { return ItemType::FN_ONCE_OUTPUT; } + else if (item.compare ("copy") == 0) + { + return ItemType::COPY; + } + else if (item.compare ("clone") == 0) + { + return ItemType::CLONE; + } + else if (item.compare ("sized") == 0) + { + return ItemType::SIZED; + } return ItemType::UNKNOWN; } @@ -321,6 +339,12 @@ public: return "fn_once"; case FN_ONCE_OUTPUT: return "fn_once_output"; + case COPY: + return "copy"; + case CLONE: + return "clone"; + case SIZED: + return "sized"; case UNKNOWN: return ""; diff --git a/gcc/testsuite/rust/compile/issue-1786.rs b/gcc/testsuite/rust/compile/issue-1786.rs new file mode 100644 index 0000000..f73b63d --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-1786.rs @@ -0,0 +1,23 @@ +#[lang = "clone"] +trait Clone { + fn clone(&self) -> Self; + + fn clone_from(&mut self, source: &Self) { + *self = source.clone() + } +} + +#[lang = "copy"] +pub trait Copy: Clone { + // Empty. +} + +mod impls { + use super::Clone; + + impl Clone for char { + fn clone(&self) -> Self { + *self + } + } +} -- cgit v1.1 From aff069dfb1fb1dcd785d5af68373d83289d62c72 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 31 Jan 2023 18:52:33 +0000 Subject: gccrs: Fix higher ranked trait bounds computation of self This updates the higher ranked trait bounds computation to handle ambigious cases. When we have a slice for example: let slice = &a[1..3]; This works by reusing the Index operator overload from libcore, so when the index range of 1..3 is computed, the type system needs to compute what the types of index are; this works by integer inference variables Range<> that need to be unified with the impl Index for Range which computes the real type of usize for the index. This is fine but what happens when we have the Copy and Clone traits bounds which have implementations for all the primitive types i8, i16, i32, i64... which is valid for any integer inference variable so the code prior to this patch would have grabbed the first impl it would have found and used it which is incorrect. When we have integer or float inference variables we need to look for their respective defaults or emit an ambigious type bound error. Signed-off-by: Philip Herron gcc/rust/ChangeLog: * typecheck/rust-hir-trait-reference.h: add const infterface * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::get_generic_param): make const (SubstitutionRef::monomorphize): fix issue * typecheck/rust-tyty-subst.h: constify interface --- gcc/rust/typecheck/rust-hir-trait-reference.h | 1 + gcc/rust/typecheck/rust-tyty-subst.cc | 107 ++++++++++++++++++++++++-- gcc/rust/typecheck/rust-tyty-subst.h | 2 +- 3 files changed, 102 insertions(+), 8 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h index 0d4da3b..aec1dd5 100644 --- a/gcc/rust/typecheck/rust-hir-trait-reference.h +++ b/gcc/rust/typecheck/rust-hir-trait-reference.h @@ -496,6 +496,7 @@ public: HIR::ImplBlock *get_impl_block () { return impl; } TyTy::BaseType *get_self () { return self; } + const TyTy::BaseType *get_self () const { return self; } TyTy::BaseType * setup_associated_types (const TyTy::BaseType *self, diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc index 996bbf2..3dfe958 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.cc +++ b/gcc/rust/typecheck/rust-tyty-subst.cc @@ -65,7 +65,7 @@ SubstitutionParamMapping::get_param_ty () const } const HIR::TypeParam & -SubstitutionParamMapping::get_generic_param () +SubstitutionParamMapping::get_generic_param () const { return generic; } @@ -892,8 +892,7 @@ SubstitutionRef::monomorphize () // setup any associated type mappings for the specified bonds and this // type auto candidates = Resolver::TypeBoundsProbe::Probe (binding); - - Resolver::AssociatedImplTrait *associated_impl_trait = nullptr; + std::vector associated_impl_traits; for (auto &probed_bound : candidates) { const Resolver::TraitReference *bound_trait_ref @@ -914,15 +913,109 @@ SubstitutionRef::monomorphize () = associated->get_self ()->can_eq (binding, false); if (found_trait && found_self) { - associated_impl_trait = associated; - break; + associated_impl_traits.push_back (associated); } } } - if (associated_impl_trait != nullptr) + if (!associated_impl_traits.empty ()) { - associated_impl_trait->setup_associated_types (binding, bound); + // This code is important when you look at slices for example when + // you have a slice such as: + // + // let slice = &array[1..3] + // + // the higher ranked bounds will end up having an Index trait + // implementation for Range so we need this code to resolve + // that we have an integer inference variable that needs to become + // a usize + // + // The other complicated issue is that we might have an intrinsic + // which requires the :Clone or Copy bound but the libcore adds + // implementations for all the integral types so when there are + // multiple candidates we need to resolve to the default + // implementation for that type otherwise its an error for + // ambiguous type bounds + + if (associated_impl_traits.size () == 1) + { + Resolver::AssociatedImplTrait *associate_impl_trait + = associated_impl_traits.at (0); + associate_impl_trait->setup_associated_types (binding, bound); + } + else + { + // if we have a non-general inference variable we need to be + // careful about the selection here + bool is_infer_var + = binding->get_kind () == TyTy::TypeKind::INFER; + bool is_integer_infervar + = is_infer_var + && static_cast (binding) + ->get_infer_kind () + == TyTy::InferType::InferTypeKind::INTEGRAL; + bool is_float_infervar + = is_infer_var + && static_cast (binding) + ->get_infer_kind () + == TyTy::InferType::InferTypeKind::FLOAT; + + Resolver::AssociatedImplTrait *associate_impl_trait = nullptr; + if (is_integer_infervar) + { + TyTy::BaseType *type = nullptr; + bool ok = context->lookup_builtin ("i32", &type); + rust_assert (ok); + + for (auto &impl : associated_impl_traits) + { + bool found = impl->get_self ()->is_equal (*type); + if (found) + { + associate_impl_trait = impl; + break; + } + } + } + else if (is_float_infervar) + { + TyTy::BaseType *type = nullptr; + bool ok = context->lookup_builtin ("f64", &type); + rust_assert (ok); + + for (auto &impl : associated_impl_traits) + { + bool found = impl->get_self ()->is_equal (*type); + if (found) + { + associate_impl_trait = impl; + break; + } + } + } + + if (associate_impl_trait == nullptr) + { + // go for the first one? or error out? + auto &mappings = *Analysis::Mappings::get (); + const auto &type_param = subst.get_generic_param (); + const auto *trait_ref = bound.get (); + + RichLocation r (type_param.get_locus ()); + r.add_range (bound.get_locus ()); + r.add_range ( + mappings.lookup_location (binding->get_ref ())); + + rust_error_at ( + r, "ambiguous type bound for trait %s and type %s", + trait_ref->get_name ().c_str (), + binding->get_name ().c_str ()); + + return false; + } + + associate_impl_trait->setup_associated_types (binding, bound); + } } } } diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h index 039eb36..982861e 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.h +++ b/gcc/rust/typecheck/rust-tyty-subst.h @@ -48,7 +48,7 @@ public: const ParamType *get_param_ty () const; - const HIR::TypeParam &get_generic_param (); + const HIR::TypeParam &get_generic_param () const; // this is used for the backend to override the HirId ref of the param to // what the concrete type is for the rest of the context -- cgit v1.1 From 1b0794c172c4e60ee4cd7f2fd3a2426997b1d0a1 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 4 Feb 2023 23:02:31 +0000 Subject: gccrs: Remove bad error message on checking function arguments Signed-off-by: Philip Herron gcc/rust/ChangeLog: * typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): remove error message gcc/testsuite/ChangeLog: * rust/compile/func3.rs: update test case --- gcc/rust/typecheck/rust-tyty-call.cc | 5 ----- gcc/testsuite/rust/compile/func3.rs | 1 - 2 files changed, 6 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc index 6ff0113..4010c60 100644 --- a/gcc/rust/typecheck/rust-tyty-call.cc +++ b/gcc/rust/typecheck/rust-tyty-call.cc @@ -140,8 +140,6 @@ TypeCheckCallExpr::visit (FnType &type) argument->get_locus ()); if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR) { - rust_error_at (argument->get_locus (), - "Type Resolution failure on parameter"); return; } } @@ -193,8 +191,6 @@ TypeCheckCallExpr::visit (FnPtr &type) TyWithLocation (argument_expr_tyty, arg_locus), argument->get_locus ()); if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR) { - rust_error_at (argument->get_locus (), - "Type Resolution failure on parameter"); return; } @@ -301,7 +297,6 @@ TypeCheckMethodCallExpr::check (FnType &type) TyWithLocation (argument_expr_tyty, arg_locus), arg_locus); if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR) { - rust_error_at (arg_locus, "Type Resolution failure on parameter"); return new ErrorType (type.get_ref ()); } diff --git a/gcc/testsuite/rust/compile/func3.rs b/gcc/testsuite/rust/compile/func3.rs index 2a32947..002e5c9 100644 --- a/gcc/testsuite/rust/compile/func3.rs +++ b/gcc/testsuite/rust/compile/func3.rs @@ -5,5 +5,4 @@ fn test(a: i32, b: i32) -> i32 { fn main() { let a = test(1, true); // { dg-error "expected .i32. got .bool." "" { target *-*-* } .-1 } - // { dg-error "Type Resolution failure on parameter" "" { target *-*-* } .-2 } } -- cgit v1.1 From 6d7a7b22882433d46bf4e4efe8c43343892c91eb Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 4 Feb 2023 22:53:48 +0000 Subject: gccrs: Add general TypeBounds checks Existing tests are updated to use libcore copy and clone implementation. Addresses #1725 Signed-off-by: Philip Herron gcc/rust/ChangeLog: * typecheck/rust-unify.cc (UnifyRules::go): ensure the bounds are checked gcc/testsuite/ChangeLog: * rust/compile/torture/intrinsics-4.rs: implement Copy trait * rust/compile/torture/intrinsics-5.rs: likewise * rust/execute/torture/atomic_load.rs: likewise * rust/execute/torture/atomic_store.rs: likewise * rust/bounds1.rs: New test. --- gcc/rust/typecheck/rust-unify.cc | 11 ++++ gcc/testsuite/rust/bounds1.rs | 19 +++++++ gcc/testsuite/rust/compile/torture/intrinsics-4.rs | 63 ++++++++++++++++++++- gcc/testsuite/rust/compile/torture/intrinsics-5.rs | 66 +++++++++++++++++++++- gcc/testsuite/rust/execute/torture/atomic_load.rs | 59 ++++++++++++++++++- gcc/testsuite/rust/execute/torture/atomic_store.rs | 59 ++++++++++++++++++- 6 files changed, 271 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/rust/bounds1.rs (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc index 072f761..415ffcd 100644 --- a/gcc/rust/typecheck/rust-unify.cc +++ b/gcc/rust/typecheck/rust-unify.cc @@ -124,6 +124,17 @@ UnifyRules::go () rust_debug ("unify::go ltype={%s} rtype={%s}", ltype->debug_str ().c_str (), rtype->debug_str ().c_str ()); + // check bounds + if (ltype->num_specified_bounds () > 0) + { + if (!ltype->bounds_compatible (*rtype, locus, true)) + { + // already emitted an error + emit_error = false; + return new TyTy::ErrorType (0); + } + } + switch (ltype->get_kind ()) { case TyTy::INFER: diff --git a/gcc/testsuite/rust/bounds1.rs b/gcc/testsuite/rust/bounds1.rs new file mode 100644 index 0000000..6658360 --- /dev/null +++ b/gcc/testsuite/rust/bounds1.rs @@ -0,0 +1,19 @@ +mod core { + mod ops { + #[lang = "add"] + pub trait Add { + type Output; + + fn add(self, rhs: Rhs) -> Self::Output; + } + } +} + +pub fn foo>(a: T) -> i32 { + // { dg-error "bounds not satisfied for f32 .Add. is not satisfied" "" { target *-*-* } .-1 } + a + a +} + +pub fn main() { + foo(123f32); +} diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-4.rs b/gcc/testsuite/rust/compile/torture/intrinsics-4.rs index 243d446..4e09f10 100644 --- a/gcc/testsuite/rust/compile/torture/intrinsics-4.rs +++ b/gcc/testsuite/rust/compile/torture/intrinsics-4.rs @@ -1,10 +1,67 @@ -trait Copy {} +#[lang = "sized"] +pub trait Sized {} + +#[lang = "clone"] +pub trait Clone: Sized { + fn clone(&self) -> Self; + + fn clone_from(&mut self, source: &Self) { + *self = source.clone() + } +} + +mod impls { + use super::Clone; + + macro_rules! impl_clone { + ($($t:ty)*) => { + $( + impl Clone for $t { + fn clone(&self) -> Self { + *self + } + } + )* + } + } + + impl_clone! { + usize u8 u16 u32 u64 // u128 + isize i8 i16 i32 i64 // i128 + f32 f64 + bool char + } +} + +#[lang = "copy"] +pub trait Copy: Clone { + // Empty. +} + +mod copy_impls { + use super::Copy; + + macro_rules! impl_copy { + ($($t:ty)*) => { + $( + impl Copy for $t {} + )* + } + } + + impl_copy! { + usize u8 u16 u32 u64 // u128 + isize i8 i16 i32 i64 // i128 + f32 f64 + bool char + } +} extern "rust-intrinsic" { pub fn atomic_store_seqcst(dst: *mut T, val: T); pub fn atomic_store_release(dst: *mut T, val: T); pub fn atomic_store_relaxed(dst: *mut T, val: T); - // pub fn atomic_store_unordered(dst: *mut T, val: T); + pub fn atomic_store_unordered(dst: *mut T, val: T); } fn main() { @@ -15,6 +72,6 @@ fn main() { atomic_store_seqcst(&mut dst, new_value); atomic_store_release(&mut dst, new_value); atomic_store_relaxed(&mut dst, new_value); - // atomic_store_unordered(&mut dst, new_value); + atomic_store_unordered(&mut dst, new_value); } } diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-5.rs b/gcc/testsuite/rust/compile/torture/intrinsics-5.rs index 7fd84dc..ffad0bd 100644 --- a/gcc/testsuite/rust/compile/torture/intrinsics-5.rs +++ b/gcc/testsuite/rust/compile/torture/intrinsics-5.rs @@ -1,4 +1,61 @@ -trait Copy {} +#[lang = "sized"] +pub trait Sized {} + +#[lang = "clone"] +pub trait Clone: Sized { + fn clone(&self) -> Self; + + fn clone_from(&mut self, source: &Self) { + *self = source.clone() + } +} + +mod impls { + use super::Clone; + + macro_rules! impl_clone { + ($($t:ty)*) => { + $( + impl Clone for $t { + fn clone(&self) -> Self { + *self + } + } + )* + } + } + + impl_clone! { + usize u8 u16 u32 u64 // u128 + isize i8 i16 i32 i64 // i128 + f32 f64 + bool char + } +} + +#[lang = "copy"] +pub trait Copy: Clone { + // Empty. +} + +mod copy_impls { + use super::Copy; + + macro_rules! impl_copy { + ($($t:ty)*) => { + $( + impl Copy for $t {} + )* + } + } + + impl_copy! { + usize u8 u16 u32 u64 // u128 + isize i8 i16 i32 i64 // i128 + f32 f64 + bool char + } +} extern "rust-intrinsic" { pub fn atomic_store_seqcst(dst: *mut T, value: T); @@ -24,6 +81,13 @@ impl VeryLargeType { } } +impl Clone for VeryLargeType { + fn clone(&self) -> Self { + *self + } +} +impl Copy for VeryLargeType {} + fn main() { let mut dst = VeryLargeType::new(0); let mut b = false; diff --git a/gcc/testsuite/rust/execute/torture/atomic_load.rs b/gcc/testsuite/rust/execute/torture/atomic_load.rs index 28ed8ae..6e7383a 100644 --- a/gcc/testsuite/rust/execute/torture/atomic_load.rs +++ b/gcc/testsuite/rust/execute/torture/atomic_load.rs @@ -1,4 +1,61 @@ -trait Copy {} +#[lang = "sized"] +pub trait Sized {} + +#[lang = "clone"] +pub trait Clone: Sized { + fn clone(&self) -> Self; + + fn clone_from(&mut self, source: &Self) { + *self = source.clone() + } +} + +mod impls { + use super::Clone; + + macro_rules! impl_clone { + ($($t:ty)*) => { + $( + impl Clone for $t { + fn clone(&self) -> Self { + *self + } + } + )* + } + } + + impl_clone! { + usize u8 u16 u32 u64 // u128 + isize i8 i16 i32 i64 // i128 + f32 f64 + bool char + } +} + +#[lang = "copy"] +pub trait Copy: Clone { + // Empty. +} + +mod copy_impls { + use super::Copy; + + macro_rules! impl_copy { + ($($t:ty)*) => { + $( + impl Copy for $t {} + )* + } + } + + impl_copy! { + usize u8 u16 u32 u64 // u128 + isize i8 i16 i32 i64 // i128 + f32 f64 + bool char + } +} extern "rust-intrinsic" { pub fn atomic_load_seqcst(src: *const T) -> T; diff --git a/gcc/testsuite/rust/execute/torture/atomic_store.rs b/gcc/testsuite/rust/execute/torture/atomic_store.rs index 9f248b4..46960a7 100644 --- a/gcc/testsuite/rust/execute/torture/atomic_store.rs +++ b/gcc/testsuite/rust/execute/torture/atomic_store.rs @@ -1,4 +1,61 @@ -trait Copy {} +#[lang = "sized"] +pub trait Sized {} + +#[lang = "clone"] +pub trait Clone: Sized { + fn clone(&self) -> Self; + + fn clone_from(&mut self, source: &Self) { + *self = source.clone() + } +} + +mod impls { + use super::Clone; + + macro_rules! impl_clone { + ($($t:ty)*) => { + $( + impl Clone for $t { + fn clone(&self) -> Self { + *self + } + } + )* + } + } + + impl_clone! { + usize u8 u16 u32 u64 // u128 + isize i8 i16 i32 i64 // i128 + f32 f64 + bool char + } +} + +#[lang = "copy"] +pub trait Copy: Clone { + // Empty. +} + +mod copy_impls { + use super::Copy; + + macro_rules! impl_copy { + ($($t:ty)*) => { + $( + impl Copy for $t {} + )* + } + } + + impl_copy! { + usize u8 u16 u32 u64 // u128 + isize i8 i16 i32 i64 // i128 + f32 f64 + bool char + } +} extern "rust-intrinsic" { pub fn atomic_store_seqcst(dst: *mut T, val: T); -- cgit v1.1