From: Philip Herron <[email protected]>

Since the changes to improve query_type to resolve function signitures
seperate to the bodies we can end up with the case where we resolve just
to a signiture which needs to call another function which is not yet type
checked so when we do const-eval during typechecking it fails because its
not ready.

This patch adds a new const context stack so we can override that behaviour
for const eval to make sure we dont have unresolved chunks for this case.

Fixes Rust-GCC/gccrs#4855

gcc/rust/ChangeLog:

        * checks/errors/privacy/rust-reachability.cc: dont need to assert
        * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): push 
const ctx
        * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItem::visit): 
likewise
        * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): likewise
        * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): likewse
        * typecheck/rust-hir-type-check.h: likewise
        * typecheck/rust-type-util.cc (query_type): check const_context_p

gcc/testsuite/ChangeLog:

        * rust/compile/issue-4855.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: 
https://github.com/Rust-GCC/gccrs/commit/937d1fdcd3d65156809796de303f0717eb540dab

The commit has been mentioned in the following issue(s):
 - Rust-GCC/gccrs#4855: https://github.com/Rust-GCC/gccrs/issues/4855

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4856

 .../errors/privacy/rust-reachability.cc       | 10 ++--
 .../typecheck/rust-hir-type-check-expr.cc     |  9 +++-
 .../typecheck/rust-hir-type-check-implitem.cc |  2 +
 .../typecheck/rust-hir-type-check-item.cc     |  2 +
 .../typecheck/rust-hir-type-check-type.cc     |  3 ++
 gcc/rust/typecheck/rust-hir-type-check.h      | 10 ++++
 gcc/rust/typecheck/rust-type-util.cc          | 25 ++++++----
 gcc/testsuite/rust/compile/issue-4855.rs      | 46 +++++++++++++++++++
 8 files changed, 89 insertions(+), 18 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/issue-4855.rs

diff --git a/gcc/rust/checks/errors/privacy/rust-reachability.cc 
b/gcc/rust/checks/errors/privacy/rust-reachability.cc
index 8fee0e88d..1e07e091e 100644
--- a/gcc/rust/checks/errors/privacy/rust-reachability.cc
+++ b/gcc/rust/checks/errors/privacy/rust-reachability.cc
@@ -50,14 +50,12 @@ ReachabilityVisitor::visit_generic_predicates (
     {
       if (generic->get_kind () == HIR::GenericParam::GenericKind::TYPE)
        {
-         TyTy::BaseType *generic_ty = nullptr;
-         auto ok = ty_ctx.lookup_type (generic->get_mappings ().get_hirid (),
-                                       &generic_ty);
+         TyTy::BaseType *ty = nullptr;
+         auto ok
+           = ty_ctx.lookup_type (generic->get_mappings ().get_hirid (), &ty);
          rust_assert (ok);
-         rust_assert (generic_ty->get_kind () == TyTy::PARAM);
 
-         auto generic_param = static_cast<TyTy::ParamType *> (generic_ty);
-         for (const auto &bound : generic_param->get_specified_bounds ())
+         for (const auto &bound : ty->get_specified_bounds ())
            {
              const auto trait = bound.get ()->get_hir_trait_ref ();
              ctx.update_reachability (trait->get_mappings (), item_reach);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc 
b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index cc967d4b3..a77b4de81 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -1150,13 +1150,16 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr)
   HIR::Expr *capacity_expr = nullptr;
   TyTy::BaseType *element_type = nullptr;
   TyTy::BaseType *capacity_type = nullptr;
+
   switch (elements.get_array_expr_type ())
     {
     case HIR::ArrayElems::ArrayExprType::COPIED:
       {
        HIR::ArrayElemsCopied &elems
          = static_cast<HIR::ArrayElemsCopied &> (elements);
+       context->push_const_context ();
        element_type = TypeCheckExpr::Resolve (elems.get_elem_to_copy ());
+       context->pop_const_context ();
 
        auto capacity_expr_ty
          = TypeCheckExpr::Resolve (elems.get_num_copies_expr ());
@@ -1183,12 +1186,14 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr)
       {
        HIR::ArrayElemsValues &elems
          = static_cast<HIR::ArrayElemsValues &> (elements);
-
+       context->push_const_context ();
        std::vector<TyTy::BaseType *> types;
        for (auto &elem : elems.get_values ())
          {
-           types.push_back (TypeCheckExpr::Resolve (*elem));
+           auto elem_ty = TypeCheckExpr::Resolve (*elem);
+           types.push_back (elem_ty);
          }
+       context->pop_const_context ();
 
        // this is a LUB
        element_type
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc 
b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
index 9d8f8385e..9fb0d70a3 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
@@ -457,7 +457,9 @@ void
 TypeCheckImplItem::visit (HIR::ConstantItem &constant)
 {
   TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
+  context->push_const_context ();
   TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
+  context->pop_const_context ();
 
   TyTy::BaseType *unified = unify_site (
     constant.get_mappings ().get_hirid (),
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc 
b/gcc/rust/typecheck/rust-hir-type-check-item.cc
index bff50778d..7cee908b4 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc
@@ -648,7 +648,9 @@ void
 TypeCheckItem::visit (HIR::ConstantItem &constant)
 {
   TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
+  context->push_const_context ();
   TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
+  context->pop_const_context ();
 
   TyTy::BaseType *unified = unify_site (
     constant.get_mappings ().get_hirid (),
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc 
b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index e44221a7e..55468516a 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -692,7 +692,10 @@ void
 TypeCheckType::visit (HIR::ArrayType &type)
 {
   auto element_type = TypeCheckType::Resolve (type.get_element_type ());
+  context->push_const_context ();
   auto capacity_type = TypeCheckExpr::Resolve (type.get_size_expr ());
+  context->pop_const_context ();
+
   if (capacity_type->get_kind () == TyTy::TypeKind::ERROR)
     return;
 
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h 
b/gcc/rust/typecheck/rust-hir-type-check.h
index f1db16c5f..3fdd08b4d 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -326,6 +326,14 @@ public:
 
   TyTy::VarianceAnalysis::CrateCtx &get_variance_analysis_ctx ();
 
+  void push_const_context (void) { const_context++; }
+  void pop_const_context (void)
+  {
+    if (const_context > 0)
+      const_context--;
+  }
+  bool const_context_p (void) { return (const_context > 0); }
+
 private:
   TypeCheckContext ();
 
@@ -377,6 +385,8 @@ private:
   // variance analysis
   TyTy::VarianceAnalysis::CrateCtx variance_analysis_ctx;
 
+  unsigned int const_context = 0;
+
   /** Used to resolve (interned) lifetime names to their bounding scope. */
   class LifetimeResolver
   {
diff --git a/gcc/rust/typecheck/rust-type-util.cc 
b/gcc/rust/typecheck/rust-type-util.cc
index f90c95953..226ea747b 100644
--- a/gcc/rust/typecheck/rust-type-util.cc
+++ b/gcc/rust/typecheck/rust-type-util.cc
@@ -79,16 +79,21 @@ query_type (HirId reference, TyTy::BaseType **result)
       bool is_local = item_defid.crateNum == mappings.get_current_crate ();
       bool is_fn
        = item.value ()->get_item_kind () == HIR::Item::ItemKind::Function;
-      if (is_fn && is_local)
+      if (!context->const_context_p ())
        {
-         HIR::Function &fn = *static_cast<HIR::Function *> (item.value ());
-         *result = TypeCheckItem::ResolveFunctionSignature (fn);
-       }
-      else if (item.value ()->get_item_kind () == HIR::Item::ItemKind::Trait
-              && is_local)
-       {
-         HIR::Trait &trait = *static_cast<HIR::Trait *> (item.value ());
-         *result = TypeCheckItem::ResolveTraitSignature (trait);
+         if (is_fn && is_local)
+           {
+             HIR::Function &fn = *static_cast<HIR::Function *> (item.value ());
+             *result = TypeCheckItem::ResolveFunctionSignature (fn);
+           }
+         else if (item.value ()->get_item_kind () == HIR::Item::ItemKind::Trait
+                  && is_local)
+           {
+             HIR::Trait &trait = *static_cast<HIR::Trait *> (item.value ());
+             *result = TypeCheckItem::ResolveTraitSignature (trait);
+           }
+         else
+           *result = TypeCheckItem::Resolve (*item.value ());
        }
       else
        {
@@ -159,7 +164,7 @@ query_type (HirId reference, TyTy::BaseType **result)
       DefId item_defid = impl_item->first->get_impl_mappings ().get_defid ();
       bool is_local = item_defid.crateNum == mappings.get_current_crate ();
       if (impl_item->first->get_impl_item_type () == HIR::ImplItem::FUNCTION
-         && is_local)
+         && is_local && !context->const_context_p ())
        {
          HIR::Function &fn = *static_cast<HIR::Function *> (impl_item->first);
          *result = TypeCheckImplItem::ResolveFunctionSignature (
diff --git a/gcc/testsuite/rust/compile/issue-4855.rs 
b/gcc/testsuite/rust/compile/issue-4855.rs
new file mode 100644
index 000000000..5c5b47b90
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-4855.rs
@@ -0,0 +1,46 @@
+#![feature(no_core, intrinsics, lang_items, staged_api)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+mod my_u32 {
+    impl u32 {
+        pub const fn to_be_bytes(self) -> [u8; crate::mem::size_of::<Self>()] {
+            [0; crate::mem::size_of::<Self>()]
+        }
+
+        pub fn other_method(self) -> u32 {
+            self
+        }
+    }
+}
+
+mod my_f32 {
+    impl f32 {
+        pub fn to_bits(self) -> u32 {
+            0
+        }
+
+        pub fn do_something(self) -> u32 {
+            self.to_bits().other_method()
+        }
+    }
+}
+
+extern "rust-intrinsic" {
+    #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
+    pub fn size_of<T>() -> usize;
+}
+
+mod mem {
+    pub const fn size_of<T>() -> usize {
+        crate::size_of::<T>()
+    }
+}
+
+fn main() -> i32 {
+    let x: f32 = 0.0;
+    let _ = x.do_something();
+    0
+}

base-commit: 8a8099e11efb2dd86191a9e80320e36acc48ca7a
-- 
2.55.0

Reply via email to