[gccrs COMMIT] gccrs: Fix bug when compiling const position intrinsic calls

gerris.rs@gmail.com gerris.rs@gmail.com
Mon Sep 7 13:30:30 GMT 2026


From: Philip Herron <herron.philip@googlemail.com>

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 <herron.philip@googlemail.com>
---
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



More information about the Gcc-rust mailing list