aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/ast/rust-ast.h13
-rw-r--r--gcc/rust/ast/rust-item.h13
-rw-r--r--gcc/rust/ast/rust-path.h2
-rw-r--r--gcc/rust/backend/rust-compile-context.h12
-rw-r--r--gcc/rust/backend/rust-compile-expr.h14
-rw-r--r--gcc/rust/backend/rust-compile-implitem.h6
-rw-r--r--gcc/rust/backend/rust-compile-item.h28
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc10
-rw-r--r--gcc/rust/backend/rust-compile-tyty.h4
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h22
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.h25
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.h70
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc46
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h17
-rw-r--r--gcc/rust/hir/tree/rust-hir-path.h26
-rw-r--r--gcc/rust/hir/tree/rust-hir.h23
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h41
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.h16
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.h93
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.cc98
-rw-r--r--gcc/rust/rust-gcc.cc23
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct-field.h14
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.h36
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h116
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc51
-rw-r--r--gcc/rust/typecheck/rust-tycheck-dump.h20
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.h4
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h95
-rw-r--r--gcc/rust/typecheck/rust-tyty-visitor.h2
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc253
-rw-r--r--gcc/rust/typecheck/rust-tyty.h226
-rw-r--r--gcc/testsuite/rust.test/compilable/generics1.rs41
32 files changed, 1169 insertions, 291 deletions
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 7316865..7d3a075 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1209,9 +1209,18 @@ public:
virtual void accept_vis (ASTVisitor &vis) = 0;
+ virtual Location get_locus_slow () const = 0;
+
+ NodeId get_node_id () { return node_id; }
+
protected:
+ GenericParam () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}
+ GenericParam (NodeId node_id) : node_id (node_id) {}
+
// Clone function implementation as pure virtual method
virtual GenericParam *clone_generic_param_impl () const = 0;
+
+ NodeId node_id;
};
// A lifetime generic parameter (as opposed to a type generic parameter)
@@ -1251,6 +1260,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ Location get_locus () const { return locus; }
+
+ Location get_locus_slow () const override final { return get_locus (); }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index a6f5398..35d1827 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -66,6 +66,8 @@ class TypeParam : public GenericParam
Location locus;
public:
+ Identifier get_type_representation () const { return type_representation; }
+
// Returns whether the type of the type param has been specified.
bool has_type () const { return type != nullptr; }
@@ -80,7 +82,8 @@ public:
= std::vector<std::unique_ptr<TypeParamBound> > (),
std::unique_ptr<Type> type = nullptr,
Attribute outer_attr = Attribute::create_empty ())
- : outer_attr (std::move (outer_attr)),
+ : GenericParam (Analysis::Mappings::get ()->get_next_node_id ()),
+ outer_attr (std::move (outer_attr)),
type_representation (std::move (type_representation)),
type_param_bounds (std::move (type_param_bounds)),
type (std::move (type)), locus (locus)
@@ -88,7 +91,7 @@ public:
// Copy constructor uses clone
TypeParam (TypeParam const &other)
- : outer_attr (other.outer_attr),
+ : GenericParam (other.node_id), outer_attr (other.outer_attr),
type_representation (other.type_representation), locus (other.locus)
{
// guard to prevent null pointer dereference
@@ -106,6 +109,7 @@ public:
type_representation = other.type_representation;
outer_attr = other.outer_attr;
locus = other.locus;
+ node_id = other.node_id;
// guard to prevent null pointer dereference
if (other.type != nullptr)
@@ -128,6 +132,8 @@ public:
Location get_locus () const { return locus; }
+ Location get_locus_slow () const override final { return get_locus (); }
+
void accept_vis (ASTVisitor &vis) override;
// TODO: is this better? Or is a "vis_block" better?
@@ -1756,6 +1762,8 @@ public:
Location get_locus () const { return locus; }
+ Location get_locus_slow () const final { return get_locus (); };
+
// Invalid if name is empty, so base stripping on that.
void mark_for_strip () override { struct_name = ""; }
bool is_marked_for_strip () const override { return struct_name.empty (); }
@@ -1949,7 +1957,6 @@ public:
std::move (outer_attrs)),
is_unit (true)
{}
- // TODO: can a unit struct have generic fields? assuming yes for now.
/* Returns whether the struct is a unit struct - struct defined without
* fields. This is important because it also means an implicit constant of its
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index d6f3c42..81fce57 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -196,6 +196,8 @@ public:
// TODO: is this better? Or is a "vis_pattern" better?
std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; }
+
+ std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; };
};
/* A segment of a path in expression, including an identifier aspect and maybe
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index c5ae3bb..b191554 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -274,7 +274,15 @@ public:
void visit (TyTy::InferType &) override { gcc_unreachable (); }
- void visit (TyTy::StructFieldType &) override { gcc_unreachable (); }
+ void visit (TyTy::ParamType &param) override
+ {
+ rust_assert (param.get_ref () != param.get_ty_ref ());
+
+ TyTy::BaseType *lookup = nullptr;
+ bool ok = ctx->get_tyctx ()->lookup_type (param.get_ty_ref (), &lookup);
+ rust_assert (ok);
+ lookup->accept_vis (*this);
+ }
void visit (TyTy::FnType &type) override
{
@@ -338,7 +346,7 @@ public:
Btype *named_struct
= ctx->get_backend ()->named_type (type.get_name (), struct_type_record,
ctx->get_mappings ()->lookup_location (
- type.get_ty_ref ()));
+ type.get_ref ()));
ctx->push_type (named_struct);
ctx->insert_compiled_type (type.get_ty_ref (), named_struct);
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index 00625df..95a6744 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -539,8 +539,16 @@ public:
void visit (HIR::StructExprStructFields &struct_expr)
{
- Btype *type
- = ResolvePathType::Compile (&struct_expr.get_struct_name (), ctx);
+ TyTy::BaseType *tyty = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ struct_expr.get_mappings ().get_hirid (), &tyty))
+ {
+ rust_error_at (struct_expr.get_locus (), "unknown type");
+ return;
+ }
+
+ Btype *type = TyTyResolveCompile::compile (ctx, tyty);
+ rust_assert (type != nullptr);
// this assumes all fields are in order from type resolution and if a base
// struct was specified those fields are filed via accesors
@@ -573,8 +581,8 @@ public:
return;
}
rust_assert (receiver->get_kind () == TyTy::TypeKind::ADT);
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver);
- TyTy::ADTType *adt = (TyTy::ADTType *) receiver;
size_t index = 0;
adt->get_field (expr.get_field_name (), &index);
diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h
index 3da269a..8018367 100644
--- a/gcc/rust/backend/rust-compile-implitem.h
+++ b/gcc/rust/backend/rust-compile-implitem.h
@@ -50,7 +50,7 @@ public:
::Btype *type = TyTyResolveCompile::compile (ctx, resolved_type);
Bexpression *value = CompileExpr::Compile (constant.get_expr (), ctx);
- std::string ident = self->as_string () + "::" + constant.get_identifier ();
+ std::string ident = self->get_name () + "::" + constant.get_identifier ();
Bexpression *const_expr = ctx->get_backend ()->named_constant_expression (
type, constant.get_identifier (), value, constant.get_locus ());
@@ -95,7 +95,7 @@ public:
unsigned int flags = 0;
std::string fn_identifier
- = self->as_string () + "::" + function.function_name;
+ = self->get_name () + "::" + function.function_name;
// if its the main fn or pub visibility mark its as DECL_PUBLIC
// please see https://github.com/Rust-GCC/gccrs/pull/137
@@ -259,7 +259,7 @@ public:
unsigned int flags = 0;
std::string fn_identifier
- = self->as_string () + "::" + method.get_method_name ();
+ = self->get_name () + "::" + method.get_method_name ();
// if its the main fn or pub visibility mark its as DECL_PUBLIC
// please see https://github.com/Rust-GCC/gccrs/pull/137
diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h
index cfbe969..c6b135b 100644
--- a/gcc/rust/backend/rust-compile-item.h
+++ b/gcc/rust/backend/rust-compile-item.h
@@ -39,34 +39,6 @@ public:
item->accept_vis (compiler);
}
- void visit (HIR::TupleStruct &struct_decl)
- {
- TyTy::BaseType *resolved = nullptr;
- if (!ctx->get_tyctx ()->lookup_type (
- struct_decl.get_mappings ().get_hirid (), &resolved))
- {
- rust_fatal_error (struct_decl.get_locus (),
- "Failed to lookup type for struct decl");
- return;
- }
-
- TyTyResolveCompile::compile (ctx, resolved);
- }
-
- void visit (HIR::StructStruct &struct_decl)
- {
- TyTy::BaseType *resolved = nullptr;
- if (!ctx->get_tyctx ()->lookup_type (
- struct_decl.get_mappings ().get_hirid (), &resolved))
- {
- rust_fatal_error (struct_decl.get_locus (),
- "Failed to lookup type for struct decl");
- return;
- }
-
- TyTyResolveCompile::compile (ctx, resolved);
- }
-
void visit (HIR::StaticItem &var)
{
TyTy::BaseType *resolved_type = nullptr;
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index de325fa..ffc2655 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -84,7 +84,7 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
CompileItem::compile (resolved_item, ctx);
if (!ctx->lookup_function_decl (ref, &fn))
{
- rust_error_at (expr.get_locus (), "forward decl was not compiled");
+ rust_error_at (expr.get_locus (), "forward decl was not compiled 1");
return;
}
}
@@ -112,12 +112,14 @@ ResolvePathType::visit (HIR::PathInExpression &expr)
return;
}
- // assumes paths are functions for now
- if (!ctx->lookup_compiled_types (ref, &resolved))
+ TyTy::BaseType *tyty = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (ref, &tyty))
{
- rust_error_at (expr.get_locus (), "forward decl was not compiled");
+ rust_error_at (expr.get_locus (), "unknown type");
return;
}
+
+ resolved = TyTyResolveCompile::compile (ctx, tyty);
}
} // namespace Compile
diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h
index aed96e3..683a9a7 100644
--- a/gcc/rust/backend/rust-compile-tyty.h
+++ b/gcc/rust/backend/rust-compile-tyty.h
@@ -48,8 +48,6 @@ public:
void visit (TyTy::InferType &) override { gcc_unreachable (); }
- void visit (TyTy::StructFieldType &) override { gcc_unreachable (); }
-
void visit (TyTy::ADTType &) override { gcc_unreachable (); }
void visit (TyTy::TupleType &) override { gcc_unreachable (); }
@@ -58,6 +56,8 @@ public:
void visit (TyTy::ReferenceType &) override { gcc_unreachable (); }
+ void visit (TyTy::ParamType &) override { gcc_unreachable (); }
+
void visit (TyTy::UnitType &) override { translated = backend->void_type (); }
void visit (TyTy::FnType &type) override
diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h
index ea07f73..b46861e 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-expr.h
@@ -74,27 +74,7 @@ public:
return compiler.translated;
}
- void visit (AST::PathInExpression &expr)
- {
- std::vector<HIR::PathExprSegment> path_segments;
- expr.iterate_path_segments ([&] (AST::PathExprSegment &s) mutable -> bool {
- rust_assert (s.has_generic_args () == false); // TODO
-
- HIR::PathIdentSegment is (s.get_ident_segment ().as_string ());
- HIR::PathExprSegment seg (is, s.get_locus ());
- path_segments.push_back (seg);
- return true;
- });
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated = new HIR::PathInExpression (mapping, std::move (path_segments),
- expr.get_locus (),
- expr.opening_scope_resolution ());
- }
+ void visit (AST::PathInExpression &expr) override;
private:
ASTLowerPathInExpression () : translated (nullptr) {}
diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h
index 1e48e82..2865a6a 100644
--- a/gcc/rust/hir/rust-ast-lower-item.h
+++ b/gcc/rust/hir/rust-ast-lower-item.h
@@ -54,6 +54,12 @@ public:
void visit (AST::TupleStruct &struct_decl)
{
std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+ if (struct_decl.has_generics ())
+ {
+ generic_params
+ = lower_generic_params (struct_decl.get_generic_params ());
+ }
+
std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
HIR::WhereClause where_clause (std::move (where_clause_items));
HIR::Visibility vis = HIR::Visibility::create_public ();
@@ -104,6 +110,12 @@ public:
void visit (AST::StructStruct &struct_decl)
{
std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+ if (struct_decl.has_generics ())
+ {
+ generic_params
+ = lower_generic_params (struct_decl.get_generic_params ());
+ }
+
std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
HIR::WhereClause where_clause (std::move (where_clause_items));
HIR::Visibility vis = HIR::Visibility::create_public ();
@@ -324,6 +336,19 @@ public:
}
private:
+ std::vector<std::unique_ptr<HIR::GenericParam> > lower_generic_params (
+ std::vector<std::unique_ptr<AST::GenericParam> > &params)
+ {
+ std::vector<std::unique_ptr<HIR::GenericParam> > lowered;
+ for (auto &ast_param : params)
+ {
+ auto hir_param = ASTLowerGenericParam::translate (ast_param.get ());
+ lowered.push_back (std::unique_ptr<HIR::GenericParam> (hir_param));
+ }
+
+ return lowered;
+ }
+
ASTLoweringItem () : translated (nullptr) {}
HIR::Item *translated;
diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h
index 425d5c1..b5d0b7e 100644
--- a/gcc/rust/hir/rust-ast-lower-type.h
+++ b/gcc/rust/hir/rust-ast-lower-type.h
@@ -121,6 +121,33 @@ public:
segment.get_locus ());
}
+ void visit (AST::TypePathSegmentGeneric &segment)
+ {
+ std::vector<HIR::GenericArgsBinding> binding_args; // TODO
+
+ std::string segment_name = segment.get_ident_segment ().as_string ();
+ bool has_separating_scope_resolution
+ = segment.get_separating_scope_resolution ();
+
+ std::vector<HIR::Lifetime> lifetime_args;
+ for (auto &lifetime : segment.get_generic_args ().get_lifetime_args ())
+ {
+ HIR::Lifetime l = lower_lifetime (lifetime);
+ lifetime_args.push_back (std::move (l));
+ }
+
+ std::vector<std::unique_ptr<HIR::Type> > type_args;
+ for (auto &type : segment.get_generic_args ().get_type_args ())
+ {
+ HIR::Type *t = ASTLoweringType::translate (type.get ());
+ type_args.push_back (std::unique_ptr<HIR::Type> (t));
+ }
+
+ translated_segment = new HIR::TypePathSegmentGeneric (
+ segment_name, has_separating_scope_resolution, std::move (lifetime_args),
+ std::move (type_args), std::move (binding_args), segment.get_locus ());
+ }
+
void visit (AST::TypePath &path)
{
std::vector<std::unique_ptr<HIR::TypePathSegment> > translated_segments;
@@ -215,6 +242,49 @@ private:
HIR::TypePathSegment *translated_segment;
};
+class ASTLowerGenericParam : public ASTLoweringBase
+{
+public:
+ static HIR::GenericParam *translate (AST::GenericParam *param)
+ {
+ ASTLowerGenericParam resolver;
+ param->accept_vis (resolver);
+
+ rust_assert (resolver.translated != nullptr);
+ resolver.mappings->insert_location (
+ resolver.translated->get_mappings ().get_crate_num (),
+ resolver.translated->get_mappings ().get_hirid (),
+ param->get_locus_slow ());
+
+ return resolver.translated;
+ }
+
+ void visit (AST::TypeParam &param) override
+ {
+ HIR::Attribute outer_attr = HIR::Attribute::create_empty ();
+ std::vector<std::unique_ptr<HIR::TypeParamBound> > type_param_bounds;
+ HIR::Type *type = param.has_type ()
+ ? ASTLoweringType::translate (param.get_type ().get ())
+ : nullptr;
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ mappings->get_next_localdef_id (crate_num));
+
+ translated
+ = new HIR::TypeParam (mapping, param.get_type_representation (),
+ param.get_locus (), std::move (type_param_bounds),
+ std::unique_ptr<Type> (type),
+ std::move (outer_attr));
+ }
+
+private:
+ ASTLowerGenericParam () : ASTLoweringBase (), translated (nullptr) {}
+
+ HIR::GenericParam *translated;
+};
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index 230919a..355d570 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -269,5 +269,51 @@ ASTLoweringExprWithBlock::visit (AST::WhileLoopExpr &expr)
std::move (outer_attribs));
}
+// rust-ast-lower-expr.h
+
+void
+ASTLowerPathInExpression::visit (AST::PathInExpression &expr)
+{
+ std::vector<HIR::PathExprSegment> path_segments;
+ expr.iterate_path_segments ([&] (AST::PathExprSegment &s) mutable -> bool {
+ std::vector<HIR::GenericArgsBinding> binding_args; // TODO
+
+ std::vector<HIR::Lifetime> lifetime_args;
+ if (s.has_generic_args ())
+ {
+ for (auto &lifetime : s.get_generic_args ().get_lifetime_args ())
+ {
+ HIR::Lifetime l = lower_lifetime (lifetime);
+ lifetime_args.push_back (std::move (l));
+ }
+ }
+
+ std::vector<std::unique_ptr<HIR::Type> > type_args;
+ if (s.has_generic_args ())
+ {
+ for (auto &type : s.get_generic_args ().get_type_args ())
+ {
+ HIR::Type *t = ASTLoweringType::translate (type.get ());
+ type_args.push_back (std::unique_ptr<HIR::Type> (t));
+ }
+ }
+
+ PathExprSegment seg (s.get_ident_segment ().as_string (), s.get_locus (),
+ std::move (lifetime_args), std::move (type_args),
+ std::move (binding_args));
+ path_segments.push_back (seg);
+ return true;
+ });
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated = new HIR::PathInExpression (mapping, std::move (path_segments),
+ expr.get_locus (),
+ expr.opening_scope_resolution ());
+}
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index c0d6d0f..1415727 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -57,12 +57,13 @@ public:
// Returns whether the type param has an outer attribute.
bool has_outer_attribute () const { return !outer_attr.is_empty (); }
- TypeParam (Identifier type_representation, Location locus = Location (),
+ TypeParam (Analysis::NodeMapping mappings, Identifier type_representation,
+ Location locus = Location (),
std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds
= std::vector<std::unique_ptr<TypeParamBound> > (),
std::unique_ptr<Type> type = nullptr,
Attribute outer_attr = Attribute::create_empty ())
- : outer_attr (std::move (outer_attr)),
+ : GenericParam (mappings), outer_attr (std::move (outer_attr)),
type_representation (std::move (type_representation)),
type_param_bounds (std::move (type_param_bounds)),
type (std::move (type)), locus (locus)
@@ -70,7 +71,7 @@ public:
// Copy constructor uses clone
TypeParam (TypeParam const &other)
- : outer_attr (other.outer_attr),
+ : GenericParam (other.mappings), outer_attr (other.outer_attr),
type_representation (other.type_representation),
type (other.type->clone_type ()), locus (other.locus)
{
@@ -87,6 +88,7 @@ public:
type = other.type->clone_type ();
outer_attr = other.outer_attr;
locus = other.locus;
+ mappings = other.mappings;
type_param_bounds.reserve (other.type_param_bounds.size ());
for (const auto &e : other.type_param_bounds)
@@ -103,8 +105,12 @@ public:
Location get_locus () const { return locus; }
+ Location get_locus_slow () const override final { return get_locus (); }
+
void accept_vis (HIRVisitor &vis) override;
+ Identifier get_type_representation () const { return type_representation; }
+
protected:
// Clone function implementation as (not pure) virtual method
TypeParam *clone_generic_param_impl () const override
@@ -1502,6 +1508,11 @@ public:
Location get_locus () const { return locus; }
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+
protected:
Struct (Analysis::NodeMapping mappings, Identifier struct_name,
std::vector<std::unique_ptr<GenericParam> > generic_params,
diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h
index 9a772f0..c4fe0da 100644
--- a/gcc/rust/hir/tree/rust-hir-path.h
+++ b/gcc/rust/hir/tree/rust-hir-path.h
@@ -172,7 +172,21 @@ public:
std::vector<GenericArgsBinding> ());
}
+ bool is_empty () const
+ {
+ return lifetime_args.size () == 0 && type_args.size () == 0
+ && binding_args.size () == 0;
+ }
+
std::string as_string () const;
+
+ std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; }
+
+ std::vector<std::unique_ptr<Type> > &get_type_args () { return type_args; }
+
+ std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; }
+
+ Location get_locus () const { return locus; }
};
/* A segment of a path in expression, including an identifier aspect and maybe
@@ -230,6 +244,8 @@ public:
Location get_locus () const { return locus; }
PathIdentSegment get_segment () const { return segment_name; }
+
+ GenericArgs &get_generic_args () { return generic_args; }
};
// HIR node representing a pattern that involves a "path" - abstract base class
@@ -264,6 +280,8 @@ public:
return;
}
}
+
+ PathExprSegment get_final_segment () const { return segments.back (); }
};
/* HIR node representing a path-in-expression pattern (path that allows generic
@@ -432,6 +450,8 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ GenericArgs get_generic_args () { return generic_args; }
+
protected:
// Use covariance to override base class method
TypePathSegmentGeneric *clone_type_path_segment_impl () const override
@@ -653,12 +673,14 @@ public:
void iterate_segments (std::function<bool (TypePathSegment *)> cb)
{
- for (auto it = segments.begin (); it != segments.end (); it++)
+ for (auto &seg : segments)
{
- if (!cb ((*it).get ()))
+ if (!cb (seg.get ()))
return;
}
}
+
+ TypePathSegment *get_final_segment () { return segments.back ().get (); }
};
struct QualifiedPathType
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index 1567215..97f303c 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -1114,9 +1114,17 @@ public:
virtual void accept_vis (HIRVisitor &vis) = 0;
+ virtual Location get_locus_slow () const = 0;
+
+ Analysis::NodeMapping get_mappings () const { return mappings; }
+
protected:
// Clone function implementation as pure virtual method
virtual GenericParam *clone_generic_param_impl () const = 0;
+
+ GenericParam (Analysis::NodeMapping mapping) : mappings (mapping) {}
+
+ Analysis::NodeMapping mappings;
};
// A lifetime generic parameter (as opposed to a type generic parameter)
@@ -1145,11 +1153,12 @@ public:
bool is_error () const { return lifetime.is_error (); }
// Constructor
- LifetimeParam (Lifetime lifetime, Location locus = Location (),
+ LifetimeParam (Analysis::NodeMapping mappings, Lifetime lifetime,
+ Location locus = Location (),
std::vector<Lifetime> lifetime_bounds
= std::vector<Lifetime> (),
Attribute outer_attr = Attribute::create_empty ())
- : lifetime (std::move (lifetime)),
+ : GenericParam (mappings), lifetime (std::move (lifetime)),
lifetime_bounds (std::move (lifetime_bounds)),
outer_attr (std::move (outer_attr)), locus (locus)
{}
@@ -1158,8 +1167,9 @@ public:
// Copy constructor with clone
LifetimeParam (LifetimeParam const &other)
- : lifetime (other.lifetime), lifetime_bounds (other.lifetime_bounds),
- outer_attr (other.outer_attr), locus (other.locus)
+ : GenericParam (other.mappings), lifetime (other.lifetime),
+ lifetime_bounds (other.lifetime_bounds), outer_attr (other.outer_attr),
+ locus (other.locus)
{}
// Overloaded assignment operator to clone attribute
@@ -1169,6 +1179,7 @@ public:
lifetime_bounds = other.lifetime_bounds;
outer_attr = other.outer_attr;
locus = other.locus;
+ mappings = other.mappings;
return *this;
}
@@ -1181,6 +1192,10 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ Location get_locus () const { return locus; }
+
+ Location get_locus_slow () const override final { return get_locus (); }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h
index b8cf4de..216ab41 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.h
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.h
@@ -27,6 +27,21 @@
namespace Rust {
namespace Resolver {
+class ResolvePath : public ResolverBase
+{
+public:
+ static void go (AST::PathInExpression *expr, NodeId parent)
+ {
+ ResolvePath resolver (parent);
+ resolver.resolve_path (expr);
+ }
+
+private:
+ ResolvePath (NodeId parent) : ResolverBase (parent) {}
+
+ void resolve_path (AST::PathInExpression *expr);
+};
+
class ResolveExpr : public ResolverBase
{
public:
@@ -50,31 +65,7 @@ public:
ResolveExpr::go (elem.get (), expr.get_node_id ());
}
- void visit (AST::PathInExpression &expr)
- {
- // name scope first
- if (resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node))
- {
- resolver->insert_resolved_name (expr.get_node_id (), resolved_node);
- resolver->insert_new_definition (expr.get_node_id (),
- Definition{expr.get_node_id (),
- parent});
- }
- // check the type scope
- else if (resolver->get_type_scope ().lookup (expr.as_string (),
- &resolved_node))
- {
- resolver->insert_resolved_type (expr.get_node_id (), resolved_node);
- resolver->insert_new_definition (expr.get_node_id (),
- Definition{expr.get_node_id (),
- parent});
- }
- else
- {
- rust_error_at (expr.get_locus (), "unknown path %s",
- expr.as_string ().c_str ());
- }
- }
+ void visit (AST::PathInExpression &expr) { ResolvePath::go (&expr, parent); }
void visit (AST::ReturnExpr &expr)
{
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h
index f5dc579..02d864f 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.h
+++ b/gcc/rust/resolve/rust-ast-resolve-item.h
@@ -37,8 +37,6 @@ public:
item->accept_vis (resolver);
};
- ~ResolveItem () {}
-
void visit (AST::TupleStruct &struct_decl)
{
struct_decl.iterate ([&] (AST::TupleField &field) mutable -> bool {
@@ -50,11 +48,25 @@ public:
void visit (AST::StructStruct &struct_decl)
{
+ NodeId scope_node_id = struct_decl.get_node_id ();
+ resolver->get_type_scope ().push (scope_node_id);
+
+ if (struct_decl.has_generics ())
+ {
+ for (auto &generic : struct_decl.get_generic_params ())
+ {
+ ResolveGenericParam::go (generic.get (),
+ struct_decl.get_node_id ());
+ }
+ }
+
struct_decl.iterate ([&] (AST::StructField &field) mutable -> bool {
ResolveType::go (field.get_field_type ().get (),
struct_decl.get_node_id ());
return true;
});
+
+ resolver->get_type_scope ().pop ();
}
void visit (AST::StaticItem &var)
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h
index 4b08c21..24090a0 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.h
+++ b/gcc/rust/resolve/rust-ast-resolve-type.h
@@ -25,6 +25,53 @@
namespace Rust {
namespace Resolver {
+class ResolveTypePath : public ResolverBase
+{
+public:
+ static NodeId go (AST::TypePath &path, NodeId parent)
+ {
+ ResolveTypePath resolver (parent);
+ resolver.resolve (path);
+ return resolver.resolved_node;
+ }
+
+ void visit (AST::TypePathSegmentGeneric &seg) override;
+
+ void visit (AST::TypePathSegment &seg) override;
+
+private:
+ void resolve (AST::TypePath &path)
+ {
+ for (auto &seg : path.get_segments ())
+ {
+ seg->accept_vis (*this);
+ if (type_seg_failed_flag)
+ return;
+ }
+
+ if (path_buffer.empty ())
+ {
+ rust_error_at (path.get_locus (), "failed to resolve path: %s",
+ path.as_string ().c_str ());
+ return;
+ }
+
+ if (!resolver->get_type_scope ().lookup (path_buffer, &resolved_node))
+ {
+ rust_error_at (path.get_locus (), "failed to resolve TypePath: %s",
+ path_buffer.c_str ());
+ return;
+ }
+ }
+
+ ResolveTypePath (NodeId parent)
+ : ResolverBase (parent), type_seg_failed_flag (false)
+ {}
+
+ std::string path_buffer;
+ bool type_seg_failed_flag;
+};
+
class ResolveType : public ResolverBase
{
public:
@@ -63,16 +110,8 @@ public:
void visit (AST::TypePath &path)
{
- // this will need changed to handle mod/crate/use globs and look
- // at the segments in granularity
- if (!resolver->get_type_scope ().lookup (path.as_string (), &resolved_node))
- {
- rust_error_at (path.get_locus (), "failed to resolve TypePath: %s",
- path.as_string ().c_str ());
- return;
- }
-
- ok = true;
+ resolved_node = ResolveTypePath::go (path, parent);
+ ok = resolved_node != UNKNOWN_NODEID;
resolver->insert_resolved_type (path.get_node_id (), resolved_node);
resolver->insert_new_definition (path.get_node_id (),
Definition{path.get_node_id (), parent});
@@ -97,6 +136,40 @@ private:
bool ok;
};
+class ResolveGenericParam : public ResolverBase
+{
+public:
+ static NodeId go (AST::GenericParam *param, NodeId parent)
+ {
+ ResolveGenericParam resolver (parent);
+ param->accept_vis (resolver);
+ if (!resolver.ok)
+ rust_error_at (param->get_locus_slow (), "unresolved generic parameter");
+
+ return resolver.resolved_node;
+ };
+
+ void visit (AST::TypeParam &param) override
+ {
+ ok = true;
+
+ // for now lets focus on handling the basics: like struct<T> { a:T, ....}
+ resolver->get_type_scope ().insert (
+ param.get_type_representation (), param.get_node_id (),
+ param.get_locus (), false,
+ [&] (std::string, NodeId, Location locus) -> void {
+ rust_error_at (param.get_locus (),
+ "generic param redefined multiple times");
+ rust_error_at (locus, "was defined here");
+ });
+ }
+
+private:
+ ResolveGenericParam (NodeId parent) : ResolverBase (parent), ok (false) {}
+
+ bool ok;
+};
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc
index ddba7f2..6bc356a 100644
--- a/gcc/rust/resolve/rust-ast-resolve.cc
+++ b/gcc/rust/resolve/rust-ast-resolve.cc
@@ -368,5 +368,103 @@ ResolveStructExprField::visit (AST::StructExprFieldIdentifier &field)
ResolveExpr::go (&expr, field.get_node_id ());
}
+// rust-ast-resolve-type.h
+
+void
+ResolveTypePath::visit (AST::TypePathSegmentGeneric &seg)
+{
+ AST::GenericArgs &generics = seg.get_generic_args ();
+ for (auto &gt : generics.get_type_args ())
+ ResolveType::go (gt.get (), UNKNOWN_NODEID);
+
+ if (seg.is_error ())
+ {
+ type_seg_failed_flag = true;
+ rust_error_at (Location (), "segment has error: %s",
+ seg.as_string ().c_str ());
+ return;
+ }
+
+ if (seg.get_separating_scope_resolution ())
+ path_buffer += "::";
+
+ path_buffer += seg.get_ident_segment ().as_string ();
+}
+
+void
+ResolveTypePath::visit (AST::TypePathSegment &seg)
+{
+ if (seg.is_error ())
+ {
+ type_seg_failed_flag = true;
+ rust_error_at (Location (), "segment has error: %s",
+ seg.as_string ().c_str ());
+ return;
+ }
+
+ if (seg.get_separating_scope_resolution ())
+ path_buffer += "::";
+
+ path_buffer += seg.get_ident_segment ().as_string ();
+}
+
+// rust-ast-resolve-expr.h
+
+void
+ResolvePath::resolve_path (AST::PathInExpression *expr)
+{
+ // this needs extended similar to the TypePath to lookup each segment
+ // in turn then look its rib for the next segment and so forth until we
+ // resolve to a final NodeId generic args can be ignored
+ std::string path_buf;
+ for (auto &seg : expr->get_segments ())
+ {
+ auto s = seg.get_ident_segment ();
+ if (s.is_error () && !seg.has_generic_args ())
+ {
+ rust_error_at (expr->get_locus (), "malformed path");
+ return;
+ }
+
+ if (seg.has_generic_args ())
+ {
+ AST::GenericArgs &args = seg.get_generic_args ();
+ for (auto &gt : args.get_type_args ())
+ ResolveType::go (gt.get (), UNKNOWN_NODEID);
+ }
+
+ if (!s.is_error ())
+ {
+ bool needs_sep = !path_buf.empty ();
+ if (needs_sep)
+ path_buf += "::";
+
+ path_buf += s.as_string ();
+ }
+ }
+
+ // name scope first
+ if (resolver->get_name_scope ().lookup (path_buf, &resolved_node))
+ {
+ resolver->insert_resolved_name (expr->get_node_id (), resolved_node);
+ resolver->insert_new_definition (expr->get_node_id (),
+ Definition{expr->get_node_id (),
+ parent});
+ }
+ // check the type scope
+ else if (resolver->get_type_scope ().lookup (path_buf, &resolved_node))
+ {
+ resolver->insert_resolved_type (expr->get_node_id (), resolved_node);
+ resolver->insert_new_definition (expr->get_node_id (),
+ Definition{expr->get_node_id (),
+ parent});
+ }
+ else
+ {
+ rust_error_at (expr->get_locus (), "unknown path %s",
+ expr->as_string ().c_str (), path_buf.c_str ());
+ }
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index 4df813b..7cb24d8 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -1200,27 +1200,10 @@ Gcc_backend::named_type (const std::string &name, Btype *btype,
if (type == error_mark_node)
return this->error_type ();
- // The middle-end expects a basic type to have a name. In Go every
- // basic type will have a name. The first time we see a basic type,
- // give it whatever Go name we have at this point.
- if (TYPE_NAME (type) == NULL_TREE
- && location.gcc_location () == BUILTINS_LOCATION
- && (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == REAL_TYPE
- || TREE_CODE (type) == COMPLEX_TYPE
- || TREE_CODE (type) == BOOLEAN_TYPE))
- {
- tree decl = build_decl (BUILTINS_LOCATION, TYPE_DECL,
- get_identifier_from_string (name), type);
- TYPE_NAME (type) = decl;
- return this->make_type (type);
- }
-
- tree copy = build_variant_type_copy (type);
tree decl = build_decl (location.gcc_location (), TYPE_DECL,
- get_identifier_from_string (name), copy);
- DECL_ORIGINAL_TYPE (decl) = type;
- TYPE_NAME (copy) = decl;
- return this->make_type (copy);
+ get_identifier_from_string (name), type);
+ TYPE_NAME (type) = decl;
+ return this->make_type (type);
}
// Return a pointer type used as a marker for a circular type.
diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
index 8747391..525381f 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
@@ -32,9 +32,8 @@ class TypeCheckStructExpr : public TypeCheckBase
public:
static TyTy::BaseType *Resolve (HIR::StructExprStructFields *expr)
{
- TypeCheckStructExpr resolver;
+ TypeCheckStructExpr resolver (expr);
expr->accept_vis (resolver);
- rust_assert (resolver.resolved != nullptr);
return resolver.resolved;
}
@@ -49,13 +48,18 @@ public:
void visit (HIR::StructExprFieldIdentifier &field);
private:
- TypeCheckStructExpr ()
- : TypeCheckBase (), resolved (nullptr), struct_path_resolved (nullptr)
+ TypeCheckStructExpr (HIR::Expr *e)
+ : TypeCheckBase (),
+ resolved (new TyTy::ErrorType (e->get_mappings ().get_hirid ())),
+ struct_path_resolved (nullptr)
{}
+ // result
TyTy::BaseType *resolved;
+
+ // internal state:
TyTy::ADTType *struct_path_resolved;
- TyTy::BaseType *resolved_field;
+ TyTy::BaseType *resolved_field_value_expr;
std::set<std::string> fields_assigned;
std::map<size_t, HIR::StructExprField *> adtFieldIndexToField;
};
diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
index c82abaa..a7fa604 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
@@ -40,6 +40,20 @@ public:
void visit (HIR::TupleStruct &struct_decl)
{
+ std::vector<TyTy::SubstitionMapping> substitions;
+ if (struct_decl.has_generics ())
+ {
+ for (auto &generic_param : struct_decl.get_generic_params ())
+ {
+ auto param_type
+ = TypeResolveGenericParam::Resolve (generic_param.get ());
+ context->insert_type (generic_param->get_mappings (), param_type);
+
+ substitions.push_back (
+ TyTy::SubstitionMapping (generic_param, param_type));
+ }
+ }
+
std::vector<TyTy::StructFieldType *> fields;
size_t idx = 0;
@@ -57,13 +71,29 @@ public:
TyTy::BaseType *type
= new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (),
- struct_decl.get_identifier (), std::move (fields));
+ mappings->get_next_hir_id (),
+ struct_decl.get_identifier (), std::move (fields),
+ std::move (substitions));
context->insert_type (struct_decl.get_mappings (), type);
}
void visit (HIR::StructStruct &struct_decl)
{
+ std::vector<TyTy::SubstitionMapping> substitions;
+ if (struct_decl.has_generics ())
+ {
+ for (auto &generic_param : struct_decl.get_generic_params ())
+ {
+ auto param_type
+ = TypeResolveGenericParam::Resolve (generic_param.get ());
+ context->insert_type (generic_param->get_mappings (), param_type);
+
+ substitions.push_back (
+ TyTy::SubstitionMapping (generic_param, param_type));
+ }
+ }
+
std::vector<TyTy::StructFieldType *> fields;
struct_decl.iterate ([&] (HIR::StructField &field) mutable -> bool {
TyTy::BaseType *field_type
@@ -78,7 +108,9 @@ public:
TyTy::BaseType *type
= new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (),
- struct_decl.get_identifier (), std::move (fields));
+ mappings->get_next_hir_id (),
+ struct_decl.get_identifier (), std::move (fields),
+ std::move (substitions));
context->insert_type (struct_decl.get_mappings (), type);
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h
index 21f93fb..1592e22 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -62,6 +62,29 @@ private:
size_t result;
}; // namespace Resolver
+class TypeCheckResolveGenericArguments : public TypeCheckBase
+{
+public:
+ static HIR::GenericArgs resolve (HIR::TypePathSegment *segment)
+ {
+ TypeCheckResolveGenericArguments resolver;
+ segment->accept_vis (resolver);
+ return resolver.args;
+ };
+
+ void visit (HIR::TypePathSegmentGeneric &generic) override
+ {
+ args = generic.get_generic_args ();
+ }
+
+private:
+ TypeCheckResolveGenericArguments ()
+ : TypeCheckBase (), args (HIR::GenericArgs::create_empty ())
+ {}
+
+ HIR::GenericArgs args;
+};
+
class TypeCheckType : public TypeCheckBase
{
public:
@@ -71,11 +94,7 @@ public:
type->accept_vis (resolver);
if (resolver.translated == nullptr)
- {
- rust_error_at (Location (), "failed to translate %s",
- type->as_string ().c_str ());
- return new TyTy::ErrorType (type->get_mappings ().get_hirid ());
- }
+ return new TyTy::ErrorType (type->get_mappings ().get_hirid ());
resolver.context->insert_type (type->get_mappings (), resolver.translated);
return resolver.translated;
@@ -156,10 +175,65 @@ public:
translated = translated->clone ();
auto ref = path.get_mappings ().get_hirid ();
translated->set_ref (ref);
+
+ HIR::TypePathSegment *final_seg = path.get_final_segment ();
+ HIR::GenericArgs args
+ = TypeCheckResolveGenericArguments::resolve (final_seg);
+
+ bool path_declared_generic_arguments = !args.is_empty ();
+ if (path_declared_generic_arguments)
+ {
+ if (translated->has_subsititions_defined ())
+ {
+ // so far we only support ADT so lets just handle it here
+ // for now
+ if (translated->get_kind () != TyTy::TypeKind::ADT)
+ {
+ rust_error_at (
+ path.get_locus (),
+ "unsupported type for generic substitution: %s",
+ translated->as_string ().c_str ());
+ return;
+ }
+
+ TyTy::ADTType *adt
+ = static_cast<TyTy::ADTType *> (translated);
+ translated = adt->handle_substitions (args);
+ }
+ else
+ {
+ rust_error_at (
+ path.get_locus (),
+ "TypePath %s declares generic argument's but "
+ "the type %s does not have any",
+ path.as_string ().c_str (),
+ translated->as_string ().c_str ());
+ return;
+ }
+ }
+ else if (translated->supports_substitions ())
+ {
+ // so far we only support ADT so lets just handle it here
+ // for now
+ if (translated->get_kind () != TyTy::TypeKind::ADT)
+ {
+ rust_error_at (
+ path.get_locus (),
+ "unsupported type for generic substitution: %s",
+ translated->as_string ().c_str ());
+ return;
+ }
+
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (translated);
+ translated = adt->infer_substitions ();
+ }
+
return;
}
}
- gcc_unreachable ();
+
+ rust_error_at (path.get_locus (), "failed to resolve TypePath: %s",
+ path.as_string ().c_str ());
}
void visit (HIR::ArrayType &type)
@@ -197,6 +271,36 @@ private:
TyTy::BaseType *translated;
};
+class TypeResolveGenericParam : public TypeCheckBase
+{
+public:
+ static TyTy::ParamType *Resolve (HIR::GenericParam *param)
+ {
+ TypeResolveGenericParam resolver;
+ param->accept_vis (resolver);
+
+ if (resolver.resolved == nullptr)
+ {
+ rust_error_at (param->get_locus_slow (),
+ "failed to setup generic parameter");
+ return nullptr;
+ }
+
+ return resolver.resolved;
+ }
+
+ void visit (HIR::TypeParam &param) override
+ {
+ resolved = new TyTy::ParamType (param.get_type_representation (),
+ param.get_mappings ().get_hirid (), param);
+ }
+
+private:
+ TypeResolveGenericParam () : TypeCheckBase (), resolved (nullptr) {}
+
+ TyTy::ParamType *resolved;
+};
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index a43dcf6..69f13db 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -158,14 +158,15 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr)
return;
}
- resolved = struct_path_resolved;
+ TyTy::ADTType *struct_def = struct_path_resolved;
if (struct_expr.has_struct_base ())
{
TyTy::BaseType *base_resolved
= TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get (),
false);
- resolved = struct_path_resolved->unify (base_resolved);
- if (resolved == nullptr)
+ struct_def
+ = (TyTy::ADTType *) struct_path_resolved->unify (base_resolved);
+ if (struct_def == nullptr)
{
rust_fatal_error (
struct_expr.struct_base->base_struct->get_locus_slow (),
@@ -174,11 +175,12 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr)
}
}
+ std::vector<TyTy::StructFieldType *> infered_fields;
bool ok = true;
struct_expr.iterate ([&] (HIR::StructExprField *field) mutable -> bool {
- resolved_field = nullptr;
+ resolved_field_value_expr = nullptr;
field->accept_vis (*this);
- if (resolved_field == nullptr)
+ if (resolved_field_value_expr == nullptr)
{
rust_fatal_error (field->get_locus (),
"failed to resolve type for field");
@@ -186,13 +188,17 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr)
return false;
}
- context->insert_type (field->get_mappings (), resolved_field);
+ context->insert_type (field->get_mappings (), resolved_field_value_expr);
return true;
});
// something failed setting up the fields
if (!ok)
- return;
+ {
+ rust_error_at (struct_expr.get_locus (),
+ "constructor type resolution failure");
+ return;
+ }
// check the arguments are all assigned and fix up the ordering
if (fields_assigned.size () != struct_path_resolved->num_fields ())
@@ -270,6 +276,8 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr)
std::unique_ptr<HIR::StructExprField> (adtFieldIndexToField[i]));
}
struct_expr.set_fields_as_owner (std::move (ordered_fields));
+
+ resolved = struct_def;
}
void
@@ -315,7 +323,16 @@ TypeCheckStructExpr::visit (HIR::PathInExpression &expr)
"expected an ADT type");
return;
}
- struct_path_resolved = (TyTy::ADTType *) lookup;
+
+ struct_path_resolved = static_cast<TyTy::ADTType *> (lookup);
+ if (struct_path_resolved->has_substitions ())
+ {
+ HIR::PathExprSegment seg = expr.get_final_segment ();
+ struct_path_resolved
+ = seg.has_generic_args ()
+ ? struct_path_resolved->handle_substitions (seg.get_generic_args ())
+ : struct_path_resolved->infer_substitions ();
+ }
}
void
@@ -329,7 +346,6 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field)
}
size_t field_index;
- TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value (), false);
TyTy::StructFieldType *field_type
= struct_path_resolved->get_field (field.field_name, &field_index);
if (field_type == nullptr)
@@ -338,8 +354,9 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field)
return;
}
- resolved_field = field_type->get_field_type ()->unify (value);
- if (resolved_field != nullptr)
+ TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value (), false);
+ resolved_field_value_expr = field_type->get_field_type ()->unify (value);
+ if (resolved_field_value_expr != nullptr)
{
fields_assigned.insert (field.field_name);
adtFieldIndexToField[field_index] = &field;
@@ -358,7 +375,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
}
size_t field_index;
- TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value (), false);
+
TyTy::StructFieldType *field_type
= struct_path_resolved->get_field (field_name, &field_index);
if (field_type == nullptr)
@@ -367,8 +384,9 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
return;
}
- resolved_field = field_type->get_field_type ()->unify (value);
- if (resolved_field != nullptr)
+ TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value (), false);
+ resolved_field_value_expr = field_type->get_field_type ()->unify (value);
+ if (resolved_field_value_expr != nullptr)
{
fields_assigned.insert (field_name);
adtFieldIndexToField[field_index] = &field;
@@ -400,8 +418,9 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field)
field.get_locus ());
TyTy::BaseType *value = TypeCheckExpr::Resolve (&expr, false);
- resolved_field = field_type->get_field_type ()->unify (value);
- if (resolved_field != nullptr)
+ resolved_field_value_expr = field_type->get_field_type ()->unify (value);
+ if (resolved_field_value_expr != nullptr)
+
{
fields_assigned.insert (field.field_name);
adtFieldIndexToField[field_index] = &field;
diff --git a/gcc/rust/typecheck/rust-tycheck-dump.h b/gcc/rust/typecheck/rust-tycheck-dump.h
index 7e52f65..5bb33c9 100644
--- a/gcc/rust/typecheck/rust-tycheck-dump.h
+++ b/gcc/rust/typecheck/rust-tycheck-dump.h
@@ -32,11 +32,20 @@ public:
{
TypeResolverDump dumper;
for (auto &item : crate.items)
- item->accept_vis (dumper);
+ {
+ item->accept_vis (dumper);
+ dumper.dump += "\n";
+ }
out << dumper.dump;
}
+ void visit (HIR::StructStruct &struct_decl) override
+ {
+ dump += indent () + "struct " + type_string (struct_decl.get_mappings ())
+ + "\n";
+ }
+
void visit (HIR::InherentImpl &impl_block) override
{
dump += indent () + "impl "
@@ -177,6 +186,11 @@ public:
dump += type_string (expr.get_mappings ());
}
+ void visit (HIR::StructExprStructFields &expr) override
+ {
+ dump += "ctor: " + type_string (expr.get_mappings ());
+ }
+
protected:
std::string type_string (const Analysis::NodeMapping &mappings)
{
@@ -192,8 +206,8 @@ protected:
}
buf += "]";
- return "<" + lookup->as_string ()
- + " HIRID: " + std::to_string (mappings.get_hirid ())
+ std::string repr = lookup->as_string ();
+ return "<" + repr + " HIRID: " + std::to_string (mappings.get_hirid ())
+ " RF:" + std::to_string (lookup->get_ref ()) + " TF:"
+ std::to_string (lookup->get_ty_ref ()) + +" - " + buf + ">";
}
diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h
index e1f1a8c..612a5e8 100644
--- a/gcc/rust/typecheck/rust-tyty-call.h
+++ b/gcc/rust/typecheck/rust-tyty-call.h
@@ -42,7 +42,6 @@ public:
void visit (UnitType &type) override { gcc_unreachable (); }
void visit (InferType &type) override { gcc_unreachable (); }
void visit (TupleType &type) override { gcc_unreachable (); }
- void visit (StructFieldType &type) override { gcc_unreachable (); }
void visit (ArrayType &type) override { gcc_unreachable (); }
void visit (BoolType &type) override { gcc_unreachable (); }
void visit (IntType &type) override { gcc_unreachable (); }
@@ -53,6 +52,7 @@ public:
void visit (ErrorType &type) override { gcc_unreachable (); }
void visit (CharType &type) override { gcc_unreachable (); }
void visit (ReferenceType &type) override { gcc_unreachable (); }
+ void visit (ParamType &) override { gcc_unreachable (); }
// tuple-structs
void visit (ADTType &type) override;
@@ -86,7 +86,6 @@ public:
void visit (UnitType &type) override { gcc_unreachable (); }
void visit (InferType &type) override { gcc_unreachable (); }
void visit (TupleType &type) override { gcc_unreachable (); }
- void visit (StructFieldType &type) override { gcc_unreachable (); }
void visit (ArrayType &type) override { gcc_unreachable (); }
void visit (BoolType &type) override { gcc_unreachable (); }
void visit (IntType &type) override { gcc_unreachable (); }
@@ -98,6 +97,7 @@ public:
void visit (ADTType &type) override { gcc_unreachable (); };
void visit (CharType &type) override { gcc_unreachable (); }
void visit (ReferenceType &type) override { gcc_unreachable (); }
+ void visit (ParamType &) override { gcc_unreachable (); }
// call fns
void visit (FnType &type) override;
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
index 2479378..ef7a60c 100644
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ b/gcc/rust/typecheck/rust-tyty-rules.h
@@ -55,8 +55,17 @@ public:
This method is meant to be used internally by Ty. If you're trying to unify
two ty, you can simply call `unify` on ty themselves. */
- BaseType *unify (BaseType *other)
+ virtual BaseType *unify (BaseType *other)
{
+ if (other->get_kind () == TypeKind::PARAM)
+ {
+ ParamType *p = static_cast<ParamType *> (other);
+ if (p->can_resolve ())
+ {
+ other = p->resolve ();
+ }
+ }
+
other->accept_vis (*this);
if (resolved != nullptr)
{
@@ -197,7 +206,7 @@ public:
type.as_string ().c_str ());
}
- virtual void visit (StructFieldType &type) override
+ virtual void visit (CharType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
@@ -205,7 +214,7 @@ public:
type.as_string ().c_str ());
}
- virtual void visit (CharType &type) override
+ virtual void visit (ReferenceType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
@@ -213,12 +222,13 @@ public:
type.as_string ().c_str ());
}
- virtual void visit (ReferenceType &type) override
+ virtual void visit (ParamType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- rust_error_at (ref_locus, "expected [%s] got [%s]",
+ rust_error_at (ref_locus, "expected [%s] got [ParamTy <%s>]",
get_base ()->as_string ().c_str (),
type.as_string ().c_str ());
+ gcc_unreachable ();
}
protected:
@@ -461,28 +471,6 @@ private:
InferType *base;
};
-class StructFieldTypeRules : public BaseRules
-{
-public:
- StructFieldTypeRules (StructFieldType *base) : BaseRules (base), base (base)
- {}
-
- void visit (StructFieldType &type)
- {
- BaseType *ty = base->get_field_type ()->unify (type.get_field_type ());
- if (ty == nullptr)
- return;
-
- resolved = new TyTy::StructFieldType (type.get_ref (), type.get_ty_ref (),
- type.get_name (), ty);
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- StructFieldType *base;
-};
-
class UnitRules : public BaseRules
{
public:
@@ -718,7 +706,7 @@ class ADTRules : public BaseRules
public:
ADTRules (ADTType *base) : BaseRules (base), base (base) {}
- void visit (ADTType &type)
+ void visit (ADTType &type) override
{
if (base->num_fields () != type.num_fields ())
{
@@ -726,24 +714,23 @@ public:
return;
}
- std::vector<TyTy::StructFieldType *> fields;
for (size_t i = 0; i < type.num_fields (); ++i)
{
TyTy::StructFieldType *base_field = base->get_field (i);
TyTy::StructFieldType *other_field = type.get_field (i);
- BaseType *unified_ty = base_field->unify (other_field);
+ TyTy::BaseType *this_field_ty = base_field->get_field_type ();
+ TyTy::BaseType *other_field_ty = other_field->get_field_type ();
+
+ BaseType *unified_ty = this_field_ty->unify (other_field_ty);
if (unified_ty == nullptr)
{
BaseRules::visit (type);
return;
}
-
- fields.push_back ((TyTy::StructFieldType *) unified_ty);
}
- resolved = new TyTy::ADTType (type.get_ref (), type.get_ty_ref (),
- type.get_name (), fields);
+ resolved = base->clone ();
}
private:
@@ -889,6 +876,46 @@ private:
ReferenceType *base;
};
+class ParamRules : public BaseRules
+{
+public:
+ ParamRules (ParamType *base) : BaseRules (base), base (base) {}
+
+ // param types are a placeholder we shouldn't have cases where we unify
+ // against it. eg: struct foo<T> { a: T }; When we invoke it we can do either:
+ //
+ // foo<i32>{ a: 123 }.
+ // Then this enforces the i32 type to be referenced on the
+ // field via an hirid.
+ //
+ // rust also allows for a = foo{a:123}; Where we can use an Inference Variable
+ // to handle the typing of the struct
+ BaseType *unify (BaseType *other) override final
+ {
+ if (base->get_ref () == base->get_ty_ref ())
+ {
+ Location locus = mappings->lookup_location (base->get_ref ());
+ rust_fatal_error (locus,
+ "invalid use of unify with ParamTy [%s] and [%s]",
+ base->as_string ().c_str (),
+ other->as_string ().c_str ());
+ return nullptr;
+ }
+
+ auto context = Resolver::TypeCheckContext::get ();
+ BaseType *lookup = nullptr;
+ bool ok = context->lookup_type (base->get_ty_ref (), &lookup);
+ rust_assert (ok);
+
+ return lookup->unify (other);
+ }
+
+private:
+ BaseType *get_base () override { return base; }
+
+ ParamType *base;
+};
+
} // namespace TyTy
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h
index 6609605..b49085d 100644
--- a/gcc/rust/typecheck/rust-tyty-visitor.h
+++ b/gcc/rust/typecheck/rust-tyty-visitor.h
@@ -29,7 +29,6 @@ class TyVisitor
public:
virtual void visit (UnitType &type) = 0;
virtual void visit (InferType &type) = 0;
- virtual void visit (StructFieldType &type) = 0;
virtual void visit (ADTType &type) = 0;
virtual void visit (TupleType &type) = 0;
virtual void visit (FnType &type) = 0;
@@ -43,6 +42,7 @@ public:
virtual void visit (ErrorType &type) = 0;
virtual void visit (CharType &type) = 0;
virtual void visit (ReferenceType &type) = 0;
+ virtual void visit (ParamType &type) = 0;
};
} // namespace TyTy
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 66b87e3..89507c7 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -20,7 +20,9 @@
#include "rust-tyty-visitor.h"
#include "rust-tyty-call.h"
#include "rust-hir-type-check-expr.h"
+#include "rust-hir-type-check-type.h"
#include "rust-tyty-rules.h"
+#include "rust-hir-map.h"
namespace Rust {
namespace TyTy {
@@ -100,8 +102,6 @@ ErrorType::as_string () const
BaseType *
ErrorType::unify (BaseType *other)
{
- // FIXME
- // rust_error_at ();
return this;
}
@@ -111,45 +111,24 @@ ErrorType::clone ()
return new ErrorType (get_ref (), get_ty_ref (), get_combined_refs ());
}
-void
-StructFieldType::accept_vis (TyVisitor &vis)
-{
- vis.visit (*this);
-}
-
std::string
StructFieldType::as_string () const
{
return name + ":" + ty->as_string ();
}
-BaseType *
-StructFieldType::unify (BaseType *other)
-{
- StructFieldTypeRules r (this);
- return r.unify (other);
-}
-
bool
-StructFieldType::is_equal (const BaseType &other) const
+StructFieldType::is_equal (const StructFieldType &other) const
{
- if (get_kind () != other.get_kind ())
- {
- return false;
- }
- else
- {
- auto other2 = static_cast<const StructFieldType &> (other);
- return get_field_type () == other2.get_field_type ();
- }
+ return get_name ().compare (other.get_name ()) == 0
+ && get_field_type ()->is_equal (*other.get_field_type ());
}
-BaseType *
-StructFieldType::clone ()
+StructFieldType *
+StructFieldType::clone () const
{
- return new StructFieldType (get_ref (), get_ty_ref (), get_name (),
- get_field_type ()->clone (),
- get_combined_refs ());
+ return new StructFieldType (get_ref (), get_name (),
+ get_field_type ()->clone ());
}
void
@@ -161,15 +140,35 @@ ADTType::accept_vis (TyVisitor &vis)
std::string
ADTType::as_string () const
{
- // if (num_fields () == 0)
- // return identifier;
+ if (num_fields () == 0)
+ return identifier;
+
+ std::string fields_buffer;
+ for (size_t i = 0; i < num_fields (); ++i)
+ {
+ fields_buffer += get_field (i)->as_string ();
+ if ((i + 1) < num_fields ())
+ fields_buffer += ", ";
+ }
+
+ return identifier + subst_as_string () + "{" + fields_buffer + "}";
+}
- // std::string fields_buffer;
- // for (auto &field : fields)
- // fields_buffer += field->as_string () + ", ";
+const StructFieldType *
+ADTType::get_field (size_t index) const
+{
+ return fields.at (index);
+}
- // return identifier + "{" + fields_buffer + "}";
- return identifier;
+const BaseType *
+ADTType::get_field_type (size_t index) const
+{
+ const StructFieldType *ref = get_field (index);
+ auto context = Resolver::TypeCheckContext::get ();
+ BaseType *lookup = nullptr;
+ bool ok = context->lookup_type (ref->get_field_type ()->get_ref (), &lookup);
+ rust_assert (ok);
+ return lookup;
}
BaseType *
@@ -183,25 +182,19 @@ bool
ADTType::is_equal (const BaseType &other) const
{
if (get_kind () != other.get_kind ())
+ return false;
+
+ auto other2 = static_cast<const ADTType &> (other);
+ if (num_fields () != other2.num_fields ())
+ return false;
+
+ for (size_t i = 0; i < num_fields (); i++)
{
- return false;
- }
- else
- {
- auto other2 = static_cast<const ADTType &> (other);
- if (num_fields () != other2.num_fields ())
- {
- return false;
- }
- for (size_t i = 0; i < num_fields (); i++)
- {
- if (!get_field (i)->is_equal (*other2.get_field (i)))
- {
- return false;
- }
- }
- return true;
+ if (!get_field (i)->is_equal (*other2.get_field (i)))
+ return false;
}
+
+ return true;
}
BaseType *
@@ -211,8 +204,93 @@ ADTType::clone ()
for (auto &f : fields)
cloned_fields.push_back ((StructFieldType *) f->clone ());
- return new ADTType (get_ref (), get_ty_ref (), get_name (), cloned_fields,
- get_combined_refs ());
+ return new ADTType (get_ref (), get_ty_ref (), identifier, cloned_fields,
+ clone_substs (), get_combined_refs ());
+}
+
+ADTType *
+ADTType::infer_substitions ()
+{
+ auto context = Resolver::TypeCheckContext::get ();
+ ADTType *adt = static_cast<ADTType *> (clone ());
+
+ for (auto &sub : adt->get_substs ())
+ {
+ // generate an new inference variable
+ InferType *infer = new InferType (mappings->get_next_hir_id (),
+ InferType::InferTypeKind::GENERAL);
+ context->insert_type (
+ Analysis::NodeMapping (mappings->get_current_crate (), UNKNOWN_NODEID,
+ infer->get_ref (), UNKNOWN_LOCAL_DEFID),
+ infer);
+
+ sub.fill_param_ty (infer);
+ adt->fill_in_params_for (sub, infer);
+ }
+
+ // generate new ty ref id since this is an instantiate of the generic
+ adt->set_ty_ref (mappings->get_next_hir_id ());
+
+ return adt;
+}
+
+ADTType *
+ADTType::handle_substitions (HIR::GenericArgs &generic_args)
+{
+ if (generic_args.get_type_args ().size () != get_num_substitions ())
+ {
+ rust_error_at (generic_args.get_locus (),
+ "invalid number of generic arguments to generic ADT type");
+ return nullptr;
+ }
+
+ ADTType *adt = static_cast<ADTType *> (clone ());
+ size_t index = 0;
+ for (auto &arg : generic_args.get_type_args ())
+ {
+ BaseType *resolved = Resolver::TypeCheckType::Resolve (arg.get ());
+ if (resolved == nullptr)
+ {
+ rust_error_at (generic_args.get_locus (),
+ "failed to resolve type arguments");
+ return nullptr;
+ }
+
+ adt->fill_in_at (index, resolved);
+ index++;
+ }
+
+ // generate new ty ref id since this is an instantiate of the generic
+ adt->set_ty_ref (mappings->get_next_hir_id ());
+
+ return adt;
+}
+
+void
+ADTType::fill_in_at (size_t index, BaseType *type)
+{
+ SubstitionMapping sub = get_substition_mapping_at (index);
+ SubstitionRef<ADTType>::fill_in_at (index, type);
+ fill_in_params_for (sub, type);
+}
+
+void
+ADTType::fill_in_params_for (SubstitionMapping sub, BaseType *type)
+{
+ iterate_fields ([&] (StructFieldType *field) mutable -> bool {
+ bool is_param_ty = field->get_field_type ()->get_kind () == TypeKind::PARAM;
+ if (!is_param_ty)
+ return true;
+
+ const ParamType *pp = sub.get_param_ty ();
+ ParamType *p = static_cast<ParamType *> (field->get_field_type ());
+
+ // for now let just see what symbols match up for the substitution
+ if (p->get_symbol ().compare (pp->get_symbol ()) == 0)
+ p->set_ty_ref (type->get_ref ());
+
+ return true;
+ });
}
void
@@ -637,14 +715,10 @@ bool
ReferenceType::is_equal (const BaseType &other) const
{
if (get_kind () != other.get_kind ())
- {
- return false;
- }
- else
- {
- auto other2 = static_cast<const ReferenceType &> (other);
- return get_base () == other2.get_base ();
- }
+ return false;
+
+ auto other2 = static_cast<const ReferenceType &> (other);
+ return get_base ()->is_equal (*other2.get_base ());
}
const BaseType *
@@ -674,6 +748,57 @@ ReferenceType::clone ()
get_combined_refs ());
}
+void
+ParamType::accept_vis (TyVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+std::string
+ParamType::as_string () const
+{
+ if (get_ref () == get_ty_ref ())
+ return get_symbol ();
+
+ auto context = Resolver::TypeCheckContext::get ();
+ BaseType *lookup = nullptr;
+ bool ok = context->lookup_type (get_ty_ref (), &lookup);
+ rust_assert (ok);
+
+ return lookup->as_string ();
+}
+
+BaseType *
+ParamType::unify (BaseType *other)
+{
+ ParamRules r (this);
+ return r.unify (other);
+}
+
+BaseType *
+ParamType::clone ()
+{
+ return new ParamType (get_symbol (), get_ref (), get_ty_ref (),
+ get_generic_param (), get_combined_refs ());
+}
+
+std::string
+ParamType::get_symbol () const
+{
+ return symbol;
+}
+
+BaseType *
+ParamType::resolve ()
+{
+ auto context = Resolver::TypeCheckContext::get ();
+ BaseType *lookup = nullptr;
+ bool ok = context->lookup_type (get_ty_ref (), &lookup);
+ rust_assert (ok);
+
+ return lookup;
+}
+
// rust-tyty-call.h
void
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 12a3bd5..50fc352 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -42,7 +42,6 @@ enum TypeKind
UINT,
FLOAT,
UNIT,
- FIELD,
USIZE,
ISIZE,
// there are more to add...
@@ -68,6 +67,8 @@ public:
virtual std::string as_string () const = 0;
+ virtual std::string get_name () const = 0;
+
/* Unify two types. Returns a pointer to the newly-created unified ty, or
nullptr if the two ty cannot be unified. The caller is responsible for
releasing the memory of the returned ty. */
@@ -90,21 +91,28 @@ public:
* releasing the memory of the returned ty. */
virtual BaseType *clone () = 0;
+ // get_combined_refs returns the chain of node refs involved in unification
std::set<HirId> get_combined_refs () { return combined; }
void append_reference (HirId id) { combined.insert (id); }
+ virtual bool supports_substitions () const { return false; }
+
+ virtual bool has_subsititions_defined () const { return false; }
+
protected:
BaseType (HirId ref, HirId ty_ref, TypeKind kind,
std::set<HirId> refs = std::set<HirId> ())
- : kind (kind), ref (ref), ty_ref (ty_ref), combined (refs)
+ : kind (kind), ref (ref), ty_ref (ty_ref), combined (refs),
+ mappings (Analysis::Mappings::get ())
{}
TypeKind kind;
HirId ref;
HirId ty_ref;
-
std::set<HirId> combined;
+
+ Analysis::Mappings *mappings;
};
class InferType : public BaseType
@@ -129,7 +137,7 @@ public:
void accept_vis (TyVisitor &vis) override;
- bool is_unit () const override { return true; }
+ bool is_unit () const override { return false; }
std::string as_string () const override;
@@ -139,6 +147,8 @@ public:
InferTypeKind get_infer_kind () const { return infer_kind; }
+ std::string get_name () const override final { return as_string (); }
+
private:
InferTypeKind infer_kind;
};
@@ -163,6 +173,8 @@ public:
BaseType *unify (BaseType *other) override;
BaseType *clone () final override;
+
+ std::string get_name () const override final { return as_string (); }
};
class UnitType : public BaseType
@@ -185,38 +197,31 @@ public:
BaseType *unify (BaseType *other) override;
BaseType *clone () final override;
+
+ std::string get_name () const override final { return as_string (); }
};
-class StructFieldType : public BaseType
+class StructFieldType
{
public:
- StructFieldType (HirId ref, std::string name, BaseType *ty,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::FIELD, refs), name (name), ty (ty)
- {}
-
- StructFieldType (HirId ref, HirId ty_ref, std::string name, BaseType *ty,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::FIELD, refs), name (name), ty (ty)
+ StructFieldType (HirId ref, std::string name, BaseType *ty)
+ : ref (ref), name (name), ty (ty)
{}
- void accept_vis (TyVisitor &vis) override;
-
- bool is_unit () const override { return ty->is_unit (); }
-
- std::string as_string () const override;
+ HirId get_ref () const { return ref; }
- BaseType *unify (BaseType *other) override;
+ std::string as_string () const;
- virtual bool is_equal (const BaseType &other) const override;
+ bool is_equal (const StructFieldType &other) const;
std::string get_name () const { return name; }
BaseType *get_field_type () const { return ty; }
- BaseType *clone () final override;
+ StructFieldType *clone () const;
private:
+ HirId ref;
std::string name;
BaseType *ty;
};
@@ -225,6 +230,7 @@ class TupleType : public BaseType
{
public:
TupleType (HirId ref, std::vector<HirId> fields,
+
std::set<HirId> refs = std::set<HirId> ())
: BaseType (ref, ref, TypeKind::TUPLE, refs), fields (fields)
{}
@@ -259,24 +265,148 @@ public:
}
}
+ std::string get_name () const override final { return as_string (); }
+
private:
std::vector<HirId> fields;
};
-class ADTType : public BaseType
+class ParamType : public BaseType
+{
+public:
+ ParamType (std::string symbol, HirId ref, HIR::GenericParam &param,
+ std::set<HirId> refs = std::set<HirId> ())
+ : BaseType (ref, ref, TypeKind::PARAM), symbol (symbol), param (param)
+ {}
+
+ ParamType (std::string symbol, HirId ref, HirId ty_ref,
+ HIR::GenericParam &param,
+ std::set<HirId> refs = std::set<HirId> ())
+ : BaseType (ref, ty_ref, TypeKind::PARAM), symbol (symbol), param (param)
+ {}
+
+ void accept_vis (TyVisitor &vis) override;
+
+ std::string as_string () const override;
+
+ BaseType *unify (BaseType *other) override;
+
+ BaseType *clone () final override;
+
+ std::string get_symbol () const;
+
+ HIR::GenericParam &get_generic_param () { return param; }
+
+ bool can_resolve () const { return get_ref () != get_ty_ref (); }
+
+ BaseType *resolve ();
+
+ std::string get_name () const override final { return as_string (); }
+
+private:
+ std::string symbol;
+ HIR::GenericParam &param;
+};
+
+class SubstitionMapping
+{
+public:
+ SubstitionMapping (std::unique_ptr<HIR::GenericParam> &generic,
+ ParamType *param)
+ : generic (generic), param (param)
+ {}
+
+ std::string as_string () const { return param->as_string (); }
+
+ void fill_param_ty (BaseType *type) { param->set_ty_ref (type->get_ref ()); }
+
+ SubstitionMapping clone ()
+ {
+ return SubstitionMapping (generic,
+ static_cast<ParamType *> (param->clone ()));
+ }
+
+ const ParamType *get_param_ty () const { return param; }
+
+private:
+ std::unique_ptr<HIR::GenericParam> &generic;
+ ParamType *param;
+};
+
+template <class T> class SubstitionRef
+{
+public:
+ SubstitionRef (std::vector<SubstitionMapping> substitions)
+ : substitions (substitions)
+ {}
+
+ bool has_substitions () const { return substitions.size () > 0; }
+
+ std::string subst_as_string () const
+ {
+ std::string buffer;
+ for (size_t i = 0; i < substitions.size (); i++)
+ {
+ const SubstitionMapping &sub = substitions.at (i);
+ buffer += sub.as_string ();
+
+ if ((i + 1) < substitions.size ())
+ buffer += ", ";
+ }
+
+ return buffer.empty () ? "" : "<" + buffer + ">";
+ }
+
+ size_t get_num_substitions () const { return substitions.size (); }
+
+ std::vector<SubstitionMapping> &get_substs () { return substitions; }
+
+ std::vector<SubstitionMapping> clone_substs ()
+ {
+ std::vector<SubstitionMapping> clone;
+ for (auto &sub : substitions)
+ clone.push_back (sub.clone ());
+
+ return clone;
+ }
+
+ virtual T *infer_substitions () = 0;
+
+ virtual T *handle_substitions (HIR::GenericArgs &generic_args) = 0;
+
+protected:
+ virtual void fill_in_at (size_t index, BaseType *type)
+ {
+ substitions.at (index).fill_param_ty (type);
+ }
+
+ SubstitionMapping get_substition_mapping_at (size_t index)
+ {
+ return substitions.at (index);
+ }
+
+private:
+ std::vector<SubstitionMapping> substitions;
+};
+
+class ADTType : public BaseType, public SubstitionRef<ADTType>
{
public:
ADTType (HirId ref, std::string identifier,
std::vector<StructFieldType *> fields,
+ std::vector<SubstitionMapping> subst_refs,
std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::ADT, refs), identifier (identifier),
+ : BaseType (ref, ref, TypeKind::ADT, refs),
+ SubstitionRef (std::move (subst_refs)), identifier (identifier),
fields (fields)
{}
ADTType (HirId ref, HirId ty_ref, std::string identifier,
std::vector<StructFieldType *> fields,
+ std::vector<SubstitionMapping> subst_refs,
std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::ADT, refs), identifier (identifier),
+ : BaseType (ref, ty_ref, TypeKind::ADT, refs),
+ SubstitionRef (std::move (subst_refs)), identifier (identifier),
fields (fields)
{}
@@ -292,9 +422,18 @@ public:
size_t num_fields () const { return fields.size (); }
- std::string get_name () const { return identifier; }
+ std::string get_name () const override final
+ {
+ return identifier + subst_as_string ();
+ }
+
+ BaseType *get_field_type (size_t index);
+
+ const BaseType *get_field_type (size_t index) const;
- StructFieldType *get_field (size_t index) const { return fields.at (index); }
+ const StructFieldType *get_field (size_t index) const;
+
+ StructFieldType *get_field (size_t index) { return fields.at (index); }
StructFieldType *get_field (const std::string &lookup,
size_t *index = nullptr) const
@@ -327,6 +466,21 @@ public:
}
}
+ bool supports_substitions () const override final { return true; }
+
+ bool has_subsititions_defined () const override final
+ {
+ return has_substitions ();
+ }
+
+ ADTType *infer_substitions () override final;
+
+ ADTType *handle_substitions (HIR::GenericArgs &generic_args) override final;
+
+ void fill_in_at (size_t index, BaseType *type) override final;
+
+ void fill_in_params_for (SubstitionMapping sub, BaseType *type);
+
private:
std::string identifier;
std::vector<StructFieldType *> fields;
@@ -352,6 +506,8 @@ public:
std::string as_string () const override;
+ std::string get_name () const override final { return as_string (); }
+
BaseType *return_type () { return type; }
BaseType *unify (BaseType *other) override;
@@ -408,6 +564,8 @@ public:
std::string as_string () const override;
+ std::string get_name () const override final { return as_string (); }
+
BaseType *unify (BaseType *other) override;
virtual bool is_equal (const BaseType &other) const override;
@@ -440,6 +598,8 @@ public:
std::string as_string () const override;
+ std::string get_name () const override final { return as_string (); }
+
BaseType *unify (BaseType *other) override;
BaseType *clone () final override;
@@ -470,6 +630,8 @@ public:
std::string as_string () const override;
+ std::string get_name () const override final { return as_string (); }
+
BaseType *unify (BaseType *other) override;
IntKind get_kind () const { return int_kind; }
@@ -505,6 +667,8 @@ public:
std::string as_string () const override;
+ std::string get_name () const override final { return as_string (); }
+
BaseType *unify (BaseType *other) override;
UintKind get_kind () const { return uint_kind; }
@@ -538,6 +702,8 @@ public:
std::string as_string () const override;
+ std::string get_name () const override final { return as_string (); }
+
BaseType *unify (BaseType *other) override;
FloatKind get_kind () const { return float_kind; }
@@ -563,6 +729,8 @@ public:
std::string as_string () const override;
+ std::string get_name () const override final { return as_string (); }
+
BaseType *unify (BaseType *other) override;
BaseType *clone () final override;
@@ -583,6 +751,8 @@ public:
std::string as_string () const override;
+ std::string get_name () const override final { return as_string (); }
+
BaseType *unify (BaseType *other) override;
BaseType *clone () final override;
@@ -604,6 +774,8 @@ public:
std::string as_string () const override;
+ std::string get_name () const override final { return as_string (); }
+
BaseType *unify (BaseType *other) override;
BaseType *clone () final override;
@@ -630,6 +802,8 @@ public:
std::string as_string () const override;
+ std::string get_name () const override final { return as_string (); }
+
BaseType *unify (BaseType *other) override;
virtual bool is_equal (const BaseType &other) const override;
diff --git a/gcc/testsuite/rust.test/compilable/generics1.rs b/gcc/testsuite/rust.test/compilable/generics1.rs
new file mode 100644
index 0000000..8a2965a
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/generics1.rs
@@ -0,0 +1,41 @@
+struct Foo {
+ a: f32,
+ b: bool,
+}
+
+struct GenericStruct<T> {
+ a: T,
+ b: usize,
+}
+
+fn main() {
+ let a1;
+ a1 = Foo { a: 1.0, b: false };
+
+ let b1: f32 = a1.a;
+ let c1: bool = a1.b;
+
+ let a2: GenericStruct<i8>;
+ a2 = GenericStruct::<i8> { a: 1, b: 456 };
+
+ let b2: i8 = a2.a;
+ let c2: usize = a2.b;
+
+ let a3;
+ a3 = GenericStruct::<i32> { a: 123, b: 456 };
+
+ let b3: i32 = a3.a;
+ let c3: usize = a3.b;
+
+ let a4;
+ a4 = GenericStruct { a: 1.0, b: 456 };
+
+ let b4: f32 = a4.a;
+ let c4: usize = a4.b;
+
+ let a5;
+ a5 = GenericStruct::<_> { a: true, b: 456 };
+
+ let b5: bool = a5.a;
+ let c5: usize = a5.b;
+}