"declared identifiers");
}
+ if (Analysis::Mappings::get ().is_module (
+ resolved->definition.get_node_id ()))
+ {
+ if (type.get_segments ().size () == 1)
+ {
+ if (auto resolved
+ = Builtins::find_builtin_node_id (type.as_string ()))
+ {
+ ctx.map_usage (Usage (type.get_node_id ()),
+ Definition (*resolved), Namespace::Types);
+
+ // In that specific case, we also override the segment resolution
+ // as it causes issues later down the line during typechecking
+ ctx.map_usage (Usage (unwrap_segment_node_id (
+ type.get_segments ().front ())),
+ Definition (*resolved), Namespace::Types);
+ }
+ else
+ {
+ rust_error_at (type.get_locus (), ErrorCode::E0573,
+ "expected type, found module %qs",
+ unwrap_segment_error_string (type).c_str ());
+ }
+ }
+
+ return;
+ }
+
ctx.map_usage (Usage (type.get_node_id ()),
Definition (resolved->definition.get_node_id ()),
Namespace::Types);
#ifndef RUST_NAME_RESOLVER_2_0_H
#define RUST_NAME_RESOLVER_2_0_H
+#include "rust-mapping-common.h"
+
namespace Rust {
namespace Resolver2_0 {
class Definition
{
public:
+ explicit Definition () : id (UNKNOWN_NODEID) {}
explicit Definition (NodeId id) : id (id) {}
NodeId id;
unit_type);
}
+tl::optional<NodeId>
+find_builtin_node_id (const std::string &name)
+{
+ for (size_t i = 0; i < builtin_count; i++)
+ if (strcmp (name.c_str (), builtin_names[i]) == 0)
+ return builtin_node_ids[i];
+
+ return tl::nullopt;
+}
+
} // namespace Builtins
} // namespace Resolver2_0
} // namespace Rust
#ifndef RUST_RESOLVE_BUILTINS_H
#define RUST_RESOLVE_BUILTINS_H
+#include "optional.h"
+#include "rust-ast.h"
+
namespace Rust {
namespace Resolver2_0 {
void setup_lang_prelude (NameResolutionContext &ctx);
void setup_type_ctx ();
+// Return the NodeId associated with a builtin type name if it exists
+tl::optional<NodeId> find_builtin_node_id (const std::string &name);
+
} // namespace Builtins
} // namespace Resolver2_0
} // namespace Rust
void
TopLevel::visit (AST::Module &module)
{
- DefaultResolver::visit (module);
-
if (Analysis::Mappings::get ().lookup_glob_container (module.get_node_id ())
== tl::nullopt)
Analysis::Mappings::get ().insert_glob_container (module.get_node_id (),
&module);
+
+ insert_or_error_out (module.get_name (), module, Namespace::Types);
+
+ Analysis::Mappings::get ().insert_module_id (module.get_node_id ());
+
+ DefaultResolver::visit (module);
}
void
glob_containers[id] = container;
}
+void
+Mappings::insert_module_id (NodeId id)
+{
+ module_ids.insert (id);
+}
+
+bool
+Mappings::is_module (NodeId id)
+{
+ return module_ids.find (id) != module_ids.end ();
+}
+
tl::optional<AST::GlobContainer *>
Mappings::lookup_glob_container (NodeId id)
{
void insert_glob_container (NodeId, AST::GlobContainer *);
tl::optional<AST::GlobContainer *> lookup_glob_container (NodeId id);
+
+ void insert_module_id (NodeId);
+ bool is_module (NodeId id);
+
void insert_module_child (NodeId module, NodeId child);
tl::optional<std::vector<NodeId> &> lookup_module_children (NodeId module);
// Module tree maps
// Maps each module's node id to a list of its children
+ // TODO: I think these are only used by the old resolved and can be removed
std::map<NodeId, std::vector<NodeId>> module_child_map;
std::map<NodeId, std::vector<Resolver::CanonicalPath>> module_child_items;
std::map<NodeId, NodeId> child_to_parent_module_map;
+
std::map<NodeId, AST::GlobContainer *> glob_containers;
+ std::set<NodeId> module_ids;
// AST mappings
std::map<NodeId, AST::Item *> ast_item_mappings;
--- /dev/null
+#![feature(no_core)]
+#![no_core]
+
+mod foo {
+ mod bar {}
+
+ struct bar; // { dg-error "defined multiple times" }
+}
--- /dev/null
+#![feature(no_core)]
+#![no_core]
+
+mod foo {
+ mod bar {}
+
+ fn baz() -> bar {} // { dg-error "expected type, found module" }
+}