]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Refactor TyTy::ConstType into separate types
authorPhilip Herron <herron.philip@googlemail.com>
Sat, 4 Oct 2025 20:53:40 +0000 (21:53 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Thu, 30 Oct 2025 20:30:56 +0000 (21:30 +0100)
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 <herron.philip@googlemail.com>
21 files changed:
gcc/rust/backend/rust-compile-expr.cc
gcc/rust/backend/rust-compile-pattern.cc
gcc/rust/backend/rust-compile-type.cc
gcc/rust/backend/rust-compile-type.h
gcc/rust/typecheck/rust-hir-type-check-base.cc
gcc/rust/typecheck/rust-hir-type-check-expr.cc
gcc/rust/typecheck/rust-hir-type-check-pattern.cc
gcc/rust/typecheck/rust-hir-type-check-type.cc
gcc/rust/typecheck/rust-substitution-mapper.cc
gcc/rust/typecheck/rust-substitution-mapper.h
gcc/rust/typecheck/rust-type-util.cc
gcc/rust/typecheck/rust-tyty-call.h
gcc/rust/typecheck/rust-tyty-subst.cc
gcc/rust/typecheck/rust-tyty-util.cc
gcc/rust/typecheck/rust-tyty-util.h
gcc/rust/typecheck/rust-tyty-variance-analysis-private.h
gcc/rust/typecheck/rust-tyty-visitor.h
gcc/rust/typecheck/rust-tyty.cc
gcc/rust/typecheck/rust-tyty.h
gcc/rust/typecheck/rust-unify.cc
gcc/rust/typecheck/rust-unify.h

index d09ac727529f251f2dc058f79774d61b516bf618..0a627f353524564ee3d848588986859e837d03f5 100644 (file)
@@ -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<TyTy::ConstValueType *> (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 ();
index 9459fd618f35b1fe7efc2f163aa7d19e509a7e67..82333dc39c046706d5d169899c87508331cfe1d3 100644 (file)
@@ -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<TyTy::ArrayType *> (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<TyTy::ConstValueType *> (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<TyTy::ArrayType *> (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<TyTy::ConstValueType *> (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 ())
index d58b53c5c92aade1f159279c8ae9c01f252e174d..5b00afae4e571d6728525cd6ca0b64ed8e7fbf67 100644 (file)
@@ -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<TyTy::ConstValueType *> (capacity_const);
+  auto folded_capacity_expr = capacity_value.get_value ();
 
   // build_index_type takes the maximum index, which is one less than
   // the length.
index 0675343776586163679fbc67c693afe1327ef26d..d6c32595e268173e9e52e3b25c7444ad4ee7518a 100644 (file)
@@ -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;
index ebe7fad713c7b010e18e56e40891f5439f9f0809..cdbaa69cd776c05cff7fd72f62ac806fdb491040 100644 (file)
@@ -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);
index c7f8192bada1009088cde3ba6f2fc01e435d546d..71dcaa316ab35b4dee09ce0451c6b9c36762e627 100644 (file)
@@ -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
index 4d9d60ca5bdc7f51763ed84b97d6579ca4dae224..e8467f0c7b8a770c01baed9e8c1c5d8d4fe1a911 100644 (file)
@@ -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<TyTy::ArrayType &> (*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<TyTy::ConstValueType *> (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 (),
index 833ad92db59845893fb9ba2bb790592fec8a68ca..799efc809d51c9e6a787a04b27bbab4ac6b5b9bf 100644 (file)
@@ -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<TyTy::ConstType *> (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<TyTy::ErrorType> ())
-       {
-         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
index 958651e559393a614bc8b77612932092ad5cb29b..238ede45b05710b3f90aaa6009d2155c94c431ca 100644 (file)
@@ -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)
 {
index 2389d83e392d1ace852bc5e99aaf1dd29eddb890..98f9e7268b716a84fb7bb7e9f3b051311842870c 100644 (file)
@@ -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 {}
index 34e99d34bb32dc72ff2ae5d858e0476d357476ab..6f30ebf49e9b28411d995966289c0c7a311f71d5 100644 (file)
@@ -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;
index 9e4aab56ea1e42b56ee820ec1f0b522063fd99e9..025a1ad456124acec5130317d439320c3f7dd878 100644 (file)
@@ -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;
index 4699b71197a4e31a9aa34dd124c2d0f3ade8c6aa..e82e8a3b0bca4829f6973fe1b843ac19b9716a8d 100644 (file)
@@ -54,8 +54,8 @@ SubstitutionParamMapping::as_string () const
 SubstitutionParamMapping
 SubstitutionParamMapping::clone () const
 {
-  return SubstitutionParamMapping (generic,
-                                  static_cast<ParamType *> (param->clone ()));
+  return SubstitutionParamMapping (generic, static_cast<BaseGeneric *> (
+                                             param->clone ()));
 }
 
 BaseGeneric *
@@ -167,7 +167,12 @@ SubstitutionParamMapping::fill_param_ty (
     }
   else if (type.get_kind () == TyTy::TypeKind::CONST)
     {
-      param = static_cast<BaseGeneric *> (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<BaseGeneric *> (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<ConstType> ())
+         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<ConstType> ());
+      rust_assert (base_generic->get_kind () == TyTy::TypeKind::CONST);
       const auto const_param
-       = static_cast<const TyTy::ConstType *> (base_generic);
-      auto specified_type = const_param->get_ty ();
+       = static_cast<const TyTy::ConstParamType *> (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<ConstType> ())
+      if (expr_type->get_kind () == TyTy::TypeKind::CONST)
        {
-         TyTy::ConstType *const_expr_type
-           = static_cast<TyTy::ConstType *> (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<ConstType> ())
+      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 (&param_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<TyTy::ConstType> ());
-             const auto &const_type
-               = *static_cast<const TyTy::ConstType *> (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 ();
            }
index 4bc17231bf12e1221eb35f15ec0baf71c498d949..c6c740b2cba8526b9643e4305464f74118f55ef5 100644 (file)
@@ -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);
index 1c8fd72379117f8f2696f7245d0a613ea12c9292..26101fd4d93231b8cd7f34c3a766b90c98ea2b8b 100644 (file)
@@ -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);
index f1833c5874c262c5caabc694b702d009334f420a..b7ca5e1a01dfa04f45f27450dc8c67ddab3fd558 100644 (file)
@@ -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. */
index 778307591d1426161ed111f05e3d7673e5592657..f7f3665ef5920f2a6d60dfab3c1b07004ea8d38e 100644 (file)
@@ -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;
index ff84cfc9d111e9f788769d9625d8a14368e47d94..da5c35049faa20de4d0ff840d1200d7319d0e11a 100644 (file)
@@ -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<ConstParamType *> (p);
+             auto pr = decl->resolve ();
+             if (pr == x)
+               return pr;
+
+             x = pr;
+           }
+         else
+           {
+             return x;
+           }
+       }
       else if (auto p = x->try_as<PlaceholderType> ())
        {
          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<const ConstParamType *> (p);
+             auto pr = decl->resolve ();
+             if (pr == x)
+               return pr;
+
+             x = pr;
+           }
+         else
+           {
+             return x;
+           }
+       }
       else if (auto p = x->try_as<const PlaceholderType> ())
        {
          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<const SliceType> ())
@@ -751,7 +785,8 @@ BaseType::is_concrete () const
 {
   const TyTy::BaseType *x = destructure ();
 
-  if (x->is<ParamType> () || x->is<ProjectionType> ())
+  if (x->is<ParamType> () || x->is<ProjectionType> ()
+      || x->is<ConstParamType> ())
     {
       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<const ConstType> ())
-    {
-      return const_type->get_value () != error_mark_node;
-    }
   else if (x->is<InferType> () || x->is<BoolType> () || x->is<CharType> ()
           || x->is<IntType> () || x->is<UintType> () || x->is<FloatType> ()
           || x->is<USizeType> () || x->is<ISizeType> () || x->is<NeverType> ()
@@ -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<TyTy::ConstType *> (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<TypeBoundPredicate> specified_bounds,
-                     location_t locus, HirId ref, HirId ty_ref,
-                     std::set<HirId> refs)
-  : BaseGeneric (ref, ty_ref, KIND,
-                {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID,
-                                                   symbol.empty () ? "<n/a>"
-                                                                   : symbol),
+  FILE *stream = open_memstream (&buf, &size);
+  if (!stream)
+    return "<error>";
+
+  print_generic_stmt (stream, value, TDF_NONE);
+  fclose (stream);
+
+  std::string result = (buf ? std::string (buf, size) : "<error>");
+  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<HirId> 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<const ConstParamType &> (*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<ConstParamType *> (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<HirId> 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 "<error>";
+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) : "<error>");
-  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<const ConstValueType &> (*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<HirId> 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 () + " - <error>" + ">";
-       }
-    }
+  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<const ConstType &> (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<HirId> 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<TyTy::ConstType> ());
-      return static_cast<TyTy::ConstType *> (subst);
-    }
+  vis.visit (*this);
+}
+
+void
+ConstErrorType::accept_vis (TyConstVisitor &vis) const
+{
+  vis.visit (*this);
+}
+
+std::string
+ConstErrorType::as_string () const
+{
+  return "<const_error>";
+}
+
+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
index 480a195b8683b98510f0627c21942bf5069198a4..3236bf34a5925f48aac5bca1c35df35abf3e97a4 100644 (file)
@@ -91,6 +91,7 @@ public:
 
 class TyVisitor;
 class TyConstVisitor;
+class BaseConstType;
 class BaseType : public TypeBoundsMappings
 {
 public:
@@ -226,6 +227,11 @@ public:
     return static_cast<T *> (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<HirId> refs = std::set<HirId> ());
@@ -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<TypeBoundPredicate> specified_bounds, location_t locus,
-            HirId ref, HirId ty_ref,
-            std::set<HirId> refs = std::set<HirId> ());
+  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<HirId> refs = std::set<HirId> ());
+
+  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<BaseType *> (this); }
+  const BaseType *as_base_type () const override
+  {
+    return static_cast<const BaseType *> (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<HirId> refs = std::set<HirId> ());
+
+  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<BaseType *> (this); }
+  const BaseType *as_base_type () const override
+  {
+    return static_cast<const BaseType *> (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<HirId> refs = std::set<HirId> ());
+
+  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<BaseType *> (this); }
+  const BaseType *as_base_type () const override
+  {
+    return static_cast<const BaseType *> (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<HirId> refs = std::set<HirId> ());
+
+  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<BaseType *> (this); }
+  const BaseType *as_base_type () const override
+  {
+    return static_cast<const BaseType *> (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<HirId> refs = std::set<HirId> ())
     : 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<HirId> refs = std::set<HirId> ())
     : 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
index be7ac51962b5c35e82dea87d2ee47f4276553acd..43dd6dca61738926d0265660d6ae051d12e519e6 100644 (file)
@@ -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<TyTy::InferType *> (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<TyTy::InferType *> (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<TyTy::InferType> ())
-           context.insert_implicit_type (ref, resolved);
-         else if (resolved->is<TyTy::ConstType> ()
-                  && ref_tyty->is<TyTy::ConstType> ())
+         for (auto &ref : resolved->get_combined_refs ())
            {
-             auto &const_expr = *static_cast<TyTy::ConstType *> (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<TyTy::InferType> ())
+               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<TyTy::ConstType> () && rtype->is<TyTy::ConstType> ())
+      else if (ltype->get_kind () == TyTy::TypeKind::CONST
+              && rtype->get_kind () == TyTy::TypeKind::CONST)
        {
-         const auto &lhs = *static_cast<TyTy::ConstType *> (ltype);
-         const auto &rhs = *static_cast<TyTy::ConstType *> (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<TyTy::ConstType> () || rtype->is<TyTy::ConstType> ())
-      && !(ltype->is<TyTy::ConstType> () && rtype->is<TyTy::ConstType> ()))
-    {
-      if (ltype->is<TyTy::ConstType> ())
-       {
-         auto const_type = static_cast<TyTy::ConstType *> (ltype);
-         ltype = const_type->get_ty ();
-       }
-      else if (rtype->is<TyTy::ConstType> ())
-       {
-         auto const_type = static_cast<TyTy::ConstType *> (rtype);
-         rtype = const_type->get_ty ();
-       }
-    }
-
   switch (ltype->get_kind ())
     {
     case TyTy::INFER:
@@ -399,7 +410,7 @@ UnifyRules::go ()
       return expect_opaque (static_cast<TyTy::OpaqueType *> (ltype), rtype);
 
     case TyTy::CONST:
-      return expect_const (static_cast<TyTy::ConstType *> (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<TyTy::ConstType *> (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<TyTy::ConstType *> (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<TyTy::ConstParamType *> (&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<TyTy::ConstParamType *> (&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<TyTy::ConstValueType &> (*resolved_lhs);
+      auto vrhs = static_cast<TyTy::ConstValueType &> (*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 ();
index 91b2b7a70905150b9f001b16e00a7661137ef8cf..4bed24c924f80fd5cc0e91fc369031af6b752711 100644 (file)
@@ -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,