Skip to content

Commit 8422d94

Browse files
committed
gccrs: Do proper const folding during typechecking for array capacities
This patch adds proper folding to the const expression for array capacity we already have the const folding mechanics and the query system needed to handle cases where the capacity is a function call in a const context. This leverages and pulls the gcc tree capacity into the TyTy::ArrayType so it can be used for more typechecking and eventually doing more const generics work. Addresses #3885 gcc/rust/ChangeLog: * backend/rust-compile-base.cc (HIRCompileBase::query_compile_const_expr): new wrapper * backend/rust-compile-base.h: add prototype * backend/rust-compile-context.cc (Context::get): singleton helper * backend/rust-compile-context.h: likewise * backend/rust-compile-type.cc (TyTyResolveCompile::visit): handle infer's that can default * rust-session-manager.cc (Session::compile_crate): create the gcc context earlier for tychk * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): const fold it * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): likewise * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): likewise * typecheck/rust-tyty.cc (BaseType::monomorphized_clone): fix constructor call (ArrayType::as_string): print capacity (ArrayType::clone): fix constructor call * typecheck/rust-tyty.h: track capacity * typecheck/rust-unify.cc (UnifyRules::expect_array): check the capacities gcc/testsuite/ChangeLog: * rust/compile/all-cast.rs: shows array capacity now * rust/compile/arrays2.rs: likewise * rust/compile/const3.rs: fix error message * rust/compile/const_generics_3.rs: disable until typecheck we get proper errors now! * rust/compile/usize1.rs: proper capacity error message Signed-off-by: Philip Herron <[email protected]>
1 parent 508b195 commit 8422d94

17 files changed

+127
-63
lines changed

gcc/rust/backend/rust-compile-base.cc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,25 @@ HIRCompileBase::compile_constant_expr (
575575
expr_locus);
576576
}
577577

578+
tree
579+
HIRCompileBase::query_compile_const_expr (Context *ctx, TyTy::BaseType *expr_ty,
580+
HIR::Expr &const_value_expr)
581+
{
582+
HIRCompileBase c (ctx);
583+
584+
ctx->push_const_context ();
585+
586+
HirId expr_id = const_value_expr.get_mappings ().get_hirid ();
587+
location_t locus = const_value_expr.get_locus ();
588+
tree capacity_expr = HIRCompileBase::compile_constant_expr (
589+
ctx, expr_id, expr_ty, expr_ty, Resolver::CanonicalPath::create_empty (),
590+
const_value_expr, locus, locus);
591+
592+
ctx->pop_const_context ();
593+
594+
return fold_expr (capacity_expr);
595+
}
596+
578597
tree
579598
HIRCompileBase::indirect_expression (tree expr, location_t locus)
580599
{

gcc/rust/backend/rust-compile-base.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ class HIRCompileBase
3838
const Resolver::CanonicalPath &canonical_path, HIR::Expr &const_value_expr,
3939
location_t locus, location_t expr_locus);
4040

41+
static tree query_compile_const_expr (Context *ctx, TyTy::BaseType *expr_ty,
42+
HIR::Expr &const_value_expr);
43+
4144
protected:
4245
HIRCompileBase (Context *ctx) : ctx (ctx) {}
4346

gcc/rust/backend/rust-compile-context.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@
2222
namespace Rust {
2323
namespace Compile {
2424

25+
Context *
26+
Context::get ()
27+
{
28+
static Context *instance;
29+
if (instance == nullptr)
30+
instance = new Context ();
31+
32+
return instance;
33+
}
34+
2535
Context::Context ()
2636
: tyctx (Resolver::TypeCheckContext::get ()),
2737
mappings (Analysis::Mappings::get ()), mangler (Mangler ())

gcc/rust/backend/rust-compile-context.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ struct CustomDeriveInfo
4949
class Context
5050
{
5151
public:
52-
Context ();
52+
static Context *get ();
5353

5454
void setup_builtins ();
5555

@@ -390,6 +390,8 @@ class Context
390390
}
391391

392392
private:
393+
Context ();
394+
393395
Resolver::TypeCheckContext *tyctx;
394396
Analysis::Mappings &mappings;
395397
Mangler mangler;

gcc/rust/backend/rust-compile-type.cc

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,13 @@ TyTyResolveCompile::visit (const TyTy::InferType &type)
121121

122122
if (orig == lookup)
123123
{
124+
TyTy::BaseType *def = nullptr;
125+
if (type.default_type (&def))
126+
{
127+
translated = TyTyResolveCompile::compile (ctx, def);
128+
return;
129+
}
130+
124131
translated = error_mark_node;
125132
return;
126133
}
@@ -463,22 +470,7 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type)
463470
{
464471
tree element_type
465472
= TyTyResolveCompile::compile (ctx, type.get_element_type ());
466-
467-
ctx->push_const_context ();
468-
469-
HIR::Expr &hir_capacity_expr = type.get_capacity_expr ();
470-
TyTy::BaseType *capacity_expr_ty = nullptr;
471-
bool ok = ctx->get_tyctx ()->lookup_type (
472-
hir_capacity_expr.get_mappings ().get_hirid (), &capacity_expr_ty);
473-
rust_assert (ok);
474-
tree capacity_expr = HIRCompileBase::compile_constant_expr (
475-
ctx, hir_capacity_expr.get_mappings ().get_hirid (), capacity_expr_ty,
476-
capacity_expr_ty, Resolver::CanonicalPath::create_empty (),
477-
hir_capacity_expr, type.get_locus (), hir_capacity_expr.get_locus ());
478-
479-
ctx->pop_const_context ();
480-
481-
tree folded_capacity_expr = fold_expr (capacity_expr);
473+
tree folded_capacity_expr = type.get_capacity ();
482474

483475
// build_index_type takes the maximum index, which is one less than
484476
// the length.

gcc/rust/rust-session-manager.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,7 @@ Session::compile_crate (const char *filename)
681681
Resolver2_0::ImmutableNameResolutionContext::init (name_resolution_ctx);
682682

683683
// type resolve
684+
Compile::Context *ctx = Compile::Context::get ();
684685
Resolver::TypeResolution::Resolve (hir);
685686

686687
Resolver::TypeCheckContext::get ()->get_variance_analysis_ctx ().solve ();
@@ -728,16 +729,15 @@ Session::compile_crate (const char *filename)
728729
return;
729730

730731
// do compile to gcc generic
731-
Compile::Context ctx;
732-
Compile::CompileCrate::Compile (hir, &ctx);
732+
Compile::CompileCrate::Compile (hir, ctx);
733733

734734
// we can't do static analysis if there are errors to worry about
735735
if (!saw_errors ())
736736
{
737737
// lints
738738
Analysis::ScanDeadcode::Scan (hir);
739-
Analysis::UnusedVariables::Lint (ctx);
740-
Analysis::ReadonlyCheck::Lint (ctx);
739+
Analysis::UnusedVariables::Lint (*ctx);
740+
Analysis::ReadonlyCheck::Lint (*ctx);
741741

742742
// metadata
743743
bool specified_emit_metadata
@@ -758,7 +758,7 @@ Session::compile_crate (const char *filename)
758758
}
759759

760760
// pass to GCC middle-end
761-
ctx.write_to_backend ();
761+
ctx->write_to_backend ();
762762
}
763763

764764
void

gcc/rust/typecheck/rust-hir-type-check-base.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
// <http://www.gnu.org/licenses/>.
1818

1919
#include "rust-hir-type-check-base.h"
20+
#include "rust-compile-base.h"
2021
#include "rust-hir-type-check-expr.h"
2122
#include "rust-hir-type-check-type.h"
2223
#include "rust-hir-trait-resolve.h"
@@ -287,9 +288,11 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings,
287288
crate_num),
288289
UNKNOWN_LOCAL_DEFID);
289290

291+
auto ctx = Compile::Context::get ();
292+
tree capacity = Compile::HIRCompileBase::query_compile_const_expr (
293+
ctx, expected_ty, *literal_capacity);
290294
TyTy::ArrayType *array
291-
= new TyTy::ArrayType (array_mapping.get_hirid (), locus,
292-
*literal_capacity,
295+
= new TyTy::ArrayType (array_mapping.get_hirid (), locus, capacity,
293296
TyTy::TyVar (u8->get_ref ()));
294297
context->insert_type (array_mapping, array);
295298

gcc/rust/typecheck/rust-hir-type-check-expr.cc

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "rust-hir-type-check-item.h"
3232
#include "rust-type-util.h"
3333
#include "rust-immutable-name-resolution-context.h"
34+
#include "rust-compile-base.h"
3435

3536
// for flag_name_resolution_2_0
3637
#include "options.h"
@@ -1031,6 +1032,7 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr)
10311032

10321033
HIR::Expr *capacity_expr = nullptr;
10331034
TyTy::BaseType *element_type = nullptr;
1035+
TyTy::BaseType *capacity_type = nullptr;
10341036
switch (elements.get_array_expr_type ())
10351037
{
10361038
case HIR::ArrayElems::ArrayExprType::COPIED:
@@ -1039,7 +1041,7 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr)
10391041
= static_cast<HIR::ArrayElemsCopied &> (elements);
10401042
element_type = TypeCheckExpr::Resolve (elems.get_elem_to_copy ());
10411043

1042-
auto capacity_type
1044+
auto capacity_expr_ty
10431045
= TypeCheckExpr::Resolve (elems.get_num_copies_expr ());
10441046

10451047
TyTy::BaseType *expected_ty = nullptr;
@@ -1048,13 +1050,14 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr)
10481050
context->insert_type (elems.get_num_copies_expr ().get_mappings (),
10491051
expected_ty);
10501052

1051-
unify_site (expr.get_mappings ().get_hirid (),
1052-
TyTy::TyWithLocation (expected_ty),
1053-
TyTy::TyWithLocation (
1054-
capacity_type, elems.get_num_copies_expr ().get_locus ()),
1055-
expr.get_locus ());
1053+
unify_site (
1054+
expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (expected_ty),
1055+
TyTy::TyWithLocation (capacity_expr_ty,
1056+
elems.get_num_copies_expr ().get_locus ()),
1057+
expr.get_locus ());
10561058

10571059
capacity_expr = &elems.get_num_copies_expr ();
1060+
capacity_type = expected_ty;
10581061
}
10591062
break;
10601063

@@ -1096,13 +1099,20 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr)
10961099
bool ok = context->lookup_builtin ("usize", &expected_ty);
10971100
rust_assert (ok);
10981101
context->insert_type (mapping, expected_ty);
1102+
capacity_type = expected_ty;
10991103
}
11001104
break;
11011105
}
11021106

1103-
infered = new TyTy::ArrayType (expr.get_mappings ().get_hirid (),
1104-
expr.get_locus (), *capacity_expr,
1105-
TyTy::TyVar (element_type->get_ref ()));
1107+
rust_assert (capacity_expr);
1108+
rust_assert (capacity_type);
1109+
auto ctx = Compile::Context::get ();
1110+
tree capacity
1111+
= Compile::HIRCompileBase::query_compile_const_expr (ctx, capacity_type,
1112+
*capacity_expr);
1113+
infered
1114+
= new TyTy::ArrayType (expr.get_mappings ().get_hirid (), expr.get_locus (),
1115+
capacity, TyTy::TyVar (element_type->get_ref ()));
11061116
}
11071117

11081118
// empty struct

gcc/rust/typecheck/rust-hir-type-check-type.cc

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "rust-substitution-mapper.h"
3030
#include "rust-type-util.h"
3131
#include "rust-system.h"
32+
#include "rust-compile-base.h"
3233

3334
namespace Rust {
3435
namespace Resolver {
@@ -710,9 +711,14 @@ TypeCheckType::visit (HIR::ArrayType &type)
710711
type.get_size_expr ().get_locus ());
711712

712713
TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ());
713-
translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (),
714-
type.get_locus (), type.get_size_expr (),
715-
TyTy::TyVar (base->get_ref ()));
714+
715+
auto ctx = Compile::Context::get ();
716+
tree capacity
717+
= Compile::HIRCompileBase::query_compile_const_expr (ctx, capacity_type,
718+
type.get_size_expr ());
719+
translated
720+
= new TyTy::ArrayType (type.get_mappings ().get_hirid (), type.get_locus (),
721+
capacity, TyTy::TyVar (base->get_ref ()));
716722
}
717723

718724
void

gcc/rust/typecheck/rust-tyty.cc

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@
3030
#include "rust-tyty-cmp.h"
3131
#include "rust-type-util.h"
3232
#include "rust-hir-type-bounds.h"
33+
#include "print-tree.h"
3334

3435
#include "options.h"
3536
#include "rust-system.h"
37+
#include "tree.h"
3638

3739
namespace Rust {
3840
namespace TyTy {
@@ -574,7 +576,7 @@ BaseType::monomorphized_clone () const
574576
{
575577
TyVar elm = arr->get_var_element_type ().monomorphized_clone ();
576578
return new ArrayType (arr->get_ref (), arr->get_ty_ref (), ident.locus,
577-
arr->get_capacity_expr (), elm,
579+
arr->get_capacity (), elm,
578580
arr->get_combined_refs ());
579581
}
580582
else if (auto slice = x->try_as<const SliceType> ())
@@ -2486,7 +2488,16 @@ ArrayType::accept_vis (TyConstVisitor &vis) const
24862488
std::string
24872489
ArrayType::as_string () const
24882490
{
2489-
return "[" + get_element_type ()->as_string () + ":" + "CAPACITY" + "]";
2491+
std::string capacity_str = "<error>";
2492+
if (!error_operand_p (capacity))
2493+
{
2494+
unsigned HOST_WIDE_INT length = wi::to_wide (capacity).to_uhwi ();
2495+
2496+
char buf[64];
2497+
snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_UNSIGNED, length);
2498+
capacity_str = std::string (buf);
2499+
}
2500+
return "[" + get_element_type ()->as_string () + "; " + capacity_str + "]";
24902501
}
24912502

24922503
bool
@@ -2525,7 +2536,7 @@ ArrayType::get_var_element_type () const
25252536
BaseType *
25262537
ArrayType::clone () const
25272538
{
2528-
return new ArrayType (get_ref (), get_ty_ref (), ident.locus, capacity_expr,
2539+
return new ArrayType (get_ref (), get_ty_ref (), ident.locus, capacity,
25292540
element_type, get_combined_refs ());
25302541
}
25312542

0 commit comments

Comments
 (0)