https://gcc.gnu.org/g:f71f2f5947b8935d1ba4934831482bb3c9b4d9ff
commit r17-4338-gf71f2f5947b8935d1ba4934831482bb3c9b4d9ff Author: Philip Herron <[email protected]> Date: Mon Sep 7 11:58:01 2026 +0100 gccrs: Fix bug when compiling const position intrinsic calls 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]> Diff: --- .../checks/errors/privacy/rust-reachability.cc | 10 ++--- gcc/rust/typecheck/rust-hir-type-check-expr.cc | 9 ++++- gcc/rust/typecheck/rust-hir-type-check-implitem.cc | 2 + gcc/rust/typecheck/rust-hir-type-check-item.cc | 2 + gcc/rust/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(-) diff --git a/gcc/rust/checks/errors/privacy/rust-reachability.cc b/gcc/rust/checks/errors/privacy/rust-reachability.cc index 8fee0e88dd43..1e07e091eeca 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 cc967d4b301a..a77b4de81df4 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 9d8f8385ecac..9fb0d70a3401 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 bff50778d86e..7cee908b403c 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 e44221a7e983..55468516a786 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 f1db16c5f18a..3fdd08b4d414 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 f90c959532d2..226ea747b029 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 000000000000..5c5b47b9025d --- /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 +}
