Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion gcc/rust/backend/rust-compile-resolve-path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,12 @@ ResolvePathRef::resolve_with_node_id (
auto d = lookup->destructure ();
rust_assert (d->get_kind () == TyTy::TypeKind::CONST);
auto c = d->as_const_type ();
rust_assert (c->const_kind () == TyTy::BaseConstType::ConstKind::Value);
if (c->const_kind () != TyTy::BaseConstType::ConstKind::Value)
{
// Emit diagnostic so the test passes instead of silently failing
rust_error_at (expr_locus, "cannot evaluate constant expression");
return error_mark_node;
}
auto val = static_cast<TyTy::ConstValueType *> (c);
return val->get_value ();
}
Expand Down
52 changes: 45 additions & 7 deletions gcc/rust/backend/rust-compile-type.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "rust-compile-type.h"
#include "rust-constexpr.h"
#include "rust-compile-base.h"
#include "rust-compile-expr.h"

#include "tree.h"
#include "fold-const.h"
Expand All @@ -27,6 +28,34 @@
namespace Rust {
namespace Compile {

// Universal helper to convert any Rust Constant into a GCC Tree
static tree
compile_const_to_tree (const TyTy::BaseConstType *capacity_const, Context *ctx,
location_t locus)
{
switch (capacity_const->const_kind ())
{
case TyTy::BaseConstType::ConstKind::Expr:
{
auto &expr_type
= *static_cast<const TyTy::ConstExprType *> (capacity_const);
// Compile the expression (handle { N + 1 })
return CompileExpr::Compile (*expr_type.get_expr (), ctx);
}
case TyTy::BaseConstType::ConstKind::Value:
{
auto &capacity_value
= *static_cast<const TyTy::ConstValueType *> (capacity_const);
// Return the already-known value (handle 2)
return capacity_value.get_value ();
}
default:
// FAIL GRACEFULLY: Return error instead of crashing on Param/Infer/Error
rust_error_at (locus, "unexpected constant kind in backend compilation");
return error_mark_node;
}
}

static const std::string RUST_ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR";

TyTyResolveCompile::TyTyResolveCompile (Context *ctx, bool trait_object_mode)
Expand Down Expand Up @@ -165,6 +194,12 @@ TyTyResolveCompile::visit (const TyTy::ConstErrorType &type)
translated = error_mark_node;
}

void
TyTyResolveCompile::visit (const TyTy::ConstExprType &type)
{
translated = CompileExpr::Compile (*type.get_expr (), ctx);
}

void
TyTyResolveCompile::visit (const TyTy::ProjectionType &type)
{
Expand Down Expand Up @@ -488,9 +523,11 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type)
{
tree element_type
= TyTyResolveCompile::compile (ctx, type.get_element_type ());

// 1. Get capacity
auto const_capacity = type.get_capacity ();

// Check if capacity is a const type
// 2. CHECK if it is valid BEFORE using it
if (const_capacity->get_kind () != TyTy::TypeKind::CONST)
{
rust_error_at (type.get_locus (), "array capacity is not a const type");
Expand All @@ -499,14 +536,15 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type)
}

auto *capacity_const = const_capacity->as_const_type ();
tree folded_capacity_expr
= compile_const_to_tree (capacity_const, ctx, type.get_locus ());

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 ();
if (folded_capacity_expr == error_mark_node)
{
translated = error_mark_node;
return;
}

// build_index_type takes the maximum index, which is one less than
// the length.
tree index_type_tree = build_index_type (
fold_build2 (MINUS_EXPR, sizetype, folded_capacity_expr, size_one_node));

Expand Down
1 change: 1 addition & 0 deletions gcc/rust/backend/rust-compile-type.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class TyTyResolveCompile : protected TyTy::TyConstVisitor
void visit (const TyTy::ConstValueType &) override;
void visit (const TyTy::ConstInferType &) override;
void visit (const TyTy::ConstErrorType &) override;
void visit (const TyTy::ConstExprType &) override;
void visit (const TyTy::StrType &) override;
void visit (const TyTy::NeverType &) override;
void visit (const TyTy::PlaceholderType &) override;
Expand Down
96 changes: 96 additions & 0 deletions gcc/rust/typecheck/rust-hir-type-check-path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include "rust-hir-item.h"
#include "rust-session-manager.h"
#include "rust-immutable-name-resolution-context.h"
#include "rust-name-resolver.h"
#include "rust-hir-expr.h"

namespace Rust {
namespace Resolver {
Expand Down Expand Up @@ -241,6 +243,66 @@ TypeCheckExpr::visit (HIR::PathInExpression &expr)
}
}

/* Helper to check if a const generic expression is dependent (symbolic).
Returns true if the expression contains paths or identifiers (e.g., { N + 1
}). Returns false if the expression is purely literal/concrete (e.g., { 1 + 1
}). */
static bool
is_const_dependent (HIR::Expr &expr)
{
switch (expr.get_expression_type ())
{
case HIR::Expr::ExprType::Path:
{
// A path is only dependent if it resolves to a generic parameter.
// We use Resolver2_0 to find the definition ID.
auto &nr_ctx
= Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
auto resolved = nr_ctx.lookup (expr.get_mappings ().get_nodeid ());

if (!resolved)
return false;

return Analysis::Mappings::get ().lookup_hir_generic_param (*resolved)
!= nullptr;
}

case HIR::Expr::ExprType::Lit:
return false;

case HIR::Expr::ExprType::Block:
{
auto &block = static_cast<HIR::BlockExpr &> (expr);
if (block.has_expr ())

return is_const_dependent (block.get_final_expr ());

if (!block.get_statements ().empty ())
return true;

return false;
}

case HIR::Expr::ExprType::Grouped:
{
auto &group = static_cast<HIR::GroupedExpr &> (expr);

return is_const_dependent (group.get_expr_in_parens ());
}

case HIR::Expr::ExprType::Operator:
{
auto &arith = static_cast<HIR::ArithmeticOrLogicalExpr &> (expr);

return is_const_dependent (arith.get_lhs ())
|| is_const_dependent (arith.get_rhs ());
}

default:
return true;
}
}

TyTy::BaseType *
TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
NodeId *root_resolved_node_id)
Expand Down Expand Up @@ -366,6 +428,25 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
// turbo-fish segment path::<ty>
if (seg.has_generic_args ())
{
// Check for dependent const expressions (like { N + 1 })
bool is_dependent = false;
for (auto &arg : seg.get_generic_args ().get_const_args ())
{
if (is_const_dependent (*arg.get_expression ()))
{
is_dependent = true;
break;
}
}

if (is_dependent)
{
*root_resolved_node_id = ref_node_id;
*offset = *offset + 1;
root_tyty = lookup;
continue;
}

lookup = SubstMapper::Resolve (lookup, expr.get_locus (),
&seg.get_generic_args (),
context->regions_from_generic_args (
Expand Down Expand Up @@ -524,6 +605,21 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,

if (seg.has_generic_args ())
{
// Check for dependent const expressions (like { N + 1 })
bool is_dependent = false;
for (auto &arg : seg.get_generic_args ().get_const_args ())
{
if (is_const_dependent (*arg.get_expression ()))
{
is_dependent = true;
break;
}
}
if (is_dependent)
{
continue;
}

rust_debug_loc (seg.get_locus (), "applying segment generics: %s",
tyseg->as_string ().c_str ());
tyseg
Expand Down
1 change: 1 addition & 0 deletions gcc/rust/typecheck/rust-hir-type-check-pattern.cc
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,7 @@ TypeCheckPattern::visit (HIR::SlicePattern &pattern)
case TyTy::BaseConstType::ConstKind::Decl:
case TyTy::BaseConstType::ConstKind::Infer:
case TyTy::BaseConstType::ConstKind::Error:
case TyTy::BaseConstType::ConstKind::Expr:
cap = error_mark_node;
break;
}
Expand Down
6 changes: 6 additions & 0 deletions gcc/rust/typecheck/rust-substitution-mapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,12 @@ SubstMapperInternal::visit (TyTy::ConstErrorType &type)
resolved = type.clone ();
}

void
SubstMapperInternal::visit (TyTy::ConstExprType &type)
{
resolved = type.clone ();
}

void
SubstMapperInternal::visit (TyTy::PlaceholderType &type)
{
Expand Down
4 changes: 4 additions & 0 deletions gcc/rust/typecheck/rust-substitution-mapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class SubstMapper : public TyTy::TyVisitor
void visit (TyTy::ConstValueType &) override { rust_unreachable (); }
void visit (TyTy::ConstInferType &) override { rust_unreachable (); }
void visit (TyTy::ConstErrorType &) override { rust_unreachable (); }
void visit (TyTy::ConstExprType &) override { rust_unreachable (); }
void visit (TyTy::StrType &) override { rust_unreachable (); }
void visit (TyTy::NeverType &) override { rust_unreachable (); }
void visit (TyTy::DynamicObjectType &) override { rust_unreachable (); }
Expand Down Expand Up @@ -100,6 +101,7 @@ class SubstMapperInternal : public TyTy::TyVisitor
void visit (TyTy::ConstValueType &type) override;
void visit (TyTy::ConstInferType &type) override;
void visit (TyTy::ConstErrorType &type) override;
void visit (TyTy::ConstExprType &type) override;
void visit (TyTy::PlaceholderType &type) override;
void visit (TyTy::ProjectionType &type) override;
void visit (TyTy::ClosureType &type) override;
Expand Down Expand Up @@ -157,6 +159,7 @@ class SubstMapperFromExisting : public TyTy::TyVisitor
void visit (TyTy::ConstValueType &) override { rust_unreachable (); }
void visit (TyTy::ConstInferType &) override { rust_unreachable (); }
void visit (TyTy::ConstErrorType &) override { rust_unreachable (); }
void visit (TyTy::ConstExprType &) override { rust_unreachable (); }
void visit (TyTy::StrType &) override { rust_unreachable (); }
void visit (TyTy::NeverType &) override { rust_unreachable (); }
void visit (TyTy::PlaceholderType &) override { rust_unreachable (); }
Expand Down Expand Up @@ -201,6 +204,7 @@ class GetUsedSubstArgs : public TyTy::TyConstVisitor
void visit (const TyTy::ConstValueType &) override {}
void visit (const TyTy::ConstInferType &) override {}
void visit (const TyTy::ConstErrorType &) override {}
void visit (const TyTy::ConstExprType &) override {}
void visit (const TyTy::StrType &) override {}
void visit (const TyTy::NeverType &) override {}
void visit (const TyTy::PlaceholderType &) override {}
Expand Down
7 changes: 7 additions & 0 deletions gcc/rust/typecheck/rust-tyty-call.cc
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,13 @@ TypeCheckCallExpr::visit (FnPtr &type)
resolved = type.get_return_type ()->monomorphized_clone ();
}

void
TypeCheckCallExpr::visit (ConstExprType &type)
{
// A constant expression is not a callable function.
// We do nothing, which leaves 'resolved' as nullptr and fails gracefully.
}

// method call checker

TypeCheckMethodCallExpr::TypeCheckMethodCallExpr (
Expand Down
2 changes: 2 additions & 0 deletions gcc/rust/typecheck/rust-tyty-call.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ class TypeCheckCallExpr : private TyVisitor
void visit (ConstInferType &) override { rust_unreachable (); }
void visit (ConstErrorType &) override { rust_unreachable (); }

void visit (ConstExprType &type) override;

// tuple-structs
void visit (ADTType &type) override;

Expand Down
5 changes: 5 additions & 0 deletions gcc/rust/typecheck/rust-tyty-variance-analysis-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,11 @@ template <typename VARIANCE> class VisitorBase final : public TyVisitor

void visit (ErrorType &type) override {}

void visit (TyTy::ConstExprType &type) override
{
// TODO: Traverse expression for variance
}

void visit (PlaceholderType &type) override { rust_unreachable (); }
void visit (InferType &type) override { rust_unreachable (); }

Expand Down
2 changes: 2 additions & 0 deletions gcc/rust/typecheck/rust-tyty-visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class TyVisitor
virtual void visit (ConstValueType &type) = 0;
virtual void visit (ConstInferType &type) = 0;
virtual void visit (ConstErrorType &type) = 0;
virtual void visit (ConstExprType &type) = 0;
virtual void visit (StrType &type) = 0;
virtual void visit (NeverType &type) = 0;
virtual void visit (PlaceholderType &type) = 0;
Expand Down Expand Up @@ -83,6 +84,7 @@ class TyConstVisitor
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 ConstExprType &type) = 0;
virtual void visit (const StrType &type) = 0;
virtual void visit (const NeverType &type) = 0;
virtual void visit (const PlaceholderType &type) = 0;
Expand Down
Loading
Loading