}
std::vector<SimplePathSegment> &get_segments () { return segments; }
+
+ const SimplePathSegment &get_final_segment () const
+ {
+ return segments.back ();
+ }
};
// path-to-string inverse comparison operator
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 ());
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
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
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 */
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:
// 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,
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;
}
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;
}
}
+ // 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 (),
{
module_scope_id = resolved_node_id;
}
+
+ previous_resolved_node_id = resolved_node_id;
}
resolved_node = resolved_node_id;
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);
});
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
});
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
});
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
});
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
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)
{
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
#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"
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)
{
return it->second;
}
+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)
{
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);
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;
--- /dev/null
+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);
+ },
+ }
+}
--- /dev/null
+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)
+ }
+}