From 66a9a3a95bae4c7ea02495f938b674f6e037f951 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 4 Oct 2025 21:53:40 +0100 Subject: [PATCH] gccrs: Refactor TyTy::ConstType into separate types This patch refactors the const generic type system to follow the same pattern as regular type parameters. The monolithic ConstType is split into four distinct types: ConstParamType (generic parameter placeholder) ConstValueType (resolved constant value) ConstInferType (inference variable) ConstErrorType (error sentinel) gcc/rust/ChangeLog: * backend/rust-compile-expr.cc (CompileExpr::array_copied_expr): refactor to new classes * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit): likewise (CompilePatternBindings::visit): likewise * backend/rust-compile-type.cc (TyTyResolveCompile::visit): likewise * backend/rust-compile-type.h: likewise * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): likewise * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): likewise * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): likewise * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): likewise * typecheck/rust-substitution-mapper.cc (SubstMapperInternal::visit): likewise * typecheck/rust-substitution-mapper.h: likewise * typecheck/rust-type-util.cc (unify_site_and): remove bad delete (alpine32) * typecheck/rust-tyty-call.h: refactor to new classes * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::clone): likewise (SubstitutionRef::infer_substitions): likewise * typecheck/rust-tyty-util.cc (TyVar::get_implicit_const_infer_var): likewise * typecheck/rust-tyty-util.h: likewise * typecheck/rust-tyty-variance-analysis-private.h: likewise * typecheck/rust-tyty-visitor.h: likewise * typecheck/rust-tyty.cc (BaseType::destructure): likewise (BaseType::monomorphized_clone): likewise (BaseType::is_concrete): likewise (VariantDef::clone): likewise (VariantDef::monomorphized_clone): likewise (ArrayType::as_string): likewise (ArrayType::get_capacity): likewise (ArrayType::handle_substitions): likewise (generate_tree_str): likewise (ConstType::ConstType): likewise (ConstParamType::ConstParamType): likewise (ConstType::accept_vis): likewise (ConstParamType::const_kind): likewise (ConstParamType::get_symbol): likewise (ConstParamType::can_resolve): likewise (ConstParamType::resolve): likewise (ConstParamType::accept_vis): likewise (ConstType::set_value): likewise (ConstType::as_string): likewise (ConstParamType::as_string): likewise (ConstType::clone): likewise (ConstParamType::clone): likewise (ConstType::get_symbol): likewise (ConstParamType::get_name): likewise (ConstType::can_resolve): likewise (ConstParamType::is_equal): likewise (ConstType::resolve): likewise (ConstValueType::ConstValueType): likewise (ConstValueType::const_kind): likewise (ConstValueType::accept_vis): likewise (ConstValueType::as_string): likewise (ConstValueType::clone): likewise (ConstValueType::get_name): likewise (ConstValueType::is_equal): likewise (ConstValueType::get_value): likewise (ConstInferType::ConstInferType): likewise (ConstInferType::const_kind): likewise (ConstInferType::accept_vis): likewise (ConstType::get_name): likewise (ConstInferType::as_string): likewise (ConstInferType::clone): likewise (ConstInferType::get_name): likewise (ConstType::is_equal): likewise (ConstInferType::is_equal): likewise (ConstErrorType::ConstErrorType): likewise (ConstErrorType::const_kind): likewise (ConstType::handle_substitions): likewise (ConstErrorType::accept_vis): likewise (ConstErrorType::as_string): likewise (ConstErrorType::clone): likewise (ConstErrorType::get_name): likewise (ConstErrorType::is_equal): likewise * typecheck/rust-tyty.h (class BaseConstType): likewise (class ConstType): likewise (class ConstParamType): likewise (class ConstValueType): likewise (class ConstInferType): likewise (class ConstErrorType): likewise * typecheck/rust-unify.cc (UnifyRules::commit): likewise (UnifyRules::go): likewise (UnifyRules::expect_array): likewise (UnifyRules::expect_const): likewise * typecheck/rust-unify.h: likewise Signed-off-by: Philip Herron --- gcc/rust/backend/rust-compile-expr.cc | 28 +- gcc/rust/backend/rust-compile-pattern.cc | 27 +- gcc/rust/backend/rust-compile-type.cc | 40 +- gcc/rust/backend/rust-compile-type.h | 5 +- .../typecheck/rust-hir-type-check-base.cc | 45 +- .../typecheck/rust-hir-type-check-expr.cc | 35 +- .../typecheck/rust-hir-type-check-pattern.cc | 29 +- .../typecheck/rust-hir-type-check-type.cc | 26 +- .../typecheck/rust-substitution-mapper.cc | 20 +- gcc/rust/typecheck/rust-substitution-mapper.h | 22 +- gcc/rust/typecheck/rust-type-util.cc | 3 +- gcc/rust/typecheck/rust-tyty-call.h | 9 +- gcc/rust/typecheck/rust-tyty-subst.cc | 51 +- gcc/rust/typecheck/rust-tyty-util.cc | 9 +- gcc/rust/typecheck/rust-tyty-util.h | 3 +- .../rust-tyty-variance-analysis-private.h | 5 +- gcc/rust/typecheck/rust-tyty-visitor.h | 10 +- gcc/rust/typecheck/rust-tyty.cc | 451 ++++++++++++++---- gcc/rust/typecheck/rust-tyty.h | 163 ++++++- gcc/rust/typecheck/rust-unify.cc | 260 ++++++---- gcc/rust/typecheck/rust-unify.h | 3 +- 21 files changed, 920 insertions(+), 324 deletions(-) diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index d09ac727529..0a627f35352 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -2010,11 +2010,25 @@ CompileExpr::array_copied_expr (location_t expr_locus, return error_mark_node; } - auto capacity_tyty = array_tyty.get_capacity (); - tree capacity_expr = capacity_tyty->get_value (); - if (!TREE_CONSTANT (capacity_expr)) + auto capacity_ty = array_tyty.get_capacity (); + + // Check if capacity is a const type + if (capacity_ty->get_kind () != TyTy::TypeKind::CONST) + { + rust_error_at (array_tyty.get_locus (), + "array capacity is not a const type"); + return error_mark_node; + } + + auto *capacity_const = capacity_ty->as_const_type (); + + rust_assert (capacity_const->const_kind () + == TyTy::BaseConstType::ConstKind::Value); + auto &capacity_value = *static_cast (capacity_const); + auto cap_tree = capacity_value.get_value (); + if (error_operand_p (cap_tree) || !TREE_CONSTANT (cap_tree)) { - rust_error_at (expr_locus, "non const num copies %qT", capacity_expr); + rust_error_at (expr_locus, "non const num copies %qT", cap_tree); return error_mark_node; } @@ -2067,9 +2081,9 @@ CompileExpr::array_copied_expr (location_t expr_locus, ctx->push_block (init_block); tree tmp; - tree stmts = Backend::array_initializer (fndecl, init_block, array_type, - capacity_expr, translated_expr, - &tmp, expr_locus); + tree stmts + = Backend::array_initializer (fndecl, init_block, array_type, cap_tree, + translated_expr, &tmp, expr_locus); ctx->add_statement (stmts); tree block = ctx->pop_block (); diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index 9459fd618f3..82333dc39c0 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -27,6 +27,7 @@ #include "rust-hir-pattern.h" #include "rust-system.h" #include "rust-tyty.h" +#include "tree.h" namespace Rust { namespace Compile { @@ -676,7 +677,18 @@ CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern) // for array type scrutinee, we can simply get the capacity as a // const and calculate how many elements to skip auto array_ty = static_cast (lookup); - auto cap_tree = array_ty->get_capacity ()->get_value (); + auto capacity_ty = array_ty->get_capacity (); + + rust_assert (capacity_ty->get_kind () == TyTy::TypeKind::CONST); + auto *capacity_const = capacity_ty->as_const_type (); + rust_assert (capacity_const->const_kind () + == TyTy::BaseConstType::ConstKind::Value); + auto &capacity_value + = *static_cast (capacity_const); + auto cap_tree = capacity_value.get_value (); + + rust_assert (!error_operand_p (cap_tree)); + size_t cap_wi = (size_t) wi::to_wide (cap_tree).to_uhwi (); element_index = cap_wi - items.get_upper_patterns ().size (); for (auto &pattern_member : items.get_upper_patterns ()) @@ -1164,7 +1176,18 @@ CompilePatternBindings::visit (HIR::SlicePattern &pattern) case TyTy::TypeKind::ARRAY: { auto array_ty = static_cast (lookup); - auto cap_tree = array_ty->get_capacity ()->get_value (); + auto capacity_ty = array_ty->get_capacity (); + + rust_assert (capacity_ty->get_kind () == TyTy::TypeKind::CONST); + auto *capacity_const = capacity_ty->as_const_type (); + rust_assert (capacity_const->const_kind () + == TyTy::BaseConstType::ConstKind::Value); + auto &capacity_value + = *static_cast (capacity_const); + auto cap_tree = capacity_value.get_value (); + + rust_assert (!error_operand_p (cap_tree)); + size_t cap_wi = (size_t) wi::to_wide (cap_tree).to_uhwi (); element_index = cap_wi - items.get_upper_patterns ().size (); for (auto &pattern_member : items.get_upper_patterns ()) diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc index d58b53c5c92..5b00afae4e5 100644 --- a/gcc/rust/backend/rust-compile-type.cc +++ b/gcc/rust/backend/rust-compile-type.cc @@ -136,13 +136,31 @@ TyTyResolveCompile::visit (const TyTy::InferType &type) } void -TyTyResolveCompile::visit (const TyTy::ParamType &) +TyTyResolveCompile::visit (const TyTy::ParamType &type) { translated = error_mark_node; } void -TyTyResolveCompile::visit (const TyTy::ConstType &) +TyTyResolveCompile::visit (const TyTy::ConstParamType &type) +{ + translated = error_mark_node; +} + +void +TyTyResolveCompile::visit (const TyTy::ConstValueType &type) +{ + translated = error_mark_node; +} + +void +TyTyResolveCompile::visit (const TyTy::ConstInferType &type) +{ + translated = error_mark_node; +} + +void +TyTyResolveCompile::visit (const TyTy::ConstErrorType &type) { translated = error_mark_node; } @@ -470,8 +488,22 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type) { tree element_type = TyTyResolveCompile::compile (ctx, type.get_element_type ()); - TyTy::ConstType *const_capacity = type.get_capacity (); - tree folded_capacity_expr = const_capacity->get_value (); + auto const_capacity = type.get_capacity (); + + // Check if capacity is a const type + if (const_capacity->get_kind () != TyTy::TypeKind::CONST) + { + rust_error_at (type.get_locus (), "array capacity is not a const type"); + translated = error_mark_node; + return; + } + + auto *capacity_const = const_capacity->as_const_type (); + + rust_assert (capacity_const->const_kind () + == TyTy::BaseConstType::ConstKind::Value); + auto &capacity_value = *static_cast (capacity_const); + auto folded_capacity_expr = capacity_value.get_value (); // build_index_type takes the maximum index, which is one less than // the length. diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h index 06753437765..d6c32595e26 100644 --- a/gcc/rust/backend/rust-compile-type.h +++ b/gcc/rust/backend/rust-compile-type.h @@ -50,7 +50,10 @@ public: void visit (const TyTy::ReferenceType &) override; void visit (const TyTy::PointerType &) override; void visit (const TyTy::ParamType &) override; - void visit (const TyTy::ConstType &) override; + void visit (const TyTy::ConstParamType &) override; + void visit (const TyTy::ConstValueType &) override; + void visit (const TyTy::ConstInferType &) override; + void visit (const TyTy::ConstErrorType &) override; void visit (const TyTy::StrType &) override; void visit (const TyTy::NeverType &) override; void visit (const TyTy::PlaceholderType &) override; diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc index ebe7fad713c..cdbaa69cd77 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -367,17 +367,17 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, tree capacity = Compile::HIRCompileBase::query_compile_const_expr ( ctx, expected_ty, *literal_capacity); - TyTy::ConstType *capacity_expr - = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "", - expected_ty, capacity, {}, - literal_capacity->get_locus (), - literal_capacity->get_mappings ().get_hirid (), - literal_capacity->get_mappings ().get_hirid (), - {}); - - TyTy::ArrayType *array - = new TyTy::ArrayType (array_mapping.get_hirid (), locus, - capacity_expr, TyTy::TyVar (u8->get_ref ())); + HirId capacity_expr_id = literal_capacity->get_mappings ().get_hirid (); + auto capacity_expr + = new TyTy::ConstValueType (capacity, expected_ty, capacity_expr_id, + capacity_expr_id); + context->insert_type (literal_capacity->get_mappings (), + capacity_expr->as_base_type ()); + + TyTy::ArrayType *array = new TyTy::ArrayType ( + array_mapping.get_hirid (), locus, + TyTy::TyVar (capacity_expr->as_base_type ()->get_ty_ref ()), + TyTy::TyVar (u8->get_ref ())); context->insert_type (array_mapping, array); infered = new TyTy::ReferenceType (expr_mappings.get_hirid (), @@ -597,22 +597,21 @@ TypeCheckBase::resolve_generic_params ( = Compile::HIRCompileBase::query_compile_const_expr ( ctx, specified_type, expr); - TyTy::ConstType *default_const_decl - = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, - param.get_name (), specified_type, - default_value, {}, param.get_locus (), - expr.get_mappings ().get_hirid (), - expr.get_mappings ().get_hirid (), {}); + auto default_const_decl + = new TyTy::ConstValueType (default_value, specified_type, + expr.get_mappings ().get_hirid (), + expr.get_mappings ().get_hirid (), + {}); context->insert_type (expr.get_mappings (), default_const_decl); } - TyTy::ConstType *const_decl - = new TyTy::ConstType (TyTy::ConstType::ConstKind::Decl, - param.get_name (), specified_type, - error_mark_node, {}, param.get_locus (), - param.get_mappings ().get_hirid (), - param.get_mappings ().get_hirid (), {}); + TyTy::BaseGeneric *const_decl + = new TyTy::ConstParamType (param.get_name (), param.get_locus (), + specified_type, + param.get_mappings ().get_hirid (), + param.get_mappings ().get_hirid (), + {}); context->insert_type (generic_param->get_mappings (), const_decl); TyTy::SubstitutionParamMapping p (*generic_param, const_decl); diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index c7f8192bada..71dcaa316ab 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -34,6 +34,7 @@ #include "rust-immutable-name-resolution-context.h" #include "rust-compile-base.h" #include "rust-tyty-util.h" +#include "rust-tyty.h" #include "tree.h" namespace Rust { @@ -668,16 +669,9 @@ TypeCheckExpr::visit (HIR::AnonConst &expr) return; } - auto locus = expr.get_locus (); - auto infer_ty_var = TyTy::TyVar::get_implicit_infer_var (locus); - - HirId next = mappings.get_next_hir_id (); - infered = new TyTy::ConstType (TyTy::ConstType::ConstKind::Infer, "", - infer_ty_var.get_tyty (), error_mark_node, {}, - locus, next, next, {}); - - context->insert_implicit_type (infered->get_ref (), infered); - mappings.insert_location (infered->get_ref (), locus); + TyTy::TyVar var + = TyTy::TyVar::get_implicit_const_infer_var (expr.get_locus ()); + infered = var.get_tyty (); } void @@ -1155,14 +1149,23 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr) tree capacity_value = Compile::HIRCompileBase::query_compile_const_expr (ctx, capacity_type, *capacity_expr); - HirId size_id = capacity_expr->get_mappings ().get_hirid (); - TyTy::ConstType *const_type - = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "", expected_ty, - capacity_value, {}, capacity_expr->get_locus (), - size_id, size_id); + + // Create ConstValueType with ref == ty_ref (both pointing to capacity_expr) + // ty_ref gets updated during substitution via set_ty_ref() + HirId capacity_expr_id = capacity_expr->get_mappings ().get_hirid (); + auto const_type + = new TyTy::ConstValueType (capacity_value, expected_ty, capacity_expr_id, + capacity_expr_id); + + // Insert the ConstValueType at its ref + context->insert_type (capacity_expr->get_mappings (), + const_type->as_base_type ()); + infered = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), expr.get_locus (), - const_type, TyTy::TyVar (element_type->get_ref ())); + TyTy::TyVar ( + const_type->as_base_type ()->get_ty_ref ()), + TyTy::TyVar (element_type->get_ref ())); } // empty struct diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc index 4d9d60ca5bd..e8467f0c7b8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc @@ -21,6 +21,8 @@ #include "rust-hir-type-check-expr.h" #include "rust-type-util.h" #include "rust-immutable-name-resolution-context.h" +#include "rust-tyty.h" +#include "tree.h" namespace Rust { namespace Resolver { @@ -778,7 +780,32 @@ TypeCheckPattern::visit (HIR::SlicePattern &pattern) auto &array_ty_ty = static_cast (*parent); parent_element_ty = array_ty_ty.get_element_type (); auto capacity = array_ty_ty.get_capacity (); - tree cap = capacity->get_value (); + + tree cap = error_mark_node; + if (capacity->get_kind () != TyTy::TypeKind::CONST) + { + // Error case - capacity is not a const type + break; + } + + auto *capacity_const = capacity->as_const_type (); + switch (capacity_const->const_kind ()) + { + case TyTy::BaseConstType::ConstKind::Value: + { + const auto &const_value + = *static_cast (capacity); + cap = const_value.get_value (); + } + break; + + case TyTy::BaseConstType::ConstKind::Decl: + case TyTy::BaseConstType::ConstKind::Infer: + case TyTy::BaseConstType::ConstKind::Error: + cap = error_mark_node; + break; + } + if (error_operand_p (cap)) { rust_error_at (parent->get_locus (), diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 833ad92db59..799efc809d5 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -706,14 +706,14 @@ TypeCheckType::visit (HIR::ArrayType &type) rust_assert (ok); context->insert_type (type.get_size_expr ().get_mappings (), expected_ty); - TyTy::ConstType *const_type = nullptr; + TyTy::BaseConstType *const_type = nullptr; if (capacity_type->get_kind () == TyTy::TypeKind::CONST) { - const_type = static_cast (capacity_type); + const_type = capacity_type->as_const_type (); unify_site (type.get_size_expr ().get_mappings ().get_hirid (), TyTy::TyWithLocation (expected_ty), - TyTy::TyWithLocation (const_type->get_ty (), + TyTy::TyWithLocation (const_type->get_specified_type (), type.get_size_expr ().get_locus ()), type.get_size_expr ().get_locus ()); } @@ -727,13 +727,7 @@ TypeCheckType::visit (HIR::ArrayType &type) type.get_size_expr ().get_locus ()); if (result->is ()) - { - const_type - = new TyTy::ConstType (TyTy::ConstType::ConstKind::Error, "", - expected_ty, error_mark_node, {}, - type.get_size_expr ().get_locus (), size_id, - size_id); - } + const_type = new TyTy::ConstErrorType (expected_ty, size_id, size_id); else { auto ctx = Compile::Context::get (); @@ -741,16 +735,18 @@ TypeCheckType::visit (HIR::ArrayType &type) = Compile::HIRCompileBase::query_compile_const_expr ( ctx, capacity_type, type.get_size_expr ()); - const_type = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, - "", expected_ty, capacity_expr, {}, - type.get_size_expr ().get_locus (), - size_id, size_id); + const_type = new TyTy::ConstValueType (capacity_expr, expected_ty, + size_id, size_id); + context->insert_type (type.get_size_expr ().get_mappings (), + const_type->as_base_type ()); } } translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (), type.get_locus (), - const_type, TyTy::TyVar (element_type->get_ref ())); + TyTy::TyVar ( + const_type->as_base_type ()->get_ty_ref ()), + TyTy::TyVar (element_type->get_ref ())); } void diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc index 958651e5593..238ede45b05 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.cc +++ b/gcc/rust/typecheck/rust-substitution-mapper.cc @@ -268,11 +268,29 @@ SubstMapperInternal::visit (TyTy::ParamType &type) } void -SubstMapperInternal::visit (TyTy::ConstType &type) +SubstMapperInternal::visit (TyTy::ConstParamType &type) { resolved = type.handle_substitions (mappings); } +void +SubstMapperInternal::visit (TyTy::ConstValueType &type) +{ + resolved = type.clone (); +} + +void +SubstMapperInternal::visit (TyTy::ConstInferType &type) +{ + resolved = type.clone (); +} + +void +SubstMapperInternal::visit (TyTy::ConstErrorType &type) +{ + resolved = type.clone (); +} + void SubstMapperInternal::visit (TyTy::PlaceholderType &type) { diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h index 2389d83e392..98f9e7268b7 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.h +++ b/gcc/rust/typecheck/rust-substitution-mapper.h @@ -61,7 +61,10 @@ public: void visit (TyTy::ReferenceType &) override { rust_unreachable (); } void visit (TyTy::PointerType &) override { rust_unreachable (); } void visit (TyTy::ParamType &) override { rust_unreachable (); } - void visit (TyTy::ConstType &) override { rust_unreachable (); } + void visit (TyTy::ConstParamType &) override { rust_unreachable (); } + void visit (TyTy::ConstValueType &) override { rust_unreachable (); } + void visit (TyTy::ConstInferType &) override { rust_unreachable (); } + void visit (TyTy::ConstErrorType &) override { rust_unreachable (); } void visit (TyTy::StrType &) override { rust_unreachable (); } void visit (TyTy::NeverType &) override { rust_unreachable (); } void visit (TyTy::DynamicObjectType &) override { rust_unreachable (); } @@ -93,7 +96,10 @@ public: void visit (TyTy::ReferenceType &type) override; void visit (TyTy::PointerType &type) override; void visit (TyTy::ParamType &type) override; - void visit (TyTy::ConstType &type) override; + void visit (TyTy::ConstParamType &type) override; + void visit (TyTy::ConstValueType &type) override; + void visit (TyTy::ConstInferType &type) override; + void visit (TyTy::ConstErrorType &type) override; void visit (TyTy::PlaceholderType &type) override; void visit (TyTy::ProjectionType &type) override; void visit (TyTy::ClosureType &type) override; @@ -147,13 +153,16 @@ public: void visit (TyTy::ReferenceType &) override { rust_unreachable (); } void visit (TyTy::PointerType &) override { rust_unreachable (); } void visit (TyTy::ParamType &) override { rust_unreachable (); } - void visit (TyTy::ConstType &) override { rust_unreachable (); } + void visit (TyTy::ConstParamType &) override { rust_unreachable (); } + void visit (TyTy::ConstValueType &) override { rust_unreachable (); } + void visit (TyTy::ConstInferType &) override { rust_unreachable (); } + void visit (TyTy::ConstErrorType &) override { rust_unreachable (); } void visit (TyTy::StrType &) override { rust_unreachable (); } void visit (TyTy::NeverType &) override { rust_unreachable (); } void visit (TyTy::PlaceholderType &) override { rust_unreachable (); } void visit (TyTy::ProjectionType &) override { rust_unreachable (); } void visit (TyTy::DynamicObjectType &) override { rust_unreachable (); } - void visit (TyTy::OpaqueType &type) override { rust_unreachable (); } + void visit (TyTy::OpaqueType &) override { rust_unreachable (); } private: SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver); @@ -188,7 +197,10 @@ public: void visit (const TyTy::ReferenceType &) override {} void visit (const TyTy::PointerType &) override {} void visit (const TyTy::ParamType &) override {} - void visit (const TyTy::ConstType &) override {} + void visit (const TyTy::ConstParamType &) override {} + void visit (const TyTy::ConstValueType &) override {} + void visit (const TyTy::ConstInferType &) override {} + void visit (const TyTy::ConstErrorType &) override {} void visit (const TyTy::StrType &) override {} void visit (const TyTy::NeverType &) override {} void visit (const TyTy::PlaceholderType &) override {} diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc index 34e99d34bb3..6f30ebf49e9 100644 --- a/gcc/rust/typecheck/rust-type-util.cc +++ b/gcc/rust/typecheck/rust-type-util.cc @@ -231,7 +231,8 @@ unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, // remove the inference variable context.clear_type (i.infer); - delete i.infer; + // FIXME: Don't delete - result might point to this + // delete i.infer; } } return result; diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h index 9e4aab56ea1..025a1ad4561 100644 --- a/gcc/rust/typecheck/rust-tyty-call.h +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -60,9 +60,12 @@ public: void visit (PlaceholderType &) override { rust_unreachable (); } void visit (ProjectionType &) override { rust_unreachable (); } void visit (DynamicObjectType &) override { rust_unreachable (); } - void visit (ClosureType &type) override { rust_unreachable (); } - void visit (OpaqueType &type) override { rust_unreachable (); } - void visit (ConstType &type) override { rust_unreachable (); } + void visit (ClosureType &) override { rust_unreachable (); } + void visit (OpaqueType &) override { rust_unreachable (); } + void visit (ConstParamType &) override { rust_unreachable (); } + void visit (ConstValueType &) override { rust_unreachable (); } + void visit (ConstInferType &) override { rust_unreachable (); } + void visit (ConstErrorType &) override { rust_unreachable (); } // tuple-structs void visit (ADTType &type) override; diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc index 4699b71197a..e82e8a3b0bc 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.cc +++ b/gcc/rust/typecheck/rust-tyty-subst.cc @@ -54,8 +54,8 @@ SubstitutionParamMapping::as_string () const SubstitutionParamMapping SubstitutionParamMapping::clone () const { - return SubstitutionParamMapping (generic, - static_cast (param->clone ())); + return SubstitutionParamMapping (generic, static_cast ( + param->clone ())); } BaseGeneric * @@ -167,7 +167,12 @@ SubstitutionParamMapping::fill_param_ty ( } else if (type.get_kind () == TyTy::TypeKind::CONST) { - param = static_cast (type.clone ()); + rust_assert (param->get_kind () == TyTy::TypeKind::CONST); + auto *const_type = type.as_const_type (); + if (const_type->const_kind () == TyTy::BaseConstType::ConstKind::Decl) + param = static_cast (type.clone ()); + else + param->set_ty_ref (type.get_ref ()); } else if (param->get_kind () == TypeKind::PARAM) { @@ -768,7 +773,7 @@ SubstitutionRef::get_mappings_from_generic_args ( } else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST) { - if (!resolved->is ()) + if (resolved->get_kind () != TyTy::TypeKind::CONST) { rich_location r (line_table, arg->get_locus ()); r.add_fixit_remove (arg->get_locus ()); @@ -802,18 +807,17 @@ SubstitutionRef::get_mappings_from_generic_args ( // get the const generic specified type const auto base_generic = param_mapping.get_param_ty (); - rust_assert (base_generic->is ()); + rust_assert (base_generic->get_kind () == TyTy::TypeKind::CONST); const auto const_param - = static_cast (base_generic); - auto specified_type = const_param->get_ty (); + = static_cast (base_generic); + auto specified_type = const_param->get_specified_type (); // validate this const generic is of the correct type TyTy::BaseType *coereced_type = nullptr; - if (expr_type->is ()) + if (expr_type->get_kind () == TyTy::TypeKind::CONST) { - TyTy::ConstType *const_expr_type - = static_cast (expr_type); - TyTy::BaseType *const_value_type = const_expr_type->get_ty (); + auto const_expr_type = expr_type->as_const_type (); + auto const_value_type = const_expr_type->get_specified_type (); coereced_type = Resolver::coercion_site (expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (specified_type), @@ -835,7 +839,7 @@ SubstitutionRef::get_mappings_from_generic_args ( return SubstitutionArgumentMappings::error (); TyTy::BaseType *const_value_ty = nullptr; - if (expr_type->is ()) + if (expr_type->get_kind () == TyTy::TypeKind::CONST) const_value_ty = expr_type; else { @@ -854,11 +858,18 @@ SubstitutionRef::get_mappings_from_generic_args ( return SubstitutionArgumentMappings::error (); } + // Use a fresh HirId to avoid conflicts with the expr's type + auto &global_mappings = Analysis::Mappings::get (); + HirId const_value_id = global_mappings.get_next_hir_id (); const_value_ty - = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "", - coereced_type, folded, {}, expr.get_locus (), - expr.get_mappings ().get_hirid (), - expr.get_mappings ().get_hirid (), {}); + = new TyTy::ConstValueType (folded, coereced_type, const_value_id, + const_value_id, {}); + + // Insert the ConstValueType into the context so it can be looked up + auto context = Resolver::TypeCheckContext::get (); + context->insert_type ( + Analysis::NodeMapping (0, 0, const_value_ty->get_ref (), 0), + const_value_ty); } mappings.emplace_back (¶m_mapping, const_value_ty); @@ -928,13 +939,7 @@ SubstitutionRef::infer_substitions (location_t locus) } else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST) { - const auto const_param = p.get_param_ty (); - rust_assert (const_param->is ()); - const auto &const_type - = *static_cast (const_param); - - TyVar infer_var - = TyVar::get_implicit_const_infer_var (const_type, locus); + TyVar infer_var = TyVar::get_implicit_const_infer_var (locus); args.emplace_back (&p, infer_var.get_tyty ()); argument_mappings[symbol] = infer_var.get_tyty (); } diff --git a/gcc/rust/typecheck/rust-tyty-util.cc b/gcc/rust/typecheck/rust-tyty-util.cc index 4bc17231bf1..c6c740b2cba 100644 --- a/gcc/rust/typecheck/rust-tyty-util.cc +++ b/gcc/rust/typecheck/rust-tyty-util.cc @@ -60,17 +60,14 @@ TyVar::get_implicit_infer_var (location_t locus) } TyVar -TyVar::get_implicit_const_infer_var (const ConstType &const_type, - location_t locus) +TyVar::get_implicit_const_infer_var (location_t locus) { auto &mappings = Analysis::Mappings::get (); auto context = Resolver::TypeCheckContext::get (); + TyVar ty_infer = get_implicit_infer_var (locus); HirId next = mappings.get_next_hir_id (); - auto infer - = new ConstType (ConstType::ConstKind::Infer, const_type.get_symbol (), - const_type.get_ty (), error_mark_node, - const_type.get_specified_bounds (), locus, next, next, {}); + auto infer = new ConstInferType (ty_infer.get_tyty (), next, next, {}); context->insert_implicit_type (infer->get_ref (), infer); mappings.insert_location (infer->get_ref (), locus); diff --git a/gcc/rust/typecheck/rust-tyty-util.h b/gcc/rust/typecheck/rust-tyty-util.h index 1c8fd723791..26101fd4d93 100644 --- a/gcc/rust/typecheck/rust-tyty-util.h +++ b/gcc/rust/typecheck/rust-tyty-util.h @@ -43,8 +43,7 @@ public: static TyVar get_implicit_infer_var (location_t locus); - static TyVar get_implicit_const_infer_var (const TyTy::ConstType &const_type, - location_t locus); + static TyVar get_implicit_const_infer_var (location_t locus); static TyVar subst_covariant_var (TyTy::BaseType *orig, TyTy::BaseType *subst); diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h b/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h index f1833c5874c..b7ca5e1a01d 100644 --- a/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h +++ b/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h @@ -175,7 +175,10 @@ public: void visit (OpaqueType &type) override {} - void visit (ConstType &type) override {} + void visit (TyTy::ConstParamType &) override {} + void visit (TyTy::ConstValueType &) override {} + void visit (TyTy::ConstInferType &) override {} + void visit (TyTy::ConstErrorType &) override {} }; /** Per crate context for generic type variance analysis. */ diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h index 778307591d1..f7f3665ef59 100644 --- a/gcc/rust/typecheck/rust-tyty-visitor.h +++ b/gcc/rust/typecheck/rust-tyty-visitor.h @@ -45,7 +45,10 @@ public: virtual void visit (ReferenceType &type) = 0; virtual void visit (PointerType &type) = 0; virtual void visit (ParamType &type) = 0; - virtual void visit (ConstType &type) = 0; + virtual void visit (ConstParamType &type) = 0; + virtual void visit (ConstValueType &type) = 0; + virtual void visit (ConstInferType &type) = 0; + virtual void visit (ConstErrorType &type) = 0; virtual void visit (StrType &type) = 0; virtual void visit (NeverType &type) = 0; virtual void visit (PlaceholderType &type) = 0; @@ -76,7 +79,10 @@ public: virtual void visit (const ReferenceType &type) = 0; virtual void visit (const PointerType &type) = 0; virtual void visit (const ParamType &type) = 0; - virtual void visit (const ConstType &type) = 0; + virtual void visit (const ConstParamType &type) = 0; + virtual void visit (const ConstValueType &type) = 0; + virtual void visit (const ConstInferType &type) = 0; + virtual void visit (const ConstErrorType &type) = 0; virtual void visit (const StrType &type) = 0; virtual void visit (const NeverType &type) = 0; virtual void visit (const PlaceholderType &type) = 0; diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index ff84cfc9d11..da5c35049fa 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -472,6 +472,23 @@ BaseType::destructure () x = pr; } + else if (x->get_kind () == TypeKind::CONST) + { + auto p = x->as_const_type (); + if (p->const_kind () == BaseConstType::ConstKind::Decl) + { + auto decl = static_cast (p); + auto pr = decl->resolve (); + if (pr == x) + return pr; + + x = pr; + } + else + { + return x; + } + } else if (auto p = x->try_as ()) { if (!p->can_resolve ()) @@ -517,6 +534,23 @@ BaseType::destructure () const x = pr; } + else if (x->get_kind () == TypeKind::CONST) + { + auto p = x->as_const_type (); + if (p->const_kind () == BaseConstType::ConstKind::Decl) + { + auto decl = static_cast (p); + auto pr = decl->resolve (); + if (pr == x) + return pr; + + x = pr; + } + else + { + return x; + } + } else if (auto p = x->try_as ()) { if (!p->can_resolve ()) @@ -554,7 +588,7 @@ BaseType::monomorphized_clone () const { TyVar elm = arr->get_var_element_type ().monomorphized_clone (); return new ArrayType (arr->get_ref (), arr->get_ty_ref (), ident.locus, - arr->get_capacity (), elm, + arr->get_capacity_var (), elm, arr->get_combined_refs ()); } else if (auto slice = x->try_as ()) @@ -751,7 +785,8 @@ BaseType::is_concrete () const { const TyTy::BaseType *x = destructure (); - if (x->is () || x->is ()) + if (x->is () || x->is () + || x->is ()) { return false; } @@ -833,10 +868,6 @@ BaseType::is_concrete () const return false; return closure->get_result_type ().is_concrete (); } - else if (auto const_type = x->try_as ()) - { - return const_type->get_value () != error_mark_node; - } else if (x->is () || x->is () || x->is () || x->is () || x->is () || x->is () || x->is () || x->is () || x->is () @@ -2464,8 +2495,10 @@ ArrayType::accept_vis (TyConstVisitor &vis) const std::string ArrayType::as_string () const { - return "[" + get_element_type ()->as_string () + "; " + capacity->as_string () - + "]"; + auto cap = get_capacity (); + std::string capacity_str = cap->as_string (); + + return "[" + get_element_type ()->as_string () + "; " + capacity_str + "]"; } bool @@ -2494,6 +2527,12 @@ ArrayType::get_var_element_type () const return element_type; } +BaseType * +ArrayType::get_capacity () const +{ + return capacity.get_tyty (); +} + BaseType * ArrayType::clone () const { @@ -2519,7 +2558,7 @@ ArrayType::handle_substitions (SubstitutionArgumentMappings &mappings) BaseType *concrete_cap = Resolver::SubstMapperInternal::Resolve (cap, mappings); rust_assert (concrete_cap->get_kind () == TyTy::TypeKind::CONST); - ref->capacity = static_cast (concrete_cap); + ref->capacity = TyVar::subst_covariant_var (cap, concrete_cap); return ref; } @@ -3469,148 +3508,382 @@ ParamType::is_implicit_self_trait () const return is_trait_self; } -// ConstType +static std::string +generate_tree_str (tree value) +{ + char *buf = nullptr; + size_t size = 0; -ConstType::ConstType (ConstKind kind, std::string symbol, TyTy::BaseType *ty, - tree value, - std::vector specified_bounds, - location_t locus, HirId ref, HirId ty_ref, - std::set refs) - : BaseGeneric (ref, ty_ref, KIND, - {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, - symbol.empty () ? "" - : symbol), + FILE *stream = open_memstream (&buf, &size); + if (!stream) + return ""; + + print_generic_stmt (stream, value, TDF_NONE); + fclose (stream); + + std::string result = (buf ? std::string (buf, size) : ""); + free (buf); + + if (!result.empty () && result.back () == '\n') + result.pop_back (); + + return result; +} + +// --- + +ConstParamType::ConstParamType (std::string symbol, location_t locus, + BaseType *type, HirId ref, HirId ty_ref, + std::set refs) + : BaseConstType (type), + BaseGeneric (ref, ty_ref, KIND, + {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol), locus}, - specified_bounds, refs), - const_kind (kind), ty (ty), value (value), symbol (symbol) + {}, refs), + symbol (symbol) {} -void -ConstType::accept_vis (TyVisitor &vis) +BaseConstType::ConstKind +ConstParamType::const_kind () const { - vis.visit (*this); + return BaseConstType::ConstKind::Decl; +} + +std::string +ConstParamType::get_symbol () const +{ + return symbol; +} + +bool +ConstParamType::can_resolve () const +{ + return get_ref () != get_ty_ref (); +} + +BaseType * +ConstParamType::resolve () const +{ + TyVar var (get_ty_ref ()); + BaseType *r = var.get_tyty (); + + while (r->get_kind () == TypeKind::CONST) + { + TyVar v (r->get_ty_ref ()); + BaseType *n = v.get_tyty (); + + // fix infinite loop + if (r == n) + break; + + r = n; + } + + if (r->get_kind () == TypeKind::CONST && (r->get_ref () == r->get_ty_ref ())) + { + auto *const_type = r->as_const_type (); + if (const_type->const_kind () != BaseConstType::ConstKind::Value) + return TyVar (r->get_ty_ref ()).get_tyty (); + } + + return r; } void -ConstType::accept_vis (TyConstVisitor &vis) const +ConstParamType::accept_vis (TyVisitor &vis) { vis.visit (*this); } void -ConstType::set_value (tree v) +ConstParamType::accept_vis (TyConstVisitor &vis) const { - value = v; - const_kind = ConstType::ConstKind::Value; + vis.visit (*this); } std::string -ConstType::as_string () const +ConstParamType::as_string () const { - return get_name (); + if (!can_resolve ()) + { + return get_symbol () + " CONST_REF: " + std::to_string (get_ref ()); + } + + BaseType *lookup = resolve (); + // Avoid infinite recursion if resolve() returns this same type + if (lookup == this->as_base_type ()) + { + return get_symbol () + " CONST_REF: " + std::to_string (get_ref ()); + } + + return get_symbol () + "=" + lookup->as_string (); } BaseType * -ConstType::clone () const +ConstParamType::clone () const { - return new ConstType (const_kind, symbol, ty, value, get_specified_bounds (), - ident.locus, ref, ty_ref, get_combined_refs ()); + return new ConstParamType (get_symbol (), ident.locus, specified_type, + get_ref (), get_ty_ref (), get_combined_refs ()); } std::string -ConstType::get_symbol () const +ConstParamType::get_name () const { - return symbol; + if (!can_resolve ()) + return get_symbol (); + + BaseType *lookup = resolve (); + // Avoid infinite recursion if resolve() returns this same type + if (lookup == this->as_base_type ()) + return get_symbol (); + + return lookup->get_name (); } bool -ConstType::can_resolve () const +ConstParamType::is_equal (const BaseType &other) const { - return false; + if (get_kind () != other.get_kind ()) + { + if (!can_resolve ()) + return false; + + return resolve ()->is_equal (other); + } + + auto other_const = other.as_const_type (); + if (other_const->const_kind () != BaseConstType::ConstKind::Decl) + return false; + + auto &other2 = static_cast (*other_const); + if (can_resolve () != other2.can_resolve ()) + return false; + + if (can_resolve ()) + return Resolver::types_compatable (TyTy::TyWithLocation (resolve ()), + TyTy::TyWithLocation (other2.resolve ()), + ident.locus, false); + + return get_symbol ().compare (other2.get_symbol ()) == 0; } BaseType * -ConstType::resolve () const +ConstParamType::handle_substitions ( + SubstitutionArgumentMappings &subst_mappings) { - rust_unreachable (); - return nullptr; + SubstitutionArg arg = SubstitutionArg::error (); + bool ok = subst_mappings.get_argument_for_symbol (this, &arg); + if (!ok || arg.is_error ()) + return this; + + ConstParamType *p = static_cast (clone ()); + const BaseType *resolved = arg.get_tyty (); + + // this is the new subst that this needs to pass + p->set_ref (mappings.get_next_hir_id ()); + p->set_ty_ref (resolved->get_ref ()); + + return p; } -static std::string -generate_tree_str (tree value) +// --- ConstValueType + +ConstValueType::ConstValueType (tree value, BaseType *type, HirId ref, + HirId ty_ref, std::set refs) + : BaseType (ref, ty_ref, KIND, + {Resolver::CanonicalPath::create_empty (), UNKNOWN_LOCATION}, + refs), + BaseConstType (type), folded_val (value) +{} + +BaseConstType::ConstKind +ConstValueType::const_kind () const { - char *buf = nullptr; - size_t size = 0; + return BaseConstType::ConstKind::Value; +} - FILE *stream = open_memstream (&buf, &size); - if (!stream) - return ""; +void +ConstValueType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} - print_generic_stmt (stream, value, TDF_NONE); - fclose (stream); +void +ConstValueType::accept_vis (TyConstVisitor &vis) const +{ + vis.visit (*this); +} - std::string result = (buf ? std::string (buf, size) : ""); - free (buf); +std::string +ConstValueType::as_string () const +{ + return generate_tree_str (folded_val); +} - if (!result.empty () && result.back () == '\n') - result.pop_back (); +BaseType * +ConstValueType::clone () const +{ + return new ConstValueType (folded_val, specified_type, get_ref (), + get_ty_ref (), get_combined_refs ()); +} - return result; +std::string +ConstValueType::get_name () const +{ + return as_string (); +} + +bool +ConstValueType::is_equal (const BaseType &other) const +{ + if (get_kind () != other.get_kind ()) + return false; + + auto other_const = other.as_const_type (); + if (other_const->const_kind () != BaseConstType::ConstKind::Value) + return false; + + auto &other2 = static_cast (*other_const); + return folded_val == other2.folded_val; +} + +tree +ConstValueType::get_value () const +{ + return folded_val; +} + +// --- ConstInferType + +ConstInferType::ConstInferType (BaseType *type, HirId ref, HirId ty_ref, + std::set refs) + : BaseType (ref, ty_ref, KIND, + {Resolver::CanonicalPath::create_empty (), UNKNOWN_LOCATION}, + refs), + BaseConstType (type) +{} + +BaseConstType::ConstKind +ConstInferType::const_kind () const +{ + return BaseConstType::ConstKind::Infer; +} + +void +ConstInferType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstInferType::accept_vis (TyConstVisitor &vis) const +{ + vis.visit (*this); } std::string -ConstType::get_name () const +ConstInferType::as_string () const { - if (value == error_mark_node) - { - switch (get_const_kind ()) - { - case Rust::TyTy::ConstType::Decl: - return "ConstType:<" + get_ty ()->get_name () + " " + get_symbol () - + ">"; + return specified_type->get_name () + "-?"; +} - case Rust::TyTy::ConstType::Infer: - return "ConstType:<" + get_ty ()->get_name () + " ?" + ">"; +BaseType * +ConstInferType::clone () const +{ + auto &mappings = Analysis::Mappings::get (); + auto context = Resolver::TypeCheckContext::get (); - default: - return "ConstType:<" + get_ty ()->get_name () + " - " + ">"; - } - } + ConstInferType *clone + = new ConstInferType (specified_type, mappings.get_next_hir_id (), + get_ty_ref (), get_combined_refs ()); - return generate_tree_str (value); + context->insert_type (Analysis::NodeMapping (mappings.get_current_crate (), + UNKNOWN_NODEID, + clone->get_ref (), + UNKNOWN_LOCAL_DEFID), + clone); + mappings.insert_location (clone->get_ref (), + mappings.lookup_location (get_ref ())); + + clone->append_reference (get_ref ()); + + return clone; +} + +std::string +ConstInferType::get_name () const +{ + return as_string (); } bool -ConstType::is_equal (const BaseType &other) const +ConstInferType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) - { - return false; - } + return false; - const ConstType &rhs = static_cast (other); - if (!get_ty ()->is_equal (*rhs.get_ty ())) + auto other_const = other.as_const_type (); + if (other_const->const_kind () != BaseConstType::ConstKind::Infer) return false; - tree lv = get_value (); - tree rv = rhs.get_value (); + return get_ref () == other.get_ref (); +} + +// --- ConstErrorType + +ConstErrorType::ConstErrorType (BaseType *type, HirId ref, HirId ty_ref, + std::set refs) + : BaseType (ref, ty_ref, KIND, + {Resolver::CanonicalPath::create_empty (), UNKNOWN_LOCATION}, + refs), + BaseConstType (type) +{} - return operand_equal_p (lv, rv, 0); +BaseConstType::ConstKind +ConstErrorType::const_kind () const +{ + return BaseConstType::ConstKind::Error; } -ConstType * -ConstType::handle_substitions (SubstitutionArgumentMappings &mappings) +void +ConstErrorType::accept_vis (TyVisitor &vis) { - SubstitutionArg arg = SubstitutionArg::error (); - bool found = mappings.get_argument_for_symbol (this, &arg); - if (found && !arg.is_error ()) - { - TyTy::BaseType *subst = arg.get_tyty (); - rust_assert (subst->is ()); - return static_cast (subst); - } + vis.visit (*this); +} + +void +ConstErrorType::accept_vis (TyConstVisitor &vis) const +{ + vis.visit (*this); +} + +std::string +ConstErrorType::as_string () const +{ + return ""; +} + +BaseType * +ConstErrorType::clone () const +{ + return new ConstErrorType (specified_type, get_ref (), get_ty_ref (), + get_combined_refs ()); +} + +std::string +ConstErrorType::get_name () const +{ + return as_string (); +} + +bool +ConstErrorType::is_equal (const BaseType &other) const +{ + if (get_kind () != other.get_kind ()) + return false; - return this; + auto other_const = other.as_const_type (); + return other_const->const_kind () == BaseConstType::ConstKind::Error; } // OpaqueType diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 480a195b868..3236bf34a59 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -91,6 +91,7 @@ public: class TyVisitor; class TyConstVisitor; +class BaseConstType; class BaseType : public TypeBoundsMappings { public: @@ -226,6 +227,11 @@ public: return static_cast (this); } + // Helper to get BaseConstType interface for CONST types + // Overridden by const types that also inherit from BaseConstType + virtual BaseConstType *as_const_type () { return nullptr; } + virtual const BaseConstType *as_const_type () const { return nullptr; } + protected: BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident, std::set refs = std::set ()); @@ -406,7 +412,7 @@ private: std::string symbol; }; -class ConstType : public BaseGeneric +class BaseConstType { public: static constexpr auto KIND = TypeKind::CONST; @@ -419,23 +425,30 @@ public: Error }; - ConstType (ConstKind kind, std::string symbol, TyTy::BaseType *ty, tree value, - std::vector specified_bounds, location_t locus, - HirId ref, HirId ty_ref, - std::set refs = std::set ()); + virtual ConstKind const_kind () const = 0; - void accept_vis (TyVisitor &vis) override; - void accept_vis (TyConstVisitor &vis) const override; + BaseType *get_specified_type () const { return specified_type; } - ConstKind get_const_kind () const { return const_kind; } - TyTy::BaseType *get_ty () const { return ty; } - tree get_value () const { return value; } + // Helper to get BaseType interface (all const types also inherit BaseType) + // This must be implemented by concrete classes since BaseConstType doesn't + // inherit from BaseType, but all concrete const types do. + virtual BaseType *as_base_type () = 0; + virtual const BaseType *as_base_type () const = 0; - void set_value (tree value); +protected: + BaseConstType (BaseType *type) : specified_type (type) {} - std::string as_string () const override; + BaseType *specified_type; +}; - BaseType *clone () const final override; +class ConstParamType : public BaseConstType, public BaseGeneric +{ +public: + ConstParamType (std::string symbol, location_t locus, BaseType *type, + HirId ref, HirId ty_ref, + std::set refs = std::set ()); + + ConstKind const_kind () const override final; std::string get_symbol () const override final; @@ -443,19 +456,126 @@ public: BaseType *resolve () const override final; + void accept_vis (TyVisitor &vis) override; + void accept_vis (TyConstVisitor &vis) const override; + + std::string as_string () const override; + + BaseType *clone () const final override; std::string get_name () const override final; bool is_equal (const BaseType &other) const override; - ConstType *handle_substitions (SubstitutionArgumentMappings &mappings); + BaseType *handle_substitions (SubstitutionArgumentMappings &mappings); + + BaseType *as_base_type () override { return static_cast (this); } + const BaseType *as_base_type () const override + { + return static_cast (this); + } + + BaseConstType *as_const_type () override { return this; } + const BaseConstType *as_const_type () const override { return this; } private: - ConstKind const_kind; - TyTy::BaseType *ty; - tree value; std::string symbol; }; +class ConstValueType : public BaseType, public BaseConstType +{ +public: + static constexpr auto KIND = TypeKind::CONST; + + ConstValueType (tree value, BaseType *type, HirId ref, HirId ty_ref, + std::set refs = std::set ()); + + ConstKind const_kind () const override final; + + void accept_vis (TyVisitor &vis) override; + void accept_vis (TyConstVisitor &vis) const override; + + std::string as_string () const override; + + BaseType *clone () const final override; + std::string get_name () const override final; + + bool is_equal (const BaseType &other) const override; + + tree get_value () const; + + BaseType *as_base_type () override { return static_cast (this); } + const BaseType *as_base_type () const override + { + return static_cast (this); + } + + BaseConstType *as_const_type () override { return this; } + const BaseConstType *as_const_type () const override { return this; } + +private: + tree folded_val; +}; + +class ConstInferType : public BaseType, public BaseConstType +{ +public: + static constexpr auto KIND = TypeKind::CONST; + + ConstInferType (BaseType *type, HirId ref, HirId ty_ref, + std::set refs = std::set ()); + + ConstKind const_kind () const override final; + + void accept_vis (TyVisitor &vis) override; + void accept_vis (TyConstVisitor &vis) const override; + + std::string as_string () const override; + + BaseType *clone () const final override; + std::string get_name () const override final; + + bool is_equal (const BaseType &other) const override; + + BaseType *as_base_type () override { return static_cast (this); } + const BaseType *as_base_type () const override + { + return static_cast (this); + } + + BaseConstType *as_const_type () override { return this; } + const BaseConstType *as_const_type () const override { return this; } +}; + +class ConstErrorType : public BaseType, public BaseConstType +{ +public: + static constexpr auto KIND = TypeKind::CONST; + + ConstErrorType (BaseType *type, HirId ref, HirId ty_ref, + std::set refs = std::set ()); + + ConstKind const_kind () const override final; + + void accept_vis (TyVisitor &vis) override; + void accept_vis (TyConstVisitor &vis) const override; + + std::string as_string () const override; + + BaseType *clone () const final override; + std::string get_name () const override final; + + bool is_equal (const BaseType &other) const override; + + BaseType *as_base_type () override { return static_cast (this); } + const BaseType *as_base_type () const override + { + return static_cast (this); + } + + BaseConstType *as_const_type () override { return this; } + const BaseConstType *as_const_type () const override { return this; } +}; + class OpaqueType : public BaseType { public: @@ -1201,14 +1321,14 @@ class ArrayType : public BaseType public: static constexpr auto KIND = TypeKind::ARRAY; - ArrayType (HirId ref, location_t locus, ConstType *capacity, TyVar base, + ArrayType (HirId ref, location_t locus, TyVar capacity, TyVar base, std::set refs = std::set ()) : BaseType (ref, ref, TypeKind::ARRAY, {Resolver::CanonicalPath::create_empty (), locus}, refs), element_type (base), capacity (capacity) {} - ArrayType (HirId ref, HirId ty_ref, location_t locus, ConstType *capacity, + ArrayType (HirId ref, HirId ty_ref, location_t locus, TyVar capacity, TyVar base, std::set refs = std::set ()) : BaseType (ref, ty_ref, TypeKind::ARRAY, {Resolver::CanonicalPath::create_empty (), locus}, refs), @@ -1229,13 +1349,14 @@ public: BaseType *clone () const final override; - ConstType *get_capacity () const { return capacity; } + BaseType *get_capacity () const; + const TyVar &get_capacity_var () const { return capacity; } ArrayType *handle_substitions (SubstitutionArgumentMappings &mappings); private: TyVar element_type; - ConstType *capacity; + TyVar capacity; }; class SliceType : public BaseType diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc index be7ac51962b..43dd6dca617 100644 --- a/gcc/rust/typecheck/rust-unify.cc +++ b/gcc/rust/typecheck/rust-unify.cc @@ -119,31 +119,56 @@ UnifyRules::commit (TyTy::BaseType *base, TyTy::BaseType *other, b->append_reference (resolved->get_ref ()); b->append_reference (o->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) + if (resolved->get_kind () != TyTy::TypeKind::CONST) { - for (auto &ref : resolved->get_combined_refs ()) + 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) { - 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->is ()) - context.insert_implicit_type (ref, resolved); - else if (resolved->is () - && ref_tyty->is ()) + for (auto &ref : resolved->get_combined_refs ()) { - auto &const_expr = *static_cast (resolved); - if (const_expr.get_const_kind () - == TyTy::ConstType::ConstKind::Value) + 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->is ()) + context.insert_implicit_type (ref, resolved); + } + } + } + else + { + auto base_const = resolved->as_const_type (); + if (base_const->const_kind () == TyTy::BaseConstType::ConstKind::Value) + { + rust_debug ("UnifyRules::commit const value, resolved_ref=%u " + "resolved_ty_ref=%u combined_refs.size=%zu", + resolved->get_ref (), resolved->get_ty_ref (), + resolved->get_combined_refs ().size ()); + + for (auto &ref : resolved->get_combined_refs ()) + { + TyTy::BaseType *ref_tyty = nullptr; + bool ok = context.lookup_type (ref, &ref_tyty); + if (!ok) + continue; + if (ref_tyty->get_kind () != TyTy::TypeKind::CONST) + continue; + + auto ref_base_const = ref_tyty->as_const_type (); + if (ref_base_const->const_kind () + == TyTy::BaseConstType::ConstKind::Infer + || ref_base_const->const_kind () + == TyTy::BaseConstType::ConstKind::Decl) { + rust_debug (" committing to ref=%u kind=%d", ref, + (int) ref_base_const->const_kind ()); context.insert_implicit_type (ref, resolved); } } @@ -274,52 +299,38 @@ UnifyRules::go () // set the rtype now to the new inference var ltype = i; } - else if (ltype->is () && rtype->is ()) + else if (ltype->get_kind () == TyTy::TypeKind::CONST + && rtype->get_kind () == TyTy::TypeKind::CONST) { - const auto &lhs = *static_cast (ltype); - const auto &rhs = *static_cast (rtype); + const auto &lhs = *ltype->as_const_type (); + const auto &rhs = *rtype->as_const_type (); bool both_are_decls - = lhs.get_const_kind () == TyTy::ConstType::ConstKind::Decl - && rhs.get_const_kind () == TyTy::ConstType::ConstKind::Decl; + = lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl + && rhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl; bool have_decls - = lhs.get_const_kind () == TyTy::ConstType::ConstKind::Decl - || rhs.get_const_kind () == TyTy::ConstType::ConstKind::Decl; + = lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl + || rhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl; if (have_decls && !both_are_decls) { - if (lhs.get_const_kind () == TyTy::ConstType::ConstKind::Decl) + if (lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl) { TyTy::TyVar iv = TyTy::TyVar::get_implicit_const_infer_var ( - lhs, lhs.get_locus ()); + lhs.as_base_type ()->get_locus ()); ltype = iv.get_tyty (); } - else if (rhs.get_const_kind () - == TyTy::ConstType::ConstKind::Decl) + else if (rhs.const_kind () + == TyTy::BaseConstType::ConstKind::Decl) { TyTy::TyVar iv = TyTy::TyVar::get_implicit_const_infer_var ( - rhs, rhs.get_locus ()); + rhs.as_base_type ()->get_locus ()); rtype = iv.get_tyty (); } } } } - if ((ltype->is () || rtype->is ()) - && !(ltype->is () && rtype->is ())) - { - if (ltype->is ()) - { - auto const_type = static_cast (ltype); - ltype = const_type->get_ty (); - } - else if (rtype->is ()) - { - auto const_type = static_cast (rtype); - rtype = const_type->get_ty (); - } - } - switch (ltype->get_kind ()) { case TyTy::INFER: @@ -399,7 +410,7 @@ UnifyRules::go () return expect_opaque (static_cast (ltype), rtype); case TyTy::CONST: - return expect_const (static_cast (ltype), rtype); + return expect_const (ltype->as_const_type (), rtype); case TyTy::ERROR: return unify_error_type_node (); @@ -908,22 +919,33 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype) if (element_unify->get_kind () == TyTy::TypeKind::ERROR) return unify_error_type_node (); + auto ltype_cap = ltype->get_capacity (); + auto rtype_cap = type.get_capacity (); + + // If either capacity is not a const type, return error + if (ltype_cap->get_kind () != TyTy::TypeKind::CONST + || rtype_cap->get_kind () != TyTy::TypeKind::CONST) + return unify_error_type_node (); + bool save_emit_error = emit_error; emit_error = false; TyTy::BaseType *capacity_unify - = resolve_subtype (TyTy::TyWithLocation (ltype->get_capacity ()), - TyTy::TyWithLocation (type.get_capacity ())); + = resolve_subtype (TyTy::TyWithLocation (ltype_cap), + TyTy::TyWithLocation (rtype_cap)); emit_error = save_emit_error; if (capacity_unify->get_kind () != TyTy::TypeKind::CONST) return unify_error_type_node (); - TyTy::ConstType *capacity_type_unify - = static_cast (capacity_unify); - return new TyTy::ArrayType (type.get_ref (), type.get_ty_ref (), - type.get_ident ().locus, - capacity_type_unify, - TyTy::TyVar (element_unify->get_ref ())); + auto capacity_type_unify = capacity_unify->as_const_type (); + if (capacity_type_unify->const_kind () + == TyTy::BaseConstType::ConstKind::Error) + return unify_error_type_node (); + + return new TyTy::ArrayType ( + type.get_ref (), type.get_ty_ref (), type.get_ident ().locus, + TyTy::TyVar (capacity_type_unify->as_base_type ()->get_ref ()), + TyTy::TyVar (element_unify->get_ref ())); } break; @@ -2033,67 +2055,105 @@ UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype) } TyTy::BaseType * -UnifyRules::expect_const (TyTy::ConstType *ltype, TyTy::BaseType *rtype) +UnifyRules::expect_const (TyTy::BaseConstType *ltype, TyTy::BaseType *rtype) { if (rtype->get_kind () != TyTy::TypeKind::CONST) return unify_error_type_node (); - TyTy::ConstType &lhs = *ltype; - TyTy::ConstType &rhs = *static_cast (rtype); + auto &lhs = *ltype; + auto &rhs = *rtype->as_const_type (); - auto res = resolve_subtype (TyTy::TyWithLocation (lhs.get_ty ()), - TyTy::TyWithLocation (rhs.get_ty ())); - if (res->get_kind () == TyTy::TypeKind::ERROR) - return unify_error_type_node (); + // Handle error types early + if (lhs.const_kind () == TyTy::BaseConstType::ConstKind::Error + || rhs.const_kind () == TyTy::BaseConstType::ConstKind::Error) + { + auto lhs_base = ltype->as_base_type (); + return new TyTy::ConstErrorType (lhs.get_specified_type (), + lhs_base->get_ref (), + lhs_base->get_ty_ref (), + lhs_base->get_combined_refs ()); + } - tree lv = lhs.get_value (); - tree rv = rhs.get_value (); + // Try to resolve Decl types (ConstParamType) + TyTy::BaseConstType *resolved_lhs = &lhs; + TyTy::BaseConstType *resolved_rhs = &rhs; - if (error_operand_p (lv) && error_operand_p (rv)) + if (lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl) { - // this is only allowed for some silly senarios like: - // gcc/testsuite/rust/compile/issue-const_generics_5.rs - if (lhs.get_const_kind () == rhs.get_const_kind ()) + auto *param = static_cast (&lhs); + if (param->can_resolve ()) { - return new TyTy::ConstType (lhs.get_const_kind (), lhs.get_symbol (), - res, error_mark_node, - lhs.get_specified_bounds (), - lhs.get_locus (), lhs.get_ref (), - lhs.get_ty_ref (), - lhs.get_combined_refs ()); + auto *resolved = param->resolve (); + if (resolved->get_kind () == TyTy::TypeKind::CONST) + resolved_lhs = resolved->as_const_type (); } - - return unify_error_type_node (); } - bool equal = operand_equal_p (lv, rv, 0); - if (equal) + if (rhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl) { - return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, - lhs.get_symbol (), res, lv, - lhs.get_specified_bounds (), lhs.get_locus (), - lhs.get_ref (), lhs.get_ty_ref (), - lhs.get_combined_refs ()); + auto *param = static_cast (&rhs); + if (param->can_resolve ()) + { + auto *resolved = param->resolve (); + if (resolved->get_kind () == TyTy::TypeKind::CONST) + resolved_rhs = resolved->as_const_type (); + } } - if (lhs.get_const_kind () == TyTy::ConstType::Infer && !error_operand_p (rv)) + auto res = resolve_subtype ( + TyTy::TyWithLocation (resolved_lhs->get_specified_type ()), + TyTy::TyWithLocation (resolved_rhs->get_specified_type ())); + if (res->get_kind () == TyTy::TypeKind::ERROR) + return unify_error_type_node (); + + if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Value + && resolved_rhs->const_kind () == TyTy::BaseConstType::ConstKind::Value) { - lhs.set_value (rv); - return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, - lhs.get_symbol (), res, rv, - lhs.get_specified_bounds (), lhs.get_locus (), - lhs.get_ref (), lhs.get_ty_ref (), - lhs.get_combined_refs ()); + auto vlhs = static_cast (*resolved_lhs); + auto vrhs = static_cast (*resolved_rhs); + tree lv = vlhs.get_value (); + tree rv = vrhs.get_value (); + + bool ok = operand_equal_p (lv, rv, 0); + if (!ok) + return unify_error_type_node (); + else + { + auto lhs_base = resolved_lhs->as_base_type (); + return new TyTy::ConstValueType (lv, res, lhs_base->get_ref (), + lhs_base->get_ty_ref (), + lhs_base->get_combined_refs ()); + } } - else if (rhs.get_const_kind () == TyTy::ConstType::Infer - && !error_operand_p (lv)) + else if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Infer + && resolved_rhs->const_kind () + == TyTy::BaseConstType::ConstKind::Value) + return resolved_rhs->as_base_type (); + else if (resolved_rhs->const_kind () == TyTy::BaseConstType::ConstKind::Infer + && resolved_lhs->const_kind () + == TyTy::BaseConstType::ConstKind::Value) + return resolved_lhs->as_base_type (); + else if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Infer + && resolved_rhs->const_kind () + == TyTy::BaseConstType::ConstKind::Infer) + return resolved_lhs->as_base_type (); + else if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl + || resolved_rhs->const_kind () + == TyTy::BaseConstType::ConstKind::Decl) { - rhs.set_value (lv); - return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, - rhs.get_symbol (), res, lv, - rhs.get_specified_bounds (), rhs.get_locus (), - rhs.get_ref (), rhs.get_ty_ref (), - rhs.get_combined_refs ()); + // If we still have unresolved Decl after trying to resolve, unify with it + // This allows const inference to work + if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl + && resolved_rhs->const_kind () + != TyTy::BaseConstType::ConstKind::Decl) + return resolved_rhs->as_base_type (); + else if (resolved_rhs->const_kind () + == TyTy::BaseConstType::ConstKind::Decl + && resolved_lhs->const_kind () + != TyTy::BaseConstType::ConstKind::Decl) + return resolved_lhs->as_base_type (); + // Both are Decl - return lhs + return resolved_lhs->as_base_type (); } return unify_error_type_node (); diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h index 91b2b7a7090..4bed24c924f 100644 --- a/gcc/rust/typecheck/rust-unify.h +++ b/gcc/rust/typecheck/rust-unify.h @@ -95,7 +95,8 @@ protected: TyTy::BaseType *rtype); TyTy::BaseType *expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype); - TyTy::BaseType *expect_const (TyTy::ConstType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_const (TyTy::BaseConstType *ltype, + TyTy::BaseType *rtype); private: UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, -- 2.47.3