aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Herron <herron.philip@googlemail.com>2023-03-17 22:46:37 +0000
committerPhilip Herron <philip.herron@embecosm.com>2023-03-20 21:47:57 +0000
commita8662e89f84e91466acc09e28b4a289d298498ee (patch)
tree33cfd871de61c050019fdb3434a3bb6faed8ec36
parent70b83a23f508d3694aa08cda793bab118a9be768 (diff)
downloadgcc-a8662e89f84e91466acc09e28b4a289d298498ee.zip
gcc-a8662e89f84e91466acc09e28b4a289d298498ee.tar.gz
gcc-a8662e89f84e91466acc09e28b4a289d298498ee.tar.bz2
gccrs: support use declaration to write the type into the correct namespace
This builds upon the previous path resolution fixes so that it returns the resolved_node_id or UNKNOWN_NODEID on failure to resolve the use-path. It then exports the name to the current module namespace so it can be used. Fixes #850 #855 gcc/rust/ChangeLog: * ast/rust-ast.h: add const get_final_segment helper * hir/rust-ast-lower-enumitem.h: dont add an item mapping for enumitems * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): add enum to enum-items mappings * hir/rust-ast-lower-stmt.cc (ASTLoweringStmt::visit): likewise * hir/tree/rust-hir-item.h: add non const helper to get variants * resolve/rust-ast-resolve-item.cc (ResolveItem::visit): resolve the use declaration * resolve/rust-ast-resolve-path.cc (ResolvePath::resolve_path): handle self * resolve/rust-ast-resolve-toplevel.h: add enum item mappings to module mappings * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::resolve_root_path): ensure variant (TypeCheckExpr::resolve_segments): likewise * typecheck/rust-type-util.cc (query_type): lookup enum's * util/rust-hir-map.cc (Mappings::insert_hir_enumitem): enum item mappings (Mappings::lookup_hir_enumitem): likewise * util/rust-hir-map.h: likewise gcc/testsuite/ChangeLog: * rust/compile/issue-850.rs: New test. * rust/compile/issue-855.rs: New test. Signed-off-by: Philip Herron <herron.philip@googlemail.com>
-rw-r--r--gcc/rust/ast/rust-ast.h5
-rw-r--r--gcc/rust/hir/rust-ast-lower-enumitem.h1
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.cc15
-rw-r--r--gcc/rust/hir/rust-ast-lower-stmt.cc15
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h2
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.cc23
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-path.cc27
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-toplevel.h19
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-path.cc21
-rw-r--r--gcc/rust/typecheck/rust-type-util.cc19
-rw-r--r--gcc/rust/util/rust-hir-map.cc21
-rw-r--r--gcc/rust/util/rust-hir-map.h4
-rw-r--r--gcc/testsuite/rust/compile/issue-850.rs43
-rw-r--r--gcc/testsuite/rust/compile/issue-855.rs23
14 files changed, 220 insertions, 18 deletions
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 585bdb0..2c39cc7c 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -422,6 +422,11 @@ public:
}
std::vector<SimplePathSegment> &get_segments () { return segments; }
+
+ const SimplePathSegment &get_final_segment () const
+ {
+ return segments.back ();
+ }
};
// path-to-string inverse comparison operator
diff --git a/gcc/rust/hir/rust-ast-lower-enumitem.h b/gcc/rust/hir/rust-ast-lower-enumitem.h
index cc3e9e5..a8aa45a 100644
--- a/gcc/rust/hir/rust-ast-lower-enumitem.h
+++ b/gcc/rust/hir/rust-ast-lower-enumitem.h
@@ -46,7 +46,6 @@ public:
auto defid = resolver.translated->get_mappings ().get_defid ();
resolver.mappings->insert_defid_mapping (defid, resolver.translated);
- resolver.mappings->insert_hir_item (resolver.translated);
resolver.mappings->insert_location (hirid,
resolver.translated->get_locus ());
diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc
index 0ad4a84..eade1bc 100644
--- a/gcc/rust/hir/rust-ast-lower-item.cc
+++ b/gcc/rust/hir/rust-ast-lower-item.cc
@@ -274,11 +274,16 @@ ASTLoweringItem::visit (AST::Enum &enum_decl)
mappings->get_next_hir_id (crate_num),
mappings->get_next_localdef_id (crate_num));
- translated = new HIR::Enum (mapping, enum_decl.get_identifier (), vis,
- std::move (generic_params),
- std::move (where_clause), /* is_unit, */
- std::move (items), enum_decl.get_outer_attrs (),
- enum_decl.get_locus ());
+ HIR::Enum *hir_enum
+ = new HIR::Enum (mapping, enum_decl.get_identifier (), vis,
+ std::move (generic_params), std::move (where_clause),
+ std::move (items), enum_decl.get_outer_attrs (),
+ enum_decl.get_locus ());
+ translated = hir_enum;
+ for (auto &variant : hir_enum->get_variants ())
+ {
+ mappings->insert_hir_enumitem (hir_enum, variant.get ());
+ }
}
void
diff --git a/gcc/rust/hir/rust-ast-lower-stmt.cc b/gcc/rust/hir/rust-ast-lower-stmt.cc
index dbff8ad..5ba8db0 100644
--- a/gcc/rust/hir/rust-ast-lower-stmt.cc
+++ b/gcc/rust/hir/rust-ast-lower-stmt.cc
@@ -301,11 +301,16 @@ ASTLoweringStmt::visit (AST::Enum &enum_decl)
mappings->get_next_hir_id (crate_num),
mappings->get_next_localdef_id (crate_num));
- translated = new HIR::Enum (mapping, enum_decl.get_identifier (), vis,
- std::move (generic_params),
- std::move (where_clause), /* is_unit, */
- std::move (items), enum_decl.get_outer_attrs (),
- enum_decl.get_locus ());
+ HIR::Enum *hir_enum
+ = new HIR::Enum (mapping, enum_decl.get_identifier (), vis,
+ std::move (generic_params), std::move (where_clause),
+ std::move (items), enum_decl.get_outer_attrs (),
+ enum_decl.get_locus ());
+ translated = hir_enum;
+ for (auto &variant : hir_enum->get_variants ())
+ {
+ mappings->insert_hir_enumitem (hir_enum, variant.get ());
+ }
}
void
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index 7a2a39f..9ff9732 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -1966,6 +1966,8 @@ public:
return items;
}
+ std::vector<std::unique_ptr<EnumItem>> &get_variants () { return items; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc
index 385d4b0..de863a0 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-item.cc
@@ -983,7 +983,7 @@ flatten_use_dec_to_paths (const AST::UseDeclaration &use_item)
void
ResolveItem::visit (AST::UseDeclaration &use_item)
{
- auto to_resolve = flatten_use_dec_to_paths (use_item);
+ std::vector<AST::SimplePath> to_resolve = flatten_use_dec_to_paths (use_item);
// FIXME: I think this does not actually resolve glob use-decls and is going
// the wrong way about it. RFC #1560 specifies the following:
@@ -993,8 +993,27 @@ ResolveItem::visit (AST::UseDeclaration &use_item)
// importing module.
//
// Which is the opposite of what we're doing if I understand correctly?
+
+ NodeId current_module = resolver->peek_current_module_scope ();
for (auto &path : to_resolve)
- ResolvePath::go (&path);
+ {
+ rust_debug ("resolving use-decl path: [%s]", path.as_string ().c_str ());
+ NodeId resolved_node_id = ResolvePath::go (&path);
+ bool ok = resolved_node_id != UNKNOWN_NODEID;
+ if (!ok)
+ continue;
+
+ const AST::SimplePathSegment &final_seg = path.get_final_segment ();
+
+ auto decl
+ = CanonicalPath::new_seg (resolved_node_id, final_seg.as_string ());
+ mappings->insert_module_child_item (current_module, decl);
+
+ resolver->get_type_scope ().insert (decl, resolved_node_id,
+ path.get_locus (),
+ Rib::ItemType::Type);
+ rust_debug ("use-decl rexporting: [%s]", decl.get ().c_str ());
+ }
}
ResolveImplItems::ResolveImplItems (const CanonicalPath &prefix,
diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc
index c5b8dea..d8e6f90 100644
--- a/gcc/rust/resolve/rust-ast-resolve-path.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-path.cc
@@ -267,17 +267,20 @@ ResolvePath::resolve_path (AST::SimplePath *expr)
NodeId crate_scope_id = resolver->peek_crate_module_scope ();
NodeId module_scope_id = resolver->peek_current_module_scope ();
+ NodeId previous_resolved_node_id = UNKNOWN_NODEID;
NodeId resolved_node_id = UNKNOWN_NODEID;
for (size_t i = 0; i < expr->get_segments ().size (); i++)
{
- auto &segment = expr->get_segments ().at (i);
+ AST::SimplePathSegment &segment = expr->get_segments ().at (i);
bool is_first_segment = i == 0;
+ bool is_final_segment = i >= (expr->get_segments ().size () - 1);
resolved_node_id = UNKNOWN_NODEID;
if (segment.is_crate_path_seg ())
{
// what is the current crate scope node id?
module_scope_id = crate_scope_id;
+ previous_resolved_node_id = module_scope_id;
resolver->insert_resolved_name (segment.get_node_id (),
module_scope_id);
continue;
@@ -292,6 +295,7 @@ ResolvePath::resolve_path (AST::SimplePath *expr)
}
module_scope_id = resolver->peek_parent_module_scope ();
+ previous_resolved_node_id = module_scope_id;
resolver->insert_resolved_name (segment.get_node_id (),
module_scope_id);
continue;
@@ -348,6 +352,25 @@ ResolvePath::resolve_path (AST::SimplePath *expr)
}
}
+ // if we still have not resolved and this is the final segment and the
+ // final segment is self its likely the case: pub use
+ //
+ // result::Result::{self, Err, Ok};
+ //
+ // Then the resolved_node_id is just the previous one so long as it is a
+ // resolved node id
+ // rust_debug_loc (segment.get_locus (),
+ // "trying to resolve seg: [%s] first [%s] last [%s]",
+ // segment.get_segment_name ().c_str (),
+ // is_first_segment ? "true" : "false",
+ // is_final_segment ? "true" : "false");
+ if (resolved_node_id == UNKNOWN_NODEID && !is_first_segment
+ && is_final_segment && segment.is_lower_self ())
+ {
+ resolved_node_id = previous_resolved_node_id;
+ }
+
+ // final check
if (resolved_node_id == UNKNOWN_NODEID)
{
rust_error_at (segment.get_locus (),
@@ -360,6 +383,8 @@ ResolvePath::resolve_path (AST::SimplePath *expr)
{
module_scope_id = resolved_node_id;
}
+
+ previous_resolved_node_id = resolved_node_id;
}
resolved_node = resolved_node_id;
diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
index c705ea8..d784317 100644
--- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h
+++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
@@ -132,9 +132,12 @@ public:
rust_error_at (r, "redefined multiple times");
});
+ resolver->push_new_module_scope (enum_decl.get_node_id ());
for (auto &variant : enum_decl.get_variants ())
ResolveTopLevel::go (variant.get (), path, cpath);
+ resolver->pop_module_scope ();
+
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (enum_decl.get_node_id (), cpath);
@@ -156,6 +159,10 @@ public:
});
mappings->insert_canonical_path (item.get_node_id (), cpath);
+
+ NodeId current_module = resolver->peek_current_module_scope ();
+ mappings->insert_module_child_item (current_module, decl);
+ mappings->insert_module_child (current_module, item.get_node_id ());
}
void visit (AST::EnumItemTuple &item) override
@@ -174,6 +181,10 @@ public:
});
mappings->insert_canonical_path (item.get_node_id (), cpath);
+
+ NodeId current_module = resolver->peek_current_module_scope ();
+ mappings->insert_module_child_item (current_module, decl);
+ mappings->insert_module_child (current_module, item.get_node_id ());
}
void visit (AST::EnumItemStruct &item) override
@@ -192,6 +203,10 @@ public:
});
mappings->insert_canonical_path (item.get_node_id (), cpath);
+
+ NodeId current_module = resolver->peek_current_module_scope ();
+ mappings->insert_module_child_item (current_module, decl);
+ mappings->insert_module_child (current_module, item.get_node_id ());
}
void visit (AST::EnumItemDiscriminant &item) override
@@ -210,6 +225,10 @@ public:
});
mappings->insert_canonical_path (item.get_node_id (), cpath);
+
+ NodeId current_module = resolver->peek_current_module_scope ();
+ mappings->insert_module_child_item (current_module, decl);
+ mappings->insert_module_child (current_module, item.get_node_id ());
}
void visit (AST::StructStruct &struct_decl) override
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index cd0c670..88c927d 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -244,6 +244,19 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
return root_tyty;
}
+ // is it an enum item?
+ std::pair<HIR::Enum *, HIR::EnumItem *> enum_item_lookup
+ = mappings->lookup_hir_enumitem (ref);
+ bool is_enum_item = enum_item_lookup.first != nullptr
+ && enum_item_lookup.second != nullptr;
+ if (is_enum_item)
+ {
+ HirId expr_id = expr.get_mappings ().get_hirid ();
+ HirId variant_id
+ = enum_item_lookup.second->get_mappings ().get_hirid ();
+ context->insert_variant_definition (expr_id, variant_id);
+ }
+
// if we have a previous segment type
if (root_tyty != nullptr)
{
@@ -349,9 +362,13 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
const TyTy::VariantDef *variant = candidate.item.enum_field.variant;
HirId variant_id = variant->get_id ();
- HIR::Item *enum_item = mappings->lookup_hir_item (variant_id);
- rust_assert (enum_item != nullptr);
+ std::pair<HIR::Enum *, HIR::EnumItem *> enum_item_lookup
+ = mappings->lookup_hir_enumitem (variant_id);
+ bool enum_item_ok = enum_item_lookup.first != nullptr
+ && enum_item_lookup.second != nullptr;
+ rust_assert (enum_item_ok);
+ HIR::EnumItem *enum_item = enum_item_lookup.second;
resolved_node_id = enum_item->get_mappings ().get_nodeid ();
// insert the id of the variant we are resolved to
diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc
index da9a724..578e0c4 100644
--- a/gcc/rust/typecheck/rust-type-util.cc
+++ b/gcc/rust/typecheck/rust-type-util.cc
@@ -22,8 +22,6 @@
#include "rust-hir-type-check-implitem.h"
#include "rust-hir-type-check-item.h"
#include "rust-hir-type-check.h"
-#include "rust-hir-visitor.h"
-#include "rust-name-resolver.h"
#include "rust-casts.h"
#include "rust-unify.h"
#include "rust-coercion.h"
@@ -45,6 +43,23 @@ query_type (HirId reference, TyTy::BaseType **result)
context->insert_query (reference);
+ std::pair<HIR::Enum *, HIR::EnumItem *> enum_candidiate
+ = mappings->lookup_hir_enumitem (reference);
+ bool enum_candidiate_ok
+ = enum_candidiate.first != nullptr && enum_candidiate.second != nullptr;
+ if (enum_candidiate_ok)
+ {
+ HIR::Enum *parent = enum_candidiate.first;
+ HIR::EnumItem *enum_item = enum_candidiate.second;
+ rust_debug_loc (enum_item->get_locus (), "resolved item {%u} to",
+ reference);
+
+ *result = TypeCheckItem::Resolve (*parent);
+
+ context->query_completed (reference);
+ return true;
+ }
+
HIR::Item *item = mappings->lookup_hir_item (reference);
if (item != nullptr)
{
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index 57c0a3c..12f9be6 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -383,6 +383,27 @@ Mappings::lookup_hir_item (HirId id)
}
void
+Mappings::insert_hir_enumitem (HIR::Enum *parent, HIR::EnumItem *item)
+{
+ auto id = item->get_mappings ().get_hirid ();
+ auto result = lookup_hir_enumitem (id);
+ rust_assert (result.first == nullptr);
+
+ hirEnumItemMappings[id] = {parent, item};
+ insert_node_to_hir (item->get_mappings ().get_nodeid (), id);
+}
+
+std::pair<HIR::Enum *, HIR::EnumItem *>
+Mappings::lookup_hir_enumitem (HirId id)
+{
+ auto it = hirEnumItemMappings.find (id);
+ if (it == hirEnumItemMappings.end ())
+ return {nullptr, nullptr};
+
+ return it->second;
+}
+
+void
Mappings::insert_hir_trait_item (HIR::TraitItem *item)
{
auto id = item->get_mappings ().get_hirid ();
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index 9d6affa..4fd35d8 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -114,6 +114,9 @@ public:
void insert_hir_item (HIR::Item *item);
HIR::Item *lookup_hir_item (HirId id);
+ void insert_hir_enumitem (HIR::Enum *parent, HIR::EnumItem *item);
+ std::pair<HIR::Enum *, HIR::EnumItem *> lookup_hir_enumitem (HirId id);
+
void insert_hir_trait_item (HIR::TraitItem *item);
HIR::TraitItem *lookup_hir_trait_item (HirId id);
@@ -317,6 +320,7 @@ private:
std::map<HirId, HIR::Module *> hirModuleMappings;
std::map<HirId, HIR::Item *> hirItemMappings;
+ std::map<HirId, std::pair<HIR::Enum *, HIR::EnumItem *>> hirEnumItemMappings;
std::map<HirId, HIR::Type *> hirTypeMappings;
std::map<HirId, HIR::Expr *> hirExprMappings;
std::map<HirId, HIR::Stmt *> hirStmtMappings;
diff --git a/gcc/testsuite/rust/compile/issue-850.rs b/gcc/testsuite/rust/compile/issue-850.rs
new file mode 100644
index 0000000..531cbf4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-850.rs
@@ -0,0 +1,43 @@
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+mod option {
+ enum Option<T> {
+ #[lang = "None"]
+ None,
+ #[lang = "Some"]
+ Some(T),
+ }
+}
+
+pub use option::Option::{self, None, Some};
+
+fn divide(numerator: f64, denominator: f64) -> Option<f64> {
+ if denominator == 0.0 {
+ None
+ } else {
+ Some(numerator / denominator)
+ }
+}
+
+fn main() {
+ let result = divide(2.0, 3.0);
+
+ match result {
+ Some(x) => unsafe {
+ let a = "Result: %i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, x);
+ },
+ None => unsafe {
+ let a = "Cannot divide by 0\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ },
+ }
+}
diff --git a/gcc/testsuite/rust/compile/issue-855.rs b/gcc/testsuite/rust/compile/issue-855.rs
new file mode 100644
index 0000000..f48e3a1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-855.rs
@@ -0,0 +1,23 @@
+pub use result::Result::{self, Err, Ok};
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+mod result {
+ pub enum Result<T, E> {
+ #[lang = "Ok"]
+ Ok(T),
+
+ #[lang = "Err"]
+ Err(E),
+ }
+}
+
+pub fn test(a: i32) -> Result<i32, bool> {
+ if a > 5 {
+ Ok(123)
+ } else {
+ Err(false)
+ }
+}