std::string ir_symbol_name
= canonical_path.get () + fntype->subst_as_string ();
+ rust_debug_loc (locus, "--> Compiling [%s] - %s", ir_symbol_name.c_str (),
+ fntype->get_name ().c_str ());
+
// we don't mangle the main fn since we haven't implemented the main shim
bool is_main_fn = fn_name.compare ("main") == 0 && is_root_item
&& canonical_path.size () <= 2;
return;
}
+ rust_debug_loc (stmt.get_locus (), " -> LetStmt %s",
+ ty->as_string ().c_str ());
+
// setup var decl nodes
fncontext fnctx = ctx->peek_fn ();
tree fndecl = fnctx.fndecl;
{
tree element_type
= TyTyResolveCompile::compile (ctx, type.get_element_type ());
- tree folded_capacity_expr = type.get_capacity ();
+ TyTy::ConstType *const_capacity = type.get_capacity ();
+ tree folded_capacity_expr = const_capacity->get_value ();
// build_index_type takes the maximum index, which is one less than
// the length.
location_t get_locus () const override final { return locus; };
- bool has_default_expression () { return default_expression != nullptr; }
+ bool has_default_expression () const { return default_expression != nullptr; }
std::string get_name () { return name; }
Type &get_type ()
}
Expr &get_default_expression () { return *default_expression; }
+ const Expr &get_default_expression () const { return *default_expression; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
std::unique_ptr<Expr> &get_expression () { return expression; }
+ location_t get_locus () const { return locus; }
+
private:
std::unique_ptr<Expr> expression;
location_t locus;
bool has_generic_args () const
{
return !(lifetime_args.empty () && type_args.empty ()
- && binding_args.empty ());
+ && binding_args.empty () && const_args.empty ());
}
GenericArgs (std::vector<Lifetime> lifetime_args,
#include "rust-hir-type-check-base.h"
#include "rust-compile-base.h"
+#include "rust-hir-item.h"
#include "rust-hir-type-check-expr.h"
#include "rust-hir-type-check-type.h"
#include "rust-hir-trait-resolve.h"
#include "rust-type-util.h"
#include "rust-attribute-values.h"
#include "rust-tyty.h"
+#include "tree.h"
namespace Rust {
namespace Resolver {
void
TypeCheckBase::ResolveGenericParams (
+ const HIR::Item::ItemKind item_kind, location_t item_locus,
const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign,
ABI abi)
{
TypeCheckBase ctx;
- ctx.resolve_generic_params (generic_params, substitutions, is_foreign, abi);
+ ctx.resolve_generic_params (item_kind, item_locus, generic_params,
+ substitutions, is_foreign, abi);
}
static void
auto ctx = Compile::Context::get ();
tree capacity = Compile::HIRCompileBase::query_compile_const_expr (
ctx, expected_ty, *literal_capacity);
+
+ TyTy::ConstType *capacity_expr
+ = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "",
+ expected_ty, capacity, {},
+ literal_capacity->get_locus (),
+ literal_capacity->get_mappings ().get_hirid (),
+ literal_capacity->get_mappings ().get_hirid (),
+ {});
+
TyTy::ArrayType *array
- = new TyTy::ArrayType (array_mapping.get_hirid (), locus, capacity,
- TyTy::TyVar (u8->get_ref ()));
+ = new TyTy::ArrayType (array_mapping.get_hirid (), locus,
+ capacity_expr, TyTy::TyVar (u8->get_ref ()));
context->insert_type (array_mapping, array);
infered = new TyTy::ReferenceType (expr_mappings.get_hirid (),
void
TypeCheckBase::resolve_generic_params (
+ const HIR::Item::ItemKind item_kind, location_t item_locus,
const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign,
ABI abi)
if (param.has_default_expression ())
{
+ switch (item_kind)
+ {
+ case HIR::Item::ItemKind::Struct:
+ case HIR::Item::ItemKind::Enum:
+ case HIR::Item::ItemKind::TypeAlias:
+ case HIR::Item::ItemKind::Trait:
+ case HIR::Item::ItemKind::Union:
+ break;
+
+ default:
+ {
+ rich_location r (line_table, item_locus);
+ r.add_fixit_remove (param.get_locus ());
+ rust_error_at (
+ r,
+ "default values for const generic parameters are not "
+ "allowed here");
+ }
+ break;
+ }
+
auto expr_type
= TypeCheckExpr::Resolve (param.get_default_expression ());
expr_type,
param.get_default_expression ().get_locus ()),
param.get_locus ());
+
+ // fold the default value
+ auto ctx = Compile::Context::get ();
+ auto &expr = param.get_default_expression ();
+ tree default_value
+ = Compile::HIRCompileBase::query_compile_const_expr (
+ ctx, specified_type, expr);
+
+ TyTy::ConstType *default_const_decl
+ = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value,
+ param.get_name (), specified_type,
+ default_value, {}, param.get_locus (),
+ expr.get_mappings ().get_hirid (),
+ expr.get_mappings ().get_hirid (), {});
+
+ context->insert_type (expr.get_mappings (), default_const_decl);
}
- context->insert_type (generic_param->get_mappings (),
- specified_type);
+ TyTy::ConstType *const_decl
+ = new TyTy::ConstType (TyTy::ConstType::ConstKind::Decl,
+ param.get_name (), specified_type,
+ error_mark_node, {}, param.get_locus (),
+ param.get_mappings ().get_hirid (),
+ param.get_mappings ().get_hirid (), {});
- // TODO for const generics
- // TyTy::SubstitutionParamMapping p (*generic_param, param_type);
- // substitutions.push_back (p);
+ context->insert_type (generic_param->get_mappings (), const_decl);
+ TyTy::SubstitutionParamMapping p (*generic_param, const_decl);
+ substitutions.push_back (p);
}
break;
virtual ~TypeCheckBase () {}
static void ResolveGenericParams (
+ const HIR::Item::ItemKind item_kind, location_t item_locus,
const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign,
ABI abi);
location_t locus);
void resolve_generic_params (
+ const HIR::Item::ItemKind item_kind, location_t item_locus,
const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
std::vector<TyTy::SubstitutionParamMapping> &substitutions,
bool is_foreign = false, ABI abi = ABI::RUST);
#include "rust-type-util.h"
#include "rust-immutable-name-resolution-context.h"
#include "rust-compile-base.h"
+#include "tree.h"
namespace Rust {
namespace Resolver {
{
auto &elements = expr.get_internal_elements ();
+ TyTy::BaseType *expected_ty = nullptr;
+ bool ok = context->lookup_builtin ("usize", &expected_ty);
+ rust_assert (ok);
+
HIR::Expr *capacity_expr = nullptr;
TyTy::BaseType *element_type = nullptr;
TyTy::BaseType *capacity_type = nullptr;
auto capacity_expr_ty
= TypeCheckExpr::Resolve (elems.get_num_copies_expr ());
- TyTy::BaseType *expected_ty = nullptr;
- bool ok = context->lookup_builtin ("usize", &expected_ty);
- rust_assert (ok);
context->insert_type (elems.get_num_copies_expr ().get_mappings (),
expected_ty);
UNDEF_LOCATION, {});
// mark the type for this implicit node
- TyTy::BaseType *expected_ty = nullptr;
- bool ok = context->lookup_builtin ("usize", &expected_ty);
- rust_assert (ok);
context->insert_type (mapping, expected_ty);
capacity_type = expected_ty;
}
rust_assert (capacity_expr);
rust_assert (capacity_type);
auto ctx = Compile::Context::get ();
- tree capacity
+ tree capacity_value
= Compile::HIRCompileBase::query_compile_const_expr (ctx, capacity_type,
*capacity_expr);
+ HirId size_id = capacity_expr->get_mappings ().get_hirid ();
+ TyTy::ConstType *const_type
+ = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "", expected_ty,
+ capacity_value, {}, capacity_expr->get_locus (),
+ size_id, size_id);
infered
= new TyTy::ArrayType (expr.get_mappings ().get_hirid (), expr.get_locus (),
- capacity, TyTy::TyVar (element_type->get_ref ()));
+ const_type, TyTy::TyVar (element_type->get_ref ()));
}
// empty struct
TyTy::TyVar result_type
= expr.has_return_type ()
? TyTy::TyVar (
- TypeCheckType::Resolve (expr.get_return_type ())->get_ref ())
+ TypeCheckType::Resolve (expr.get_return_type ())->get_ref ())
: TyTy::TyVar::get_implicit_infer_var (expr.get_locus ());
// resolve the block
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (function.has_generics ())
{
- resolve_generic_params (function.get_generic_params (), substitutions,
+ resolve_generic_params (HIR::Item::ItemKind::Function,
+ function.get_locus (),
+ function.get_generic_params (), substitutions,
true /*is_foreign*/, parent.get_abi ());
}
auto binder_pin = context->push_lifetime_binder ();
if (function.has_generics ())
- resolve_generic_params (function.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Function,
+ function.get_locus (),
+ function.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : function.get_where_clause ().get_items ())
auto binder_pin = context->push_lifetime_binder ();
if (alias.has_generics ())
- resolve_generic_params (alias.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::TypeAlias, alias.get_locus (),
+ alias.get_generic_params (), substitutions);
TyTy::BaseType *actual_type
= TypeCheckType::Resolve (alias.get_type_aliased ());
#include "optional.h"
#include "rust-canonical-path.h"
#include "rust-diagnostics.h"
+#include "rust-hir-item.h"
#include "rust-hir-type-check-enumitem.h"
#include "rust-hir-type-check-implitem.h"
#include "rust-hir-type-check-type.h"
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (struct_decl.has_generics ())
- resolve_generic_params (struct_decl.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Struct,
+ struct_decl.get_locus (),
+ struct_decl.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (struct_decl.has_generics ())
- resolve_generic_params (struct_decl.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Struct,
+ struct_decl.get_locus (),
+ struct_decl.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
auto lifetime_pin = context->push_clean_lifetime_resolver ();
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (enum_decl.has_generics ())
- resolve_generic_params (enum_decl.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Enum, enum_decl.get_locus (),
+ enum_decl.get_generic_params (), substitutions);
// Process #[repr(X)] attribute, if any
const AST::AttrVec &attrs = enum_decl.get_outer_attrs ();
auto lifetime_pin = context->push_clean_lifetime_resolver ();
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (union_decl.has_generics ())
- resolve_generic_params (union_decl.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Union, union_decl.get_locus (),
+ union_decl.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : union_decl.get_where_clause ().get_items ())
auto lifetime_pin = context->push_clean_lifetime_resolver ();
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (function.has_generics ())
- resolve_generic_params (function.get_generic_params (),
- substitutions); // TODO resolve constraints
+ resolve_generic_params (HIR::Item::ItemKind::Function,
+ function.get_locus (),
+ function.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : function.get_where_clause ().get_items ())
{
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (impl_block.has_generics ())
- resolve_generic_params (impl_block.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Impl, impl_block.get_locus (),
+ impl_block.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : impl_block.get_where_clause ().get_items ())
{
auto &array_ty_ty = static_cast<TyTy::ArrayType &> (*parent);
parent_element_ty = array_ty_ty.get_element_type ();
- tree cap = array_ty_ty.get_capacity ();
+ auto capacity = array_ty_ty.get_capacity ();
+ tree cap = capacity->get_value ();
if (error_operand_p (cap))
{
rust_error_at (parent->get_locus (),
void
TypeCheckType::visit (HIR::ArrayType &type)
{
+ auto element_type = TypeCheckType::Resolve (type.get_element_type ());
auto capacity_type = TypeCheckExpr::Resolve (type.get_size_expr ());
if (capacity_type->get_kind () == TyTy::TypeKind::ERROR)
return;
rust_assert (ok);
context->insert_type (type.get_size_expr ().get_mappings (), expected_ty);
- unify_site (type.get_size_expr ().get_mappings ().get_hirid (),
- TyTy::TyWithLocation (expected_ty),
- TyTy::TyWithLocation (capacity_type,
- type.get_size_expr ().get_locus ()),
- type.get_size_expr ().get_locus ());
+ TyTy::ConstType *const_type = nullptr;
+ if (capacity_type->get_kind () == TyTy::TypeKind::CONST)
+ {
+ const_type = static_cast<TyTy::ConstType *> (capacity_type);
- TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ());
+ unify_site (type.get_size_expr ().get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (expected_ty),
+ TyTy::TyWithLocation (const_type->get_ty (),
+ type.get_size_expr ().get_locus ()),
+ type.get_size_expr ().get_locus ());
+ }
+ else
+ {
+ HirId size_id = type.get_size_expr ().get_mappings ().get_hirid ();
+ unify_site (size_id, TyTy::TyWithLocation (expected_ty),
+ TyTy::TyWithLocation (capacity_type,
+ type.get_size_expr ().get_locus ()),
+ type.get_size_expr ().get_locus ());
+
+ auto ctx = Compile::Context::get ();
+ tree capacity_expr = Compile::HIRCompileBase::query_compile_const_expr (
+ ctx, capacity_type, type.get_size_expr ());
+
+ const_type = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "",
+ expected_ty, capacity_expr, {},
+ type.get_size_expr ().get_locus (),
+ size_id, size_id);
+ }
- 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 ()));
+ const_type, TyTy::TyVar (element_type->get_ref ()));
}
void
if (param.has_type ())
TypeCheckType::Resolve (param.get_type ());
- resolved
- = new TyTy::ParamType (param.get_type_representation ().as_string (),
- param.get_locus (),
- param.get_mappings ().get_hirid (), param, {});
+ resolved = new TyTy::ParamType (param.get_type_representation ().as_string (),
+ param.get_locus (),
+ param.get_mappings ().get_hirid (), {});
if (resolve_trait_bounds)
apply_trait_bounds (param, resolved);
HirId implicit_id = mappings.get_next_hir_id ();
TyTy::ParamType *p
= new TyTy::ParamType (param.get_type_representation ().as_string (),
- param.get_locus (), implicit_id, param,
+ param.get_locus (), implicit_id,
{} /*empty specified bounds*/);
context->insert_implicit_type (implicit_id, p);
HIR::TraitFunctionDecl &function = fn.get_decl ();
if (function.has_generics ())
{
- TypeCheckBase::ResolveGenericParams (function.get_generic_params (),
+ TypeCheckBase::ResolveGenericParams (HIR::Item::ItemKind::Function,
+ fn.get_locus (),
+ function.get_generic_params (),
substitutions, false /*is_foreign*/,
ABI::RUST);
}
#include "rust-tyty-subst.h"
+#include "rust-hir-generic-param.h"
#include "rust-system.h"
#include "rust-tyty.h"
#include "rust-hir-type-check.h"
#include "rust-substitution-mapper.h"
#include "rust-hir-type-check-type.h"
+#include "rust-hir-type-check-expr.h"
+#include "rust-compile-base.h"
#include "rust-type-util.h"
+#include "tree.h"
namespace Rust {
namespace TyTy {
SubstitutionParamMapping::SubstitutionParamMapping (HIR::GenericParam &generic,
- ParamType *param)
+ BaseGeneric *param)
: generic (generic), param (param)
{}
Identifier
SubstitutionParamMapping::get_type_representation () const
{
- rust_assert (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE);
- const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
- return type_param.get_type_representation ();
+ return param->get_symbol ();
}
location_t
bool
SubstitutionParamMapping::param_has_default_ty () const
{
- if (generic.get_kind () != HIR::GenericParam::GenericKind::TYPE)
- return false;
+ if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
+ {
+ const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
+ return type_param.has_type ();
+ }
- const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
- return type_param.has_type ();
+ rust_assert (generic.get_kind () == HIR::GenericParam::GenericKind::CONST);
+ const auto &const_param
+ = static_cast<const HIR::ConstGenericParam &> (generic);
+ return const_param.has_default_expression ();
}
BaseType *
SubstitutionParamMapping::get_default_ty () const
{
- rust_assert (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE);
+ if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
+ {
+ const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
+ TyVar var (type_param.get_type_mappings ().get_hirid ());
+ return var.get_tyty ();
+ }
- const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
- TyVar var (type_param.get_type_mappings ().get_hirid ());
+ rust_assert (generic.get_kind () == HIR::GenericParam::GenericKind::CONST);
+ const auto &const_param
+ = static_cast<const HIR::ConstGenericParam &> (generic);
+ rust_assert (const_param.has_default_expression ());
+
+ const auto &expr = const_param.get_default_expression ();
+ TyVar var (expr.get_mappings ().get_hirid ());
return var.get_tyty ();
}
// delete param;
param = static_cast<ParamType *> (type.clone ());
}
- else
+ else if (param->get_kind () == TypeKind::PARAM)
{
+ auto &p = *static_cast<TyTy::ParamType *> (param);
+
// check the substitution is compatible with bounds
rust_debug_loc (locus,
"fill_param_ty bounds_compatible: param %s type %s",
param->get_name ().c_str (), type.get_name ().c_str ());
- if (needs_bounds_check && !param->is_implicit_self_trait ())
+ if (needs_bounds_check && !p.is_implicit_self_trait ())
{
if (!param->bounds_compatible (type, locus, true))
return false;
bound.handle_substitions (subst_mappings);
param->set_ty_ref (type.get_ref ());
- subst_mappings.on_param_subst (*param, arg);
+ subst_mappings.on_param_subst (p, arg);
}
return true;
return SubstitutionArgumentMappings::error ();
}
- if (args.get_type_args ().size () + offs < min_required_substitutions ())
+ size_t total_arguments
+ = args.get_type_args ().size () + args.get_const_args ().size () + offs;
+ if (total_arguments < min_required_substitutions ())
{
rich_location r (line_table, args.get_locus ());
if (!substitutions.empty ())
return SubstitutionArgumentMappings::error ();
}
}
+ else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
+ {
+ if (!resolved->is<ConstType> ())
+ {
+ rich_location r (line_table, arg->get_locus ());
+ r.add_fixit_remove (arg->get_locus ());
+ rust_error_at (r, ErrorCode::E0747,
+ "type provided when a constant was expected");
+ return SubstitutionArgumentMappings::error ();
+ }
+ }
SubstitutionArg subst_arg (¶m_mapping, resolved);
offs++;
mappings.push_back (std::move (subst_arg));
}
+ for (auto &arg : args.get_const_args ())
+ {
+ auto &expr = *arg.get_expression ().get ();
+ BaseType *expr_type = Resolver::TypeCheckExpr::Resolve (expr);
+ if (expr_type == nullptr || expr_type->is<ErrorType> ())
+ return SubstitutionArgumentMappings::error ();
+
+ // validate this param is really a const generic
+ const auto ¶m_mapping = substitutions.at (offs);
+ const auto &generic = param_mapping.get_generic_param ();
+ if (generic.get_kind () != HIR::GenericParam::GenericKind::CONST)
+ {
+ rich_location r (line_table, arg.get_locus ());
+ r.add_fixit_remove (expr.get_locus ());
+ rust_error_at (r, "invalid position for a const generic argument");
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ // get the const generic specified type
+ const auto base_generic = param_mapping.get_param_ty ();
+ rust_assert (base_generic->is<ConstType> ());
+ const auto const_param
+ = static_cast<const TyTy::ConstType *> (base_generic);
+ auto specified_type = const_param->get_ty ();
+
+ // validate this const generic is of the correct type
+ auto coereced_type
+ = Resolver::coercion_site (expr.get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (specified_type),
+ TyTy::TyWithLocation (expr_type,
+ expr.get_locus ()),
+ arg.get_locus ());
+ if (coereced_type->is<ErrorType> ())
+ return SubstitutionArgumentMappings::error ();
+
+ // const fold it
+ auto ctx = Compile::Context::get ();
+ tree folded
+ = Compile::HIRCompileBase::query_compile_const_expr (ctx, coereced_type,
+ expr);
+
+ if (folded == error_mark_node)
+ return SubstitutionArgumentMappings::error ();
+
+ // create const type
+ auto const_value
+ = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "",
+ coereced_type, folded, {}, expr.get_locus (),
+ expr.get_mappings ().get_hirid (),
+ expr.get_mappings ().get_hirid (), {});
+
+ SubstitutionArg subst_arg (¶m_mapping, const_value);
+ offs++;
+ mappings.push_back (std::move (subst_arg));
+ }
+
// we must need to fill out defaults
size_t left_over
= num_required_substitutions () - min_required_substitutions ();
std::map<std::string, BaseType *> argument_mappings;
for (auto &p : get_substs ())
{
+ rust_debug_loc (locus, "XXXXXXXXXXXXXXXXXXXXXX 1: [%s]",
+ p.need_substitution () ? "true" : "false");
+ p.get_param_ty ()->debug ();
+
if (p.needs_substitution ())
{
+ const HIR::GenericParam &generic = p.get_generic_param ();
const std::string &symbol = p.get_param_ty ()->get_symbol ();
auto it = argument_mappings.find (symbol);
bool have_mapping = it != argument_mappings.end ();
+ rust_debug_loc (locus, "XXXXXXXXXXXXXXX 2: [%s] [%s]",
+ have_mapping ? "true" : "false", symbol.c_str ());
+
if (have_mapping)
{
args.push_back (SubstitutionArg (&p, it->second));
}
- else
+ else if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
{
TyVar infer_var = TyVar::get_implicit_infer_var (locus);
args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
argument_mappings[symbol] = infer_var.get_tyty ();
}
+ else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
+ {
+ const auto const_param = p.get_param_ty ();
+ rust_assert (const_param->is<TyTy::ConstType> ());
+ const auto &const_type
+ = *static_cast<const TyTy::ConstType *> (const_param);
+
+ TyVar infer_var
+ = TyVar::get_implicit_const_infer_var (const_type, locus);
+ args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
+ argument_mappings[symbol] = infer_var.get_tyty ();
+ }
}
else
{
class SubstitutionParamMapping
{
public:
- SubstitutionParamMapping (HIR::GenericParam &generic, ParamType *param);
+ SubstitutionParamMapping (HIR::GenericParam &generic, BaseGeneric *param);
SubstitutionParamMapping (const SubstitutionParamMapping &other);
private:
HIR::GenericParam &generic;
- ParamType *param;
+ BaseGeneric *param;
};
/**
// <http://www.gnu.org/licenses/>.
#include "rust-hir-type-check.h"
+#include "rust-mapping-common.h"
+#include "rust-system.h"
#include "rust-tyty.h"
namespace Rust {
auto &mappings = Analysis::Mappings::get ();
auto context = Resolver::TypeCheckContext::get ();
- InferType *infer = new InferType (mappings.get_next_hir_id (),
- InferType::InferTypeKind::GENERAL,
- InferType::TypeHint::Default (), locus);
- context->insert_type (Analysis::NodeMapping (mappings.get_current_crate (),
- UNKNOWN_NODEID,
- infer->get_ref (),
- UNKNOWN_LOCAL_DEFID),
- infer);
+ HirId next = mappings.get_next_hir_id ();
+ auto infer = new InferType (next, InferType::InferTypeKind::GENERAL,
+ InferType::TypeHint::Default (), locus);
+
+ context->insert_implicit_type (infer->get_ref (), infer);
+ mappings.insert_location (infer->get_ref (), locus);
+
+ return TyVar (infer->get_ref ());
+}
+
+TyVar
+TyVar::get_implicit_const_infer_var (const ConstType &const_type,
+ location_t locus)
+{
+ auto &mappings = Analysis::Mappings::get ();
+ auto context = Resolver::TypeCheckContext::get ();
+
+ HirId next = mappings.get_next_hir_id ();
+ auto infer
+ = new ConstType (ConstType::ConstKind::Infer, const_type.get_symbol (),
+ const_type.get_ty (), error_mark_node,
+ const_type.get_specified_bounds (), locus, next, next, {});
+
+ context->insert_implicit_type (infer->get_ref (), infer);
mappings.insert_location (infer->get_ref (), locus);
return TyVar (infer->get_ref ());
namespace TyTy {
class BaseType;
+class ConstType;
// this is a placeholder for types that can change like inference variables
class TyVar
static TyVar get_implicit_infer_var (location_t locus);
+ static TyVar get_implicit_const_infer_var (const TyTy::ConstType &const_type,
+ location_t locus);
+
static TyVar subst_covariant_var (TyTy::BaseType *orig,
TyTy::BaseType *subst);
#include "rust-tyty.h"
#include "optional.h"
+#include "rust-tyty-subst.h"
#include "rust-tyty-visitor.h"
#include "rust-hir-map.h"
#include "rust-location.h"
#include "rust-type-util.h"
#include "rust-hir-type-bounds.h"
#include "print-tree.h"
+#include "tree-pretty-print.h"
#include "options.h"
#include "rust-system.h"
#include "tree.h"
+#include <string>
namespace Rust {
namespace TyTy {
}
else if (auto arr = x->try_as<const ArrayType> ())
{
- return arr->get_element_type ()->is_concrete ();
+ return arr->get_element_type ()->is_concrete ()
+ && arr->get_capacity ()->is_concrete ();
}
else if (auto slice = x->try_as<const SliceType> ())
{
return false;
return closure->get_result_type ().is_concrete ();
}
+ else if (auto const_type = x->try_as<const ConstType> ())
+ {
+ return const_type->get_value () != error_mark_node;
+ }
else if (x->is<InferType> () || x->is<BoolType> () || x->is<CharType> ()
|| x->is<IntType> () || x->is<UintType> () || x->is<FloatType> ()
|| x->is<USizeType> () || x->is<ISizeType> () || x->is<NeverType> ()
std::string
ArrayType::as_string () const
{
- 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 + "]";
+ return "[" + get_element_type ()->as_string () + "; " + capacity->as_string ()
+ + "]";
}
bool
BaseType *concrete = Resolver::SubstMapperInternal::Resolve (base, mappings);
ref->element_type = TyVar::subst_covariant_var (base, concrete);
+ // handle capacity type
+ auto cap = ref->get_capacity ();
+ BaseType *concrete_cap
+ = Resolver::SubstMapperInternal::Resolve (cap, mappings);
+ rust_assert (concrete_cap->get_kind () == TyTy::TypeKind::CONST);
+ ref->capacity = static_cast<TyTy::ConstType *> (concrete_cap);
+
return ref;
}
// PARAM Type
ParamType::ParamType (std::string symbol, location_t locus, HirId ref,
- HIR::GenericParam ¶m,
std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs)
: BaseGeneric (ref, ref, KIND,
{Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
locus},
specified_bounds, refs),
- is_trait_self (false), symbol (symbol), param (param)
+ is_trait_self (false), symbol (symbol)
{}
ParamType::ParamType (bool is_trait_self, std::string symbol, location_t locus,
- HirId ref, HirId ty_ref, HIR::GenericParam ¶m,
+ HirId ref, HirId ty_ref,
std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs)
: BaseGeneric (ref, ty_ref, KIND,
{Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
locus},
specified_bounds, refs),
- is_trait_self (is_trait_self), symbol (symbol), param (param)
+ is_trait_self (is_trait_self), symbol (symbol)
{}
-HIR::GenericParam &
-ParamType::get_generic_param ()
-{
- return param;
-}
-
bool
ParamType::can_resolve () const
{
ParamType::clone () const
{
return new ParamType (is_trait_self, get_symbol (), ident.locus, get_ref (),
- get_ty_ref (), param, get_specified_bounds (),
+ get_ty_ref (), get_specified_bounds (),
get_combined_refs ());
}
tree value,
std::vector<TypeBoundPredicate> specified_bounds,
location_t locus, HirId ref, HirId ty_ref,
- HIR::GenericParam ¶m, std::set<HirId> refs)
+ std::set<HirId> refs)
: BaseGeneric (ref, ty_ref, KIND,
- {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
+ {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID,
+ symbol.empty () ? "<n/a>"
+ : symbol),
locus},
specified_bounds, refs),
- const_kind (kind), ty (ty), value (value), symbol (symbol), param (param)
+ const_kind (kind), ty (ty), value (value), symbol (symbol)
{}
void
vis.visit (*this);
}
+void
+ConstType::set_value (tree v)
+{
+ value = v;
+ const_kind = ConstType::ConstKind::Value;
+}
+
std::string
ConstType::as_string () const
{
ConstType::clone () const
{
return new ConstType (const_kind, symbol, ty, value, get_specified_bounds (),
- ident.locus, ref, ty_ref, param, get_combined_refs ());
+ ident.locus, ref, ty_ref, get_combined_refs ());
}
std::string
return symbol;
}
-HIR::GenericParam &
-ConstType::get_generic_param ()
-{
- return param;
-}
-
bool
ConstType::can_resolve () const
{
return nullptr;
}
+static std::string
+generate_tree_str (tree value)
+{
+ char *buf = nullptr;
+ size_t size = 0;
+
+ FILE *stream = open_memstream (&buf, &size);
+ if (!stream)
+ return "<error>";
+
+ print_generic_stmt (stream, value, TDF_NONE);
+ fclose (stream);
+
+ std::string result = (buf ? std::string (buf, size) : "<error>");
+ free (buf);
+
+ if (!result.empty () && result.back () == '\n')
+ result.pop_back ();
+
+ return result;
+}
+
std::string
ConstType::get_name () const
{
- return "CONST_TYPE";
+ if (value == error_mark_node)
+ {
+ switch (get_const_kind ())
+ {
+ case Rust::TyTy::ConstType::Decl:
+ return "ConstType:<" + get_ty ()->get_name () + " " + get_symbol ()
+ + ">";
+
+ case Rust::TyTy::ConstType::Infer:
+ return "ConstType:<" + get_ty ()->get_name () + " ?" + ">";
+
+ default:
+ return "ConstType:<" + get_ty ()->get_name () + " - <error>" + ">";
+ }
+ }
+
+ return generate_tree_str (value);
}
bool
ConstType *
ConstType::handle_substitions (SubstitutionArgumentMappings &mappings)
{
- rust_unreachable ();
- return nullptr;
+ SubstitutionArg arg = SubstitutionArg::error ();
+ bool found = mappings.get_argument_for_symbol (this, &arg);
+ if (found && !arg.is_error ())
+ {
+ TyTy::BaseType *subst = arg.get_tyty ();
+ rust_assert (subst->is<TyTy::ConstType> ());
+ return static_cast<TyTy::ConstType *> (subst);
+ }
+
+ return this;
}
// OpaqueType
#ifndef RUST_TYTY
#define RUST_TYTY
+#include "optional.h"
#include "rust-hir-map.h"
#include "rust-common.h"
#include "rust-identifier.h"
public:
virtual std::string get_symbol () const = 0;
- virtual HIR::GenericParam &get_generic_param () = 0;
-
virtual bool can_resolve () const = 0;
virtual BaseType *resolve () const = 0;
static constexpr auto KIND = TypeKind::PARAM;
ParamType (std::string symbol, location_t locus, HirId ref,
- HIR::GenericParam ¶m,
std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs = std::set<HirId> ());
ParamType (bool is_trait_self, std::string symbol, location_t locus,
- HirId ref, HirId ty_ref, HIR::GenericParam ¶m,
+ HirId ref, HirId ty_ref,
std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs = std::set<HirId> ());
std::string get_symbol () const override final;
- HIR::GenericParam &get_generic_param () override final;
-
bool can_resolve () const override final;
BaseType *resolve () const override final;
private:
bool is_trait_self;
std::string symbol;
- HIR::GenericParam ¶m;
};
class ConstType : public BaseGeneric
ConstType (ConstKind kind, std::string symbol, TyTy::BaseType *ty, tree value,
std::vector<TypeBoundPredicate> specified_bounds, location_t locus,
- HirId ref, HirId ty_ref, HIR::GenericParam ¶m,
+ HirId ref, HirId ty_ref,
std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
TyTy::BaseType *get_ty () const { return ty; }
tree get_value () const { return value; }
+ void set_value (tree value);
+
std::string as_string () const override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
std::string get_symbol () const override final;
- HIR::GenericParam &get_generic_param () override final;
-
bool can_resolve () const override final;
BaseType *resolve () const override final;
TyTy::BaseType *ty;
tree value;
std::string symbol;
- HIR::GenericParam ¶m;
};
class OpaqueType : public BaseType
public:
static constexpr auto KIND = TypeKind::ARRAY;
- ArrayType (HirId ref, location_t locus, tree capacity, TyVar base,
+ ArrayType (HirId ref, location_t locus, ConstType *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 (capacity)
{}
- ArrayType (HirId ref, HirId ty_ref, location_t locus, tree capacity,
+ ArrayType (HirId ref, HirId ty_ref, location_t locus, ConstType *capacity,
TyVar base, std::set<HirId> refs = std::set<HirId> ())
: BaseType (ref, ty_ref, TypeKind::ARRAY,
{Resolver::CanonicalPath::create_empty (), locus}, refs),
BaseType *clone () const final override;
- tree get_capacity () const { return capacity; }
+ ConstType *get_capacity () const { return capacity; }
ArrayType *handle_substitions (SubstitutionArgumentMappings &mappings);
private:
TyVar element_type;
- tree capacity;
+ ConstType *capacity;
};
class SliceType : public BaseType
// <http://www.gnu.org/licenses/>.
#include "rust-unify.h"
+#include "fold-const.h"
#include "rust-tyty.h"
#include "tree.h"
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);
+ bool save_emit_error = emit_error;
+ emit_error = false;
+ TyTy::BaseType *capacity_unify
+ = resolve_subtype (TyTy::TyWithLocation (ltype->get_capacity ()),
+ TyTy::TyWithLocation (type.get_capacity ()));
+ emit_error = save_emit_error;
- auto lc = wi::to_wide (lcap).to_uhwi ();
- auto rc = wi::to_wide (rcap).to_uhwi ();
- if (lc != rc)
+ if (capacity_unify->get_kind () != TyTy::TypeKind::CONST)
return new TyTy::ErrorType (0);
+ TyTy::ConstType *capacity_type_unify
+ = static_cast<TyTy::ConstType *> (capacity_unify);
return new TyTy::ArrayType (type.get_ref (), type.get_ty_ref (),
type.get_ident ().locus,
- type.get_capacity (),
+ capacity_type_unify,
TyTy::TyVar (element_unify->get_ref ()));
}
break;
if (rtype->get_kind () != TyTy::TypeKind::CONST)
return new TyTy::ErrorType (0);
- // TODO
- // TyTy::ConstType &lhs = *ltype;
- // TyTy::ConstType &rhs = *static_cast<TyTy::ConstType *> (rtype);
+ TyTy::ConstType &lhs = *ltype;
+ TyTy::ConstType &rhs = *static_cast<TyTy::ConstType *> (rtype);
+
+ auto res = resolve_subtype (TyTy::TyWithLocation (lhs.get_ty ()),
+ TyTy::TyWithLocation (rhs.get_ty ()));
+ if (res->get_kind () == TyTy::TypeKind::ERROR)
+ return new TyTy::ErrorType (0);
+
+ tree lv = lhs.get_value ();
+ tree rv = rhs.get_value ();
+
+ if (error_operand_p (lv) && error_operand_p (rv))
+ {
+ // this is only allowed for some silly senarios like:
+ // gcc/testsuite/rust/compile/issue-const_generics_5.rs
+ if (lhs.get_const_kind () == rhs.get_const_kind ())
+ {
+ return new TyTy::ConstType (lhs.get_const_kind (), lhs.get_symbol (),
+ res, error_mark_node,
+ lhs.get_specified_bounds (),
+ lhs.get_locus (), lhs.get_ref (),
+ lhs.get_ty_ref (),
+ lhs.get_combined_refs ());
+ }
+
+ return new TyTy::ErrorType (0);
+ }
+
+ bool equal = operand_equal_p (lv, rv, 0);
+ if (equal)
+ {
+ return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value,
+ lhs.get_symbol (), res, lv,
+ lhs.get_specified_bounds (), lhs.get_locus (),
+ lhs.get_ref (), lhs.get_ty_ref (),
+ lhs.get_combined_refs ());
+ }
+
+ if (lhs.get_const_kind () == TyTy::ConstType::Infer && !error_operand_p (rv))
+ {
+ lhs.set_value (rv);
+ return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value,
+ lhs.get_symbol (), res, rv,
+ lhs.get_specified_bounds (), lhs.get_locus (),
+ lhs.get_ref (), lhs.get_ty_ref (),
+ lhs.get_combined_refs ());
+ }
+ else if (rhs.get_const_kind () == TyTy::ConstType::Infer
+ && !error_operand_p (lv))
+ {
+ rhs.set_value (lv);
+ return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value,
+ rhs.get_symbol (), res, lv,
+ rhs.get_specified_bounds (), rhs.get_locus (),
+ rhs.get_ref (), rhs.get_ty_ref (),
+ rhs.get_combined_refs ());
+ }
return new TyTy::ErrorType (0);
}
--- /dev/null
+#[lang = "sized"]
+trait Sized {}
+
+const M: usize = 4;
+
+struct Foo<T, const N: usize = 1> {
+ value: [T; N],
+}
+
+fn main() {
+ let foo = Foo::<i32> { value: [15] };
+ let foo = Foo::<i32, 2> { value: [15, 13] };
+ let foo: Foo<i32, 2> = Foo { value: [15, 13] };
+ let foo: Foo<i32, 2> = Foo::<i32, 2> { value: [15, 13] };
+ let foo: Foo<i32, { 1 + 1 }> = Foo { value: [15, 13] };
+ let foo = Foo::<i32, { 1 + 1 }> { value: [15, 13] };
+ let foo: Foo<i32, { 1 + 1 }> = Foo::<i32, { 1 + 1 }> { value: [15, 13] };
+ let foo: Foo<i32, M> = Foo::<i32, 4> {
+ value: [15, 13, 11, 9],
+ };
+
+ let invalid_foo: Foo<i32, { 1 + 1 }> = Foo::<i32, 3> { value: [15, 13] };
+ // { dg-error {mismatched types, expected ..T=i32; 3.. but got ...integer.; 2.. .E0308.} "" { target *-*-* } .-1 }
+ // { dg-error {mismatched types, expected ..T=i32; 2.. but got ..T=i32; 3.. .E0308.} "" { target *-*-* } .-2 }
+
+ let invalid_foo: Foo<i32, { 1 + 1 }> = Foo::<i32, M> { value: [15, 13] };
+ // { dg-error {mismatched types, expected ..T=i32; 4.. but got ...integer.; 2.. .E0308.} "" { target *-*-* } .-1 }
+ // { dg-error {mismatched types, expected ..T=i32; 2.. but got ..T=i32; 4.. .E0308.} "" { target *-*-* } .-2 }
+
+ let invalid_foo: Foo<i32> = Foo::<i32, 2> { value: [15, 13] };
+ // { dg-error {mismatched types, expected ..T=i32; 1.. but got ..T=i32; 2.. .E0308.} "" { target *-*-* } .-1 }
+}
--- /dev/null
+// { dg-options "-w" }
+
+#[lang = "sized"]
+trait Sized {}
+
+struct Matrix<T, const ROWS: usize, const COLS: usize> {
+ data: [[T; COLS]; ROWS],
+}
+
+fn main() {
+ let _: Matrix<u8, 2, 3> = Matrix {
+ data: [[1, 2, 3], [4, 5, 6]],
+ };
+}
--- /dev/null
+// { dg-options "-w" }
+
+#[lang = "sized"]
+trait Sized {}
+
+const BASE: usize = 2;
+
+struct Foo<T, const N: usize> {
+ data: [T; N],
+}
+
+fn main() {
+ let _ = Foo::<u8, { BASE + 1 * 2 }> { data: [0; 4] };
+}
--- /dev/null
+#[lang = "sized"]
+trait Sized {}
+
+struct Foo<T, const N: usize> {
+ value: [T; N],
+}
+
+fn main() {
+ let foo: Foo<_, _>;
+ // { dg-error {type provided when a constant was expected .E0747.} "" { target *-*-* } .-1 }
+}
--- /dev/null
+#[lang = "sized"]
+trait Sized {}
+
+type MyLen = usize;
+struct Foo<T, const N: usize> {
+ data: [T; N],
+}
+
+fn main() {
+ let _ = Foo::<u8, MyLen> { data: [1, 2, 3] };
+ // { dg-error {type provided when a constant was expected .E0747.} "" { target *-*-* } .-1 }
+ // { dg-error {expected an ADT type for constructor} "" { target *-*-* } .-2 }
+}
--- /dev/null
+#[lang = "sized"]
+trait Sized {}
+
+enum Foo<const N: usize> {
+ A([u8; N]),
+}
+
+union Bar<const N: usize> {
+ a: [i32; N],
+ b: [u8; N],
+}
+
+fn main() {
+ let _ = Foo::<4>::A([1, 2, 3, 4]);
+ let _ = Bar::<4> { a: [0; 4] };
+}
--- /dev/null
+#[lang = "sized"]
+trait Sized {}
+
+struct Foo<T = u8, const N: usize = 4> {
+ data: [T; N], // { dg-warning "field is never read: .data." }
+}
+
+fn main() {
+ let _x = Foo { data: [1, 2, 3, 4] };
+}
-// { dg-additional-options "-w -frust-compile-until=typecheck" }
-
#[lang = "sized"]
trait Sized {}
const M: usize = 4;
struct Foo<T, const N: usize = 1> {
- value: [T; N],
+ value: [T; N], // { dg-warning "field is never read: .value." }
}
fn main() {
- let foo = Foo::<i32> { value: [15] };
- let foo = Foo::<i32, 2> { value: [15, 13] };
- let foo: Foo<i32, 2> = Foo { value: [15, 13] };
- let foo: Foo<i32, 2> = Foo::<i32, 2> { value: [15, 13] };
- let foo: Foo<i32, { 1 + 1 }> = Foo { value: [15, 13] };
- let foo = Foo::<i32, { 1 + 1 }> { value: [15, 13] };
- let foo: Foo<i32, { 1 + 1 }> = Foo::<i32, { 1 + 1 }> { value: [15, 13] };
- let foo: Foo<i32, M> = Foo::<i32, 4> {
+ let _foo = Foo::<i32> { value: [15] };
+ let _foo = Foo::<i32, 2> { value: [15, 13] };
+ let _foo: Foo<i32, 2> = Foo { value: [15, 13] };
+ let _foo: Foo<i32, 2> = Foo::<i32, 2> { value: [15, 13] };
+ let _foo: Foo<i32, { 1 + 1 }> = Foo { value: [15, 13] };
+ let _foo = Foo::<i32, { 1 + 1 }> { value: [15, 13] };
+ let _foo: Foo<i32, { 1 + 1 }> = Foo::<i32, { 1 + 1 }> { value: [15, 13] };
+ let _foo: Foo<i32, M> = Foo::<i32, 4> {
value: [15, 13, 11, 9],
};
-
- // FIXME: Add proper const typecheck errors here
- let invalid_foo: Foo<i32, { 1 + 1 }> = Foo::<i32, 3> { value: [15, 13] };
- let invalid_foo: Foo<i32, { 1 + 1 }> = Foo::<i32, M> { value: [15, 13] };
- let invalid_foo: Foo<i32> = Foo::<i32, 2> { value: [15, 13] };
}
-// { dg-options "-w" }
struct Foo<const N: usize = { 14 }>;
const M: usize = 15;
let _: Foo<15> = Foo;
let _: Foo<{ M }> = Foo;
let _: Foo<M> = Foo;
- // let _: Foo<N> = Foo; this causes an ICE we need to do const generics
+ let _: Foo<N> = Foo;
+ // { dg-error {type provided when a constant was expected .E0747.} "" { target *-*-* } .-1 }
}
trait Fooable<const N: i32 = 15> {}
union Bidoulepe<const N: i32 = 15> {
- // { dg-error "default values for const generic parameters are not allowed in .union. items" "" {target *-*-* } .-1 }
int: i32,
float: f32,
}
-fn const_default<const N: i32 = 15>() {} // { dg-error "default values for const generic parameters are not allowed in .function. items" }
+fn const_default<const N: i32 = 15>() {} // { dg-error "default values for const generic parameters are not allowed here" }
// Note - missing generic parameter - needs name resolution on const generics
-impl<const N: i32 = 15> Bidule {} // { dg-error "default values for const generic parameters are not allowed in .impl. items" }
+impl<const N: i32 = 15> Bidule {}
+// { dg-error "default values for const generic parameters are not allowed here" "" {target *-*-* } .-1 }
+// { dg-error "unconstrained type parameter" "" {target *-*-* } .-2 }
--- /dev/null
+// { dg-options "-w" }
+
+#[lang = "sized"]
+trait Sized {}
+
+struct ArrayWrapper<T, const N: usize> {
+ data: [T; N],
+}
+
+pub fn test() -> [u8; 4] {
+ let a = ArrayWrapper { data: [1u8; 4] };
+ a.data
+}