diff options
author | Philip Herron <philip.herron@embecosm.com> | 2022-02-23 16:50:36 +0000 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2022-02-24 11:19:23 +0000 |
commit | a64983f86c8703d1229a7e8ee0baff07110f5a7c (patch) | |
tree | 0501a0e98734d487f0e6ef90ed220e63353de4fa /gcc | |
parent | 1c3af63eaeae50ab4ae9e11b8d363fe092707b55 (diff) | |
download | gcc-a64983f86c8703d1229a7e8ee0baff07110f5a7c.zip gcc-a64983f86c8703d1229a7e8ee0baff07110f5a7c.tar.gz gcc-a64983f86c8703d1229a7e8ee0baff07110f5a7c.tar.bz2 |
Add typechecking for range expressions
This looks up the relevant lang items and constructs their algebraic data
types with the specified range types for the substitution argument.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/Make-lang.in | 1 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-expr.h | 3 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.cc | 246 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 10 |
4 files changed, 260 insertions, 0 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 9de93fe..69943f9 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -95,6 +95,7 @@ GRS_OBJS = \ rust/rust-hir-type-check-type.o \ rust/rust-hir-type-check-struct.o \ rust/rust-hir-type-check-pattern.o \ + rust/rust-hir-type-check-expr.o \ rust/rust-hir-dot-operator.o \ rust/rust-autoderef.o \ rust/rust-substitution-mapper.o \ diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index d1f34e2..8b98881 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -2430,6 +2430,9 @@ public: void accept_vis (HIRFullVisitor &vis) override; + std::unique_ptr<Expr> &get_from_expr () { return from; } + std::unique_ptr<Expr> &get_to_expr () { return to; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc new file mode 100644 index 0000000..e99432a --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -0,0 +1,246 @@ +// 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 +// <http://www.gnu.org/licenses/>. + +#include "rust-hir-type-check-expr.h" + +namespace Rust { +namespace Resolver { + +void +TypeCheckExpr::visit (HIR::RangeFromToExpr &expr) +{ + auto lang_item_type = Analysis::RustLangItem::ItemType::RANGE; + + DefId respective_lang_item_id = UNKNOWN_DEFID; + bool lang_item_defined + = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id); + + // we need to have it maybe + if (!lang_item_defined) + { + rust_internal_error_at ( + expr.get_locus (), "unable to find relevant lang item: %s", + Analysis::RustLangItem::ToString (lang_item_type).c_str ()); + return; + } + + // look it up and it _must_ be a struct definition + HIR::Item *item = mappings->lookup_defid (respective_lang_item_id); + rust_assert (item != nullptr); + + TyTy::BaseType *item_type = nullptr; + bool ok + = context->lookup_type (item->get_mappings ().get_hirid (), &item_type); + rust_assert (ok); + rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT); + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type); + + // this is a single generic item lets assert that + rust_assert (adt->get_num_substitutions () == 1); + + // resolve the range expressions and these types must unify then we use that + // type to substitute into the ADT + TyTy::BaseType *from_ty + = TypeCheckExpr::Resolve (expr.get_from_expr ().get (), false); + TyTy::BaseType *to_ty + = TypeCheckExpr::Resolve (expr.get_to_expr ().get (), false); + TyTy::BaseType *unified = from_ty->unify (to_ty); + + // substitute it in + std::vector<TyTy::SubstitutionArg> subst_mappings; + const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0); + subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, unified)); + + TyTy::SubstitutionArgumentMappings subst (subst_mappings, expr.get_locus ()); + infered = SubstMapperInternal::Resolve (adt, subst); +} + +void +TypeCheckExpr::visit (HIR::RangeFromExpr &expr) +{ + auto lang_item_type = Analysis::RustLangItem::ItemType::RANGE_FROM; + + DefId respective_lang_item_id = UNKNOWN_DEFID; + bool lang_item_defined + = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id); + + // we need to have it maybe + if (!lang_item_defined) + { + rust_internal_error_at ( + expr.get_locus (), "unable to find relevant lang item: %s", + Analysis::RustLangItem::ToString (lang_item_type).c_str ()); + return; + } + + // look it up and it _must_ be a struct definition + HIR::Item *item = mappings->lookup_defid (respective_lang_item_id); + rust_assert (item != nullptr); + + TyTy::BaseType *item_type = nullptr; + bool ok + = context->lookup_type (item->get_mappings ().get_hirid (), &item_type); + rust_assert (ok); + rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT); + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type); + + // this is a single generic item lets assert that + rust_assert (adt->get_num_substitutions () == 1); + + // resolve the range expressions and these types must unify then we use that + // type to substitute into the ADT + TyTy::BaseType *from_ty + = TypeCheckExpr::Resolve (expr.get_from_expr ().get (), false); + + // substitute it in + std::vector<TyTy::SubstitutionArg> subst_mappings; + const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0); + subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, from_ty)); + + TyTy::SubstitutionArgumentMappings subst (subst_mappings, expr.get_locus ()); + infered = SubstMapperInternal::Resolve (adt, subst); +} + +void +TypeCheckExpr::visit (HIR::RangeToExpr &expr) +{ + auto lang_item_type = Analysis::RustLangItem::ItemType::RANGE_TO; + + DefId respective_lang_item_id = UNKNOWN_DEFID; + bool lang_item_defined + = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id); + + // we need to have it maybe + if (!lang_item_defined) + { + rust_internal_error_at ( + expr.get_locus (), "unable to find relevant lang item: %s", + Analysis::RustLangItem::ToString (lang_item_type).c_str ()); + return; + } + + // look it up and it _must_ be a struct definition + HIR::Item *item = mappings->lookup_defid (respective_lang_item_id); + rust_assert (item != nullptr); + + TyTy::BaseType *item_type = nullptr; + bool ok + = context->lookup_type (item->get_mappings ().get_hirid (), &item_type); + rust_assert (ok); + rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT); + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type); + + // this is a single generic item lets assert that + rust_assert (adt->get_num_substitutions () == 1); + + // resolve the range expressions and these types must unify then we use that + // type to substitute into the ADT + TyTy::BaseType *from_ty + = TypeCheckExpr::Resolve (expr.get_to_expr ().get (), false); + + // substitute it in + std::vector<TyTy::SubstitutionArg> subst_mappings; + const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0); + subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, from_ty)); + + TyTy::SubstitutionArgumentMappings subst (subst_mappings, expr.get_locus ()); + infered = SubstMapperInternal::Resolve (adt, subst); +} + +void +TypeCheckExpr::visit (HIR::RangeFullExpr &expr) +{ + auto lang_item_type = Analysis::RustLangItem::ItemType::RANGE_FULL; + + DefId respective_lang_item_id = UNKNOWN_DEFID; + bool lang_item_defined + = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id); + + // we need to have it maybe + if (!lang_item_defined) + { + rust_internal_error_at ( + expr.get_locus (), "unable to find relevant lang item: %s", + Analysis::RustLangItem::ToString (lang_item_type).c_str ()); + return; + } + + // look it up and it _must_ be a struct definition + HIR::Item *item = mappings->lookup_defid (respective_lang_item_id); + rust_assert (item != nullptr); + + TyTy::BaseType *item_type = nullptr; + bool ok + = context->lookup_type (item->get_mappings ().get_hirid (), &item_type); + rust_assert (ok); + rust_assert (item_type->is_unit ()); + + infered = item_type; +} + +void +TypeCheckExpr::visit (HIR::RangeFromToInclExpr &expr) +{ + auto lang_item_type = Analysis::RustLangItem::ItemType::RANGE_INCLUSIVE; + + DefId respective_lang_item_id = UNKNOWN_DEFID; + bool lang_item_defined + = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id); + + // we need to have it maybe + if (!lang_item_defined) + { + rust_internal_error_at ( + expr.get_locus (), "unable to find relevant lang item: %s", + Analysis::RustLangItem::ToString (lang_item_type).c_str ()); + return; + } + + // look it up and it _must_ be a struct definition + HIR::Item *item = mappings->lookup_defid (respective_lang_item_id); + rust_assert (item != nullptr); + + TyTy::BaseType *item_type = nullptr; + bool ok + = context->lookup_type (item->get_mappings ().get_hirid (), &item_type); + rust_assert (ok); + rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT); + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type); + + // this is a single generic item lets assert that + rust_assert (adt->get_num_substitutions () == 1); + + // resolve the range expressions and these types must unify then we use that + // type to substitute into the ADT + TyTy::BaseType *from_ty + = TypeCheckExpr::Resolve (expr.get_from_expr ().get (), false); + TyTy::BaseType *to_ty + = TypeCheckExpr::Resolve (expr.get_to_expr ().get (), false); + TyTy::BaseType *unified = from_ty->unify (to_ty); + + // substitute it in + std::vector<TyTy::SubstitutionArg> subst_mappings; + const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0); + subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, unified)); + + TyTy::SubstitutionArgumentMappings subst (subst_mappings, expr.get_locus ()); + infered = SubstMapperInternal::Resolve (adt, subst); +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index a4b8f0a..0c3d229 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -1271,6 +1271,16 @@ public: } } + void visit (HIR::RangeFromToExpr &expr) override; + + void visit (HIR::RangeFromExpr &expr) override; + + void visit (HIR::RangeToExpr &expr) override; + + void visit (HIR::RangeFullExpr &expr) override; + + void visit (HIR::RangeFromToInclExpr &expr) override; + protected: bool resolve_operator_overload (Analysis::RustLangItem::ItemType lang_item_type, |