expr_locus);
}
+tree
+HIRCompileBase::query_compile_const_expr (Context *ctx, TyTy::BaseType *expr_ty,
+ HIR::Expr &const_value_expr)
+{
+ HIRCompileBase c (ctx);
+
+ ctx->push_const_context ();
+
+ HirId expr_id = const_value_expr.get_mappings ().get_hirid ();
+ location_t locus = const_value_expr.get_locus ();
+ tree capacity_expr = HIRCompileBase::compile_constant_expr (
+ ctx, expr_id, expr_ty, expr_ty, Resolver::CanonicalPath::create_empty (),
+ const_value_expr, locus, locus);
+
+ ctx->pop_const_context ();
+
+ return fold_expr (capacity_expr);
+}
+
tree
HIRCompileBase::indirect_expression (tree expr, location_t locus)
{
const Resolver::CanonicalPath &canonical_path, HIR::Expr &const_value_expr,
location_t locus, location_t expr_locus);
+ static tree query_compile_const_expr (Context *ctx, TyTy::BaseType *expr_ty,
+ HIR::Expr &const_value_expr);
+
protected:
HIRCompileBase (Context *ctx) : ctx (ctx) {}
namespace Rust {
namespace Compile {
+Context *
+Context::get ()
+{
+ static Context *instance;
+ if (instance == nullptr)
+ instance = new Context ();
+
+ return instance;
+}
+
Context::Context ()
: tyctx (Resolver::TypeCheckContext::get ()),
mappings (Analysis::Mappings::get ()), mangler (Mangler ())
class Context
{
public:
- Context ();
+ static Context *get ();
void setup_builtins ();
}
private:
+ Context ();
+
Resolver::TypeCheckContext *tyctx;
Analysis::Mappings &mappings;
Mangler mangler;
if (orig == lookup)
{
+ TyTy::BaseType *def = nullptr;
+ if (type.default_type (&def))
+ {
+ translated = TyTyResolveCompile::compile (ctx, def);
+ return;
+ }
+
translated = error_mark_node;
return;
}
{
tree element_type
= TyTyResolveCompile::compile (ctx, type.get_element_type ());
-
- ctx->push_const_context ();
-
- HIR::Expr &hir_capacity_expr = type.get_capacity_expr ();
- TyTy::BaseType *capacity_expr_ty = nullptr;
- bool ok = ctx->get_tyctx ()->lookup_type (
- hir_capacity_expr.get_mappings ().get_hirid (), &capacity_expr_ty);
- rust_assert (ok);
- tree capacity_expr = HIRCompileBase::compile_constant_expr (
- ctx, hir_capacity_expr.get_mappings ().get_hirid (), capacity_expr_ty,
- capacity_expr_ty, Resolver::CanonicalPath::create_empty (),
- hir_capacity_expr, type.get_locus (), hir_capacity_expr.get_locus ());
-
- ctx->pop_const_context ();
-
- tree folded_capacity_expr = fold_expr (capacity_expr);
+ tree folded_capacity_expr = type.get_capacity ();
// build_index_type takes the maximum index, which is one less than
// the length.
Resolver2_0::ImmutableNameResolutionContext::init (name_resolution_ctx);
// type resolve
+ Compile::Context *ctx = Compile::Context::get ();
Resolver::TypeResolution::Resolve (hir);
Resolver::TypeCheckContext::get ()->get_variance_analysis_ctx ().solve ();
return;
// do compile to gcc generic
- Compile::Context ctx;
- Compile::CompileCrate::Compile (hir, &ctx);
+ Compile::CompileCrate::Compile (hir, ctx);
// we can't do static analysis if there are errors to worry about
if (!saw_errors ())
{
// lints
Analysis::ScanDeadcode::Scan (hir);
- Analysis::UnusedVariables::Lint (ctx);
- Analysis::ReadonlyCheck::Lint (ctx);
+ Analysis::UnusedVariables::Lint (*ctx);
+ Analysis::ReadonlyCheck::Lint (*ctx);
// metadata
bool specified_emit_metadata
}
// pass to GCC middle-end
- ctx.write_to_backend ();
+ ctx->write_to_backend ();
}
void
// <http://www.gnu.org/licenses/>.
#include "rust-hir-type-check-base.h"
+#include "rust-compile-base.h"
#include "rust-hir-type-check-expr.h"
#include "rust-hir-type-check-type.h"
#include "rust-hir-trait-resolve.h"
crate_num),
UNKNOWN_LOCAL_DEFID);
+ auto ctx = Compile::Context::get ();
+ tree capacity = Compile::HIRCompileBase::query_compile_const_expr (
+ ctx, expected_ty, *literal_capacity);
TyTy::ArrayType *array
- = new TyTy::ArrayType (array_mapping.get_hirid (), locus,
- *literal_capacity,
+ = new TyTy::ArrayType (array_mapping.get_hirid (), locus, capacity,
TyTy::TyVar (u8->get_ref ()));
context->insert_type (array_mapping, array);
#include "rust-hir-type-check-item.h"
#include "rust-type-util.h"
#include "rust-immutable-name-resolution-context.h"
+#include "rust-compile-base.h"
// for flag_name_resolution_2_0
#include "options.h"
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:
= static_cast<HIR::ArrayElemsCopied &> (elements);
element_type = TypeCheckExpr::Resolve (elems.get_elem_to_copy ());
- auto capacity_type
+ auto capacity_expr_ty
= TypeCheckExpr::Resolve (elems.get_num_copies_expr ());
TyTy::BaseType *expected_ty = nullptr;
context->insert_type (elems.get_num_copies_expr ().get_mappings (),
expected_ty);
- unify_site (expr.get_mappings ().get_hirid (),
- TyTy::TyWithLocation (expected_ty),
- TyTy::TyWithLocation (
- capacity_type, elems.get_num_copies_expr ().get_locus ()),
- expr.get_locus ());
+ unify_site (
+ expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (expected_ty),
+ TyTy::TyWithLocation (capacity_expr_ty,
+ elems.get_num_copies_expr ().get_locus ()),
+ expr.get_locus ());
capacity_expr = &elems.get_num_copies_expr ();
+ capacity_type = expected_ty;
}
break;
bool ok = context->lookup_builtin ("usize", &expected_ty);
rust_assert (ok);
context->insert_type (mapping, expected_ty);
+ capacity_type = expected_ty;
}
break;
}
- infered = new TyTy::ArrayType (expr.get_mappings ().get_hirid (),
- expr.get_locus (), *capacity_expr,
- TyTy::TyVar (element_type->get_ref ()));
+ rust_assert (capacity_expr);
+ rust_assert (capacity_type);
+ auto ctx = Compile::Context::get ();
+ tree capacity
+ = Compile::HIRCompileBase::query_compile_const_expr (ctx, capacity_type,
+ *capacity_expr);
+ infered
+ = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), expr.get_locus (),
+ capacity, TyTy::TyVar (element_type->get_ref ()));
}
// empty struct
#include "rust-substitution-mapper.h"
#include "rust-type-util.h"
#include "rust-system.h"
+#include "rust-compile-base.h"
namespace Rust {
namespace Resolver {
type.get_size_expr ().get_locus ());
TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ());
- translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (),
- type.get_locus (), type.get_size_expr (),
- TyTy::TyVar (base->get_ref ()));
+
+ auto ctx = Compile::Context::get ();
+ tree capacity
+ = Compile::HIRCompileBase::query_compile_const_expr (ctx, capacity_type,
+ type.get_size_expr ());
+ translated
+ = new TyTy::ArrayType (type.get_mappings ().get_hirid (), type.get_locus (),
+ capacity, TyTy::TyVar (base->get_ref ()));
}
void
#include "rust-tyty-cmp.h"
#include "rust-type-util.h"
#include "rust-hir-type-bounds.h"
+#include "print-tree.h"
#include "options.h"
#include "rust-system.h"
+#include "tree.h"
namespace Rust {
namespace TyTy {
{
TyVar elm = arr->get_var_element_type ().monomorphized_clone ();
return new ArrayType (arr->get_ref (), arr->get_ty_ref (), ident.locus,
- arr->get_capacity_expr (), elm,
+ arr->get_capacity (), elm,
arr->get_combined_refs ());
}
else if (auto slice = x->try_as<const SliceType> ())
std::string
ArrayType::as_string () const
{
- return "[" + get_element_type ()->as_string () + ":" + "CAPACITY" + "]";
+ std::string capacity_str = "<error>";
+ if (!error_operand_p (capacity))
+ {
+ unsigned HOST_WIDE_INT length = wi::to_wide (capacity).to_uhwi ();
+
+ char buf[64];
+ snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_UNSIGNED, length);
+ capacity_str = std::string (buf);
+ }
+ return "[" + get_element_type ()->as_string () + "; " + capacity_str + "]";
}
bool
BaseType *
ArrayType::clone () const
{
- return new ArrayType (get_ref (), get_ty_ref (), ident.locus, capacity_expr,
+ return new ArrayType (get_ref (), get_ty_ref (), ident.locus, capacity,
element_type, get_combined_refs ());
}
#include "rust-tyty-region.h"
#include "rust-system.h"
#include "rust-hir.h"
+#include "tree.h"
namespace Rust {
public:
static constexpr auto KIND = TypeKind::ARRAY;
- ArrayType (HirId ref, location_t locus, HIR::Expr &capacity_expr, TyVar base,
+ ArrayType (HirId ref, location_t locus, tree capacity, TyVar base,
std::set<HirId> refs = std::set<HirId> ())
: BaseType (ref, ref, TypeKind::ARRAY,
{Resolver::CanonicalPath::create_empty (), locus}, refs),
- element_type (base), capacity_expr (capacity_expr)
+ element_type (base), capacity (capacity)
{}
- ArrayType (HirId ref, HirId ty_ref, location_t locus,
- HIR::Expr &capacity_expr, TyVar base,
- std::set<HirId> refs = std::set<HirId> ())
+ ArrayType (HirId ref, HirId ty_ref, location_t locus, tree capacity,
+ TyVar base, std::set<HirId> refs = std::set<HirId> ())
: BaseType (ref, ty_ref, TypeKind::ARRAY,
{Resolver::CanonicalPath::create_empty (), locus}, refs),
- element_type (base), capacity_expr (capacity_expr)
+ element_type (base), capacity (capacity)
{}
void accept_vis (TyVisitor &vis) override;
BaseType *clone () const final override;
- HIR::Expr &get_capacity_expr () const { return capacity_expr; }
+ tree get_capacity () const { return capacity; }
ArrayType *handle_substitions (SubstitutionArgumentMappings &mappings);
private:
TyVar element_type;
- // FIXME: I dont think this should be in tyty - tyty should already be const
- // evaluated
- HIR::Expr &capacity_expr;
+ tree capacity;
};
class SliceType : public BaseType
// <http://www.gnu.org/licenses/>.
#include "rust-unify.h"
+#include "tree.h"
namespace Rust {
namespace Resolver {
= resolve_subtype (TyTy::TyWithLocation (ltype->get_element_type ()),
TyTy::TyWithLocation (type.get_element_type ()));
- if (element_unify->get_kind () != TyTy::TypeKind::ERROR)
- {
- return new TyTy::ArrayType (type.get_ref (), type.get_ty_ref (),
- type.get_ident ().locus,
- type.get_capacity_expr (),
- TyTy::TyVar (
- element_unify->get_ref ()));
- }
+ if (element_unify->get_kind () == TyTy::TypeKind::ERROR)
+ return new TyTy::ErrorType (0);
+
+ // TODO infer capacity?
+ tree lcap = ltype->get_capacity ();
+ tree rcap = type.get_capacity ();
+ if (error_operand_p (lcap) || error_operand_p (rcap))
+ return new TyTy::ErrorType (0);
+
+ auto lc = wi::to_wide (lcap).to_uhwi ();
+ auto rc = wi::to_wide (rcap).to_uhwi ();
+ if (lc != rc)
+ return new TyTy::ErrorType (0);
+
+ return new TyTy::ArrayType (type.get_ref (), type.get_ty_ref (),
+ type.get_ident ().locus,
+ type.get_capacity (),
+ TyTy::TyVar (element_unify->get_ref ()));
}
break;
0u32 as char; // { dg-error "cannot cast .u32. as .char., only .u8. can be cast as .char." }
- let x = &[1_usize, 2] as [usize]; // { dg-error "cast to unsized type: .& .usize:CAPACITY.. as ..usize.." }
+ let x = &[1_usize, 2] as [usize]; // { dg-error "cast to unsized type: .& .usize; 2.. as ..usize.." }
let a = &0u8; // Here, `x` is a `&u8`.
let y: u32 = a as u32; // { dg-error "casting .& u8. as .u32. is invalid" }
-// { dg-additional-options "-w" }
fn main() {
let array: [i32; 5] = [1, 2, 3];
- // { dg-error "mismatched types, expected an array with a fixed size of 5 elements, found one with 3 elements" "" { target *-*-* } .-1 }
+ // { dg-error "mismatched types, expected ..i32; 5.. but got ...integer.; 3.. .E0308." "" { target *-*-* } .-1 }
}
}
fn main() {
- let a = [15; size()]; // { dg-error "only functions marked as .const. are allowed to be called from constant contexts" }
+ let a = [15; size()]; // { dg-error "calls in constants are limited to constant functions, tuple structs and tuple variants" }
}
-// { dg-additional-options "-w -frust-compile-until=compilation" }
+// { dg-additional-options "-w -frust-compile-until=typecheck" }
#[lang = "sized"]
trait Sized {}
fn main() {
let a = [1, 2, 3];
let b: u32 = 1;
- let c = a[b]; // { dg-error "the type ...integer..CAPACITY.. cannot be indexed by .u32." }
+ let c = a[b]; // { dg-error "the type ...integer.; 3.. cannot be indexed by .u32." }
}