aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-01-18 17:57:22 +0000
committerPhilip Herron <herron.philip@googlemail.com>2021-01-20 09:59:22 +0000
commit12f7bd0fc4e9ab4e98869b5265aea6bacfb31d03 (patch)
treeaaff0986f81394b83e8536b68a18bcd48ecb9484 /gcc
parent6e2acd529fcfa43368f7ea8209cc5e6b88d2bd79 (diff)
downloadgcc-12f7bd0fc4e9ab4e98869b5265aea6bacfb31d03.zip
gcc-12f7bd0fc4e9ab4e98869b5265aea6bacfb31d03.tar.gz
gcc-12f7bd0fc4e9ab4e98869b5265aea6bacfb31d03.tar.bz2
Support struct initializers using Identifiers
This resolves each identifier for its respective field. It includes fixes for the TypeResolver to print errors instead of asserts where we loose decent debug info.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/ast/rust-ast.h2
-rw-r--r--gcc/rust/ast/rust-expr.h2
-rw-r--r--gcc/rust/backend/rust-compile-struct-field-expr.h2
-rw-r--r--gcc/rust/backend/rust-compile.cc10
-rw-r--r--gcc/rust/hir/rust-ast-lower-struct-field-expr.h13
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc13
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h2
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h5
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.cc9
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct-field.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc29
-rw-r--r--gcc/rust/typecheck/rust-tyty-resolver.h68
-rw-r--r--gcc/rust/util/rust-hir-map.cc24
-rw-r--r--gcc/rust/util/rust-hir-map.h6
-rw-r--r--gcc/testsuite/rust.test/compilable/struct_init_3.rs10
15 files changed, 173 insertions, 24 deletions
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 941b2fe..34122bb 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -882,6 +882,8 @@ public:
virtual NodeId get_node_id () const { return node_id; }
+ virtual void set_node_id (NodeId id) { node_id = id; }
+
protected:
// Constructor
Expr (std::vector<Attribute> outer_attribs = std::vector<Attribute> ())
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index 8a1fd6e..6dba7fd 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -1604,6 +1604,8 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ Identifier get_field_name () const { return field_name; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/backend/rust-compile-struct-field-expr.h b/gcc/rust/backend/rust-compile-struct-field-expr.h
index 0e54281..0a16f6a 100644
--- a/gcc/rust/backend/rust-compile-struct-field-expr.h
+++ b/gcc/rust/backend/rust-compile-struct-field-expr.h
@@ -40,6 +40,8 @@ public:
void visit (HIR::StructExprFieldIndexValue &field);
+ void visit (HIR::StructExprFieldIdentifier &field);
+
private:
CompileStructExprField (Context *ctx)
: HIRCompileBase (ctx), translated (nullptr)
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index cb6272f..ce6d827 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -234,5 +234,15 @@ CompileStructExprField::visit (HIR::StructExprFieldIndexValue &field)
translated = CompileExpr::Compile (field.get_value (), ctx);
}
+void
+CompileStructExprField::visit (HIR::StructExprFieldIdentifier &field)
+{
+ // we can make the field look like an identifier expr to take advantage of
+ // existing code
+ HIR::IdentifierExpr expr (field.get_mappings (), field.get_field_name (),
+ field.get_locus ());
+ translated = CompileExpr::Compile (&expr, ctx);
+}
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower-struct-field-expr.h b/gcc/rust/hir/rust-ast-lower-struct-field-expr.h
index 71c1f1f..c44c9f9 100644
--- a/gcc/rust/hir/rust-ast-lower-struct-field-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-struct-field-expr.h
@@ -34,10 +34,13 @@ public:
field->accept_vis (compiler);
rust_assert (compiler.translated != nullptr);
- // compiler.mappings->insert_hir_expr (
- // compiler.translated->get_mappings ().get_crate_num (),
- // compiler.translated->get_mappings ().get_hirid (),
- // compiler.translated);
+ compiler.mappings->insert_hir_struct_field (
+ compiler.translated->get_mappings ().get_crate_num (),
+ compiler.translated->get_mappings ().get_hirid (), compiler.translated);
+ compiler.mappings->insert_location (
+ compiler.translated->get_mappings ().get_crate_num (),
+ compiler.translated->get_mappings ().get_hirid (),
+ field->get_locus_slow ());
return compiler.translated;
}
@@ -48,6 +51,8 @@ public:
void visit (AST::StructExprFieldIndexValue &field);
+ void visit (AST::StructExprFieldIdentifier &field);
+
private:
ASTLowerStructExprField () : translated (nullptr) {}
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index d4c8224..dac2320 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -228,5 +228,18 @@ ASTLowerStructExprField::visit (AST::StructExprFieldIndexValue &field)
field.get_locus ());
}
+void
+ASTLowerStructExprField::visit (AST::StructExprFieldIdentifier &field)
+{
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, field.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::StructExprFieldIdentifier (mapping, field.get_field_name (),
+ field.get_locus ());
+}
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index a50f744..ff3fbab 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -1496,6 +1496,8 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ Identifier get_field_name () const { return field_name; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h
index 45d3e59..3916473 100644
--- a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h
+++ b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h
@@ -26,8 +26,7 @@ namespace Rust {
namespace Resolver {
// this resolves values being assigned not that the field actually exists yet.
-// We cant resolve the field to struct until type resolution since the HIR
-// Mappings don't exist yet.
+
class ResolveStructExprField : public ResolverBase
{
public:
@@ -43,6 +42,8 @@ public:
void visit (AST::StructExprFieldIndexValue &field);
+ void visit (AST::StructExprFieldIdentifier &field);
+
private:
ResolveStructExprField (NodeId parent) : ResolverBase (parent) {}
};
diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc
index 910cd86..ec53ae0 100644
--- a/gcc/rust/resolve/rust-ast-resolve.cc
+++ b/gcc/rust/resolve/rust-ast-resolve.cc
@@ -324,5 +324,14 @@ ResolveStructExprField::visit (AST::StructExprFieldIndexValue &field)
ResolveExpr::go (field.get_value ().get (), field.get_node_id ());
}
+void
+ResolveStructExprField::visit (AST::StructExprFieldIdentifier &field)
+{
+ AST::IdentifierExpr expr (field.get_field_name (), field.get_locus ());
+ expr.set_node_id (field.get_node_id ());
+
+ ResolveExpr::go (&expr, field.get_node_id ());
+}
+
} // namespace Resolver
} // namespace Rust
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 02bc9df..48ab40f 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
@@ -46,6 +46,8 @@ public:
void visit (HIR::StructExprFieldIndexValue &field);
+ void visit (HIR::StructExprFieldIdentifier &field);
+
private:
TypeCheckStructExpr ()
: TypeCheckBase (), resolved (nullptr), struct_path_resolved (nullptr)
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index 6819627..6f8c3a1 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -222,5 +222,34 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
fields_assigned.insert (field_name);
}
+void
+TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field)
+{
+ auto it = fields_assigned.find (field.get_field_name ());
+ if (it != fields_assigned.end ())
+ {
+ rust_fatal_error (field.get_locus (), "used more than once");
+ return;
+ }
+
+ TyTy::StructFieldType *field_type
+ = struct_path_resolved->get_field (field.get_field_name ());
+ if (field_type == nullptr)
+ {
+ rust_error_at (field.get_locus (), "unknown field");
+ return;
+ }
+
+ // we can make the field look like an identifier expr to take advantage of
+ // existing code to figure out the type
+ HIR::IdentifierExpr expr (field.get_mappings (), field.get_field_name (),
+ field.get_locus ());
+ TyTy::TyBase *value = TypeCheckExpr::Resolve (&expr);
+
+ resolved_field = field_type->get_field_type ()->combine (value);
+ if (resolved_field != nullptr)
+ fields_assigned.insert (field.field_name);
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-resolver.h b/gcc/rust/typecheck/rust-tyty-resolver.h
index 3c31076..eb03ff9 100644
--- a/gcc/rust/typecheck/rust-tyty-resolver.h
+++ b/gcc/rust/typecheck/rust-tyty-resolver.h
@@ -44,7 +44,8 @@ public:
void go (Rib *rib)
{
- rib->iterate_decls ([&] (NodeId decl_node_id, Location) mutable -> bool {
+ rib->iterate_decls ([&] (NodeId decl_node_id,
+ Location locus) mutable -> bool {
// type inference in rust means we need to gather and examine all
// references of this decl and combine each to make sure the type is
// correctly inferred. Consider the example:
@@ -52,33 +53,53 @@ public:
// we can only say x is an infer variable then at the assignment
// we think x must be an integer
+ bool ok = true;
std::vector<TyTy::TyBase *> gathered_types;
rib->iterate_references_for_def (
decl_node_id, [&] (NodeId ref_node) mutable -> bool {
HirId hir_node_ref;
- bool ok
- = mappings->lookup_node_to_hir (mappings->get_current_crate (),
- ref_node, &hir_node_ref);
- rust_assert (ok);
+ if (!mappings->lookup_node_to_hir (mappings->get_current_crate (),
+ ref_node, &hir_node_ref))
+ {
+ rust_error_at (locus,
+ "failed to reserve lookup HIR node for reference");
+ ok = false;
+ return false;
+ }
TyTy::TyBase *resolved = nullptr;
if (!context->lookup_type (hir_node_ref, &resolved))
{
// this could be an array/adt type
Definition d;
- bool ok = resolver->lookup_definition (ref_node, &d);
- rust_assert (ok);
+ if (!resolver->lookup_definition (ref_node, &d))
+ {
+ rust_error_at (
+ locus,
+ "failed to lookup definition for referenced hir node");
+
+ ok = false;
+ return false;
+ }
+
+ if (!mappings->lookup_node_to_hir (mappings->get_current_crate (),
+ d.parent, &hir_node_ref))
+ {
+ rust_error_at (locus,
+ "failed to lookup HIR node for parent NodeId");
- ok = mappings->lookup_node_to_hir (mappings->get_current_crate (),
- d.parent, &hir_node_ref);
- rust_assert (ok);
+ ok = false;
+ return false;
+ }
if (!context->lookup_type (hir_node_ref, &resolved))
{
- rust_fatal_error (
+ rust_error_at (
mappings->lookup_location (hir_node_ref),
"failed to lookup type for reference at node [%u]",
hir_node_ref);
+
+ ok = false;
return false;
}
}
@@ -88,18 +109,29 @@ public:
});
Definition d;
- bool ok = resolver->lookup_definition (decl_node_id, &d);
- rust_assert (ok);
+ if (!resolver->lookup_definition (decl_node_id, &d))
+ {
+ rust_error_at (locus, "Failed to lookup definition within rib");
+ return false;
+ }
HIR::Stmt *decl = nullptr;
- ok = mappings->resolve_nodeid_to_stmt (d.parent, &decl);
- rust_assert (ok);
+ if (!mappings->resolve_nodeid_to_stmt (d.parent, &decl))
+ {
+ rust_error_at (locus, "Failed to resolve decl to HIR::Stmt");
+ return false;
+ }
TyTy::TyBase *resolved_type = nullptr;
- ok = context->lookup_type (decl->get_mappings ().get_hirid (),
- &resolved_type);
- rust_assert (ok);
+ if (!context->lookup_type (decl->get_mappings ().get_hirid (),
+ &resolved_type))
+ {
+ rust_error_at (locus, "Unknown base type for decl in Rib");
+ return false;
+ }
+ // if it is not infer then it must have been figured out already
+ // we might need changes for generics later on
if (resolved_type->get_kind () != TyTy::TypeKind::INFER)
return true;
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index 0fea501..c6e177b 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -350,6 +350,30 @@ Mappings::lookup_hir_param (CrateNum crateNum, HirId id)
}
void
+Mappings::insert_hir_struct_field (CrateNum crateNum, HirId id,
+ HIR::StructExprField *field)
+{
+ rust_assert (lookup_hir_stmt (crateNum, id) == nullptr);
+
+ hirStructFieldMappings[crateNum][id] = field;
+ nodeIdToHirMappings[crateNum][field->get_mappings ().get_nodeid ()] = id;
+}
+
+HIR::StructExprField *
+Mappings::lookup_hir_struct_field (CrateNum crateNum, HirId id)
+{
+ auto it = hirStructFieldMappings.find (crateNum);
+ if (it == hirStructFieldMappings.end ())
+ return nullptr;
+
+ auto iy = it->second.find (id);
+ if (iy == it->second.end ())
+ return nullptr;
+
+ return iy->second;
+}
+
+void
Mappings::insert_local_defid_mapping (CrateNum crateNum, LocalDefId id,
HIR::Item *item)
{
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index a400265..3818be9 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -121,6 +121,10 @@ public:
void insert_hir_param (CrateNum crateNum, HirId id, HIR::FunctionParam *type);
HIR::FunctionParam *lookup_hir_param (CrateNum crateNum, HirId id);
+ void insert_hir_struct_field (CrateNum crateNum, HirId id,
+ HIR::StructExprField *type);
+ HIR::StructExprField *lookup_hir_struct_field (CrateNum crateNum, HirId id);
+
void walk_local_defids_for_crate (CrateNum crateNum,
std::function<bool (HIR::Item *)> cb);
@@ -159,6 +163,8 @@ private:
std::map<CrateNum, std::map<HirId, HIR::Expr *> > hirExprMappings;
std::map<CrateNum, std::map<HirId, HIR::Stmt *> > hirStmtMappings;
std::map<CrateNum, std::map<HirId, HIR::FunctionParam *> > hirParamMappings;
+ std::map<CrateNum, std::map<HirId, HIR::StructExprField *> >
+ hirStructFieldMappings;
// location info
std::map<CrateNum, std::map<NodeId, Location> > locations;
diff --git a/gcc/testsuite/rust.test/compilable/struct_init_3.rs b/gcc/testsuite/rust.test/compilable/struct_init_3.rs
new file mode 100644
index 0000000..fb1e58e
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/struct_init_3.rs
@@ -0,0 +1,10 @@
+struct Foo {
+ a: i32,
+ b: i32,
+}
+
+fn main() {
+ let a = 1;
+ let b = 2;
+ let c = Foo { a, b };
+}