diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-04-22 12:15:22 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-04-22 12:15:22 +0000 |
commit | 4337aea3be387921ee60520d2188906d8762367b (patch) | |
tree | ea9540ded2e2be710336c3ed7a0c0d4de72f1e99 | |
parent | b392376cc521230c8b254841ab036541317dc907 (diff) | |
parent | bdd1b86ccb87d942a24dd60c01736e439ad57087 (diff) | |
download | gcc-4337aea3be387921ee60520d2188906d8762367b.zip gcc-4337aea3be387921ee60520d2188906d8762367b.tar.gz gcc-4337aea3be387921ee60520d2188906d8762367b.tar.bz2 |
Merge #1155
1155: Add base for visibility resolving r=CohenArthur a=CohenArthur
This adds a new visitor whose aim is to resolve the visibility of each VisItem in a crate. The crux of the implementation will be resolving `pub restricted` items, whose module needs to be resolved using name resolution/path resolution. On top of that, we will need to add a new visitor building a "tree" of modules, with a `accessible_from` or `is_child_of` method: All children of a module get to access its items whose visibility is inherited.
Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
-rw-r--r-- | gcc/rust/Make-lang.in | 1 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-item.h | 2 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-privacy-check.cc | 8 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-privacy-check.h | 1 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-privacy-common.h | 64 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-reachability.h | 2 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-visibility-resolver.cc | 163 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-visibility-resolver.h | 89 | ||||
-rw-r--r-- | gcc/rust/util/rust-hir-map.cc | 17 | ||||
-rw-r--r-- | gcc/rust/util/rust-hir-map.h | 7 |
10 files changed, 352 insertions, 2 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 82a4d6b..d25f403 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -93,6 +93,7 @@ GRS_OBJS = \ rust/rust-privacy-check.o \ rust/rust-privacy-ctx.o \ rust/rust-reachability.o \ + rust/rust-visibility-resolver.o \ rust/rust-tyty.o \ rust/rust-tyctx.o \ rust/rust-tyty-bounds.o \ diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 2f69630..2e28207 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -549,7 +549,7 @@ public: const Analysis::NodeMapping &get_mappings () const { return mappings; } }; -// Visibility of item - if the item has it, then it is some form of public +// Visibility of an item struct Visibility { public: diff --git a/gcc/rust/privacy/rust-privacy-check.cc b/gcc/rust/privacy/rust-privacy-check.cc index ccef318..ccfed2c 100644 --- a/gcc/rust/privacy/rust-privacy-check.cc +++ b/gcc/rust/privacy/rust-privacy-check.cc @@ -19,6 +19,8 @@ #include "rust-privacy-check.h" #include "rust-reachability.h" #include "rust-hir-type-check.h" +#include "rust-hir-map.h" +#include "rust-visibility-resolver.h" extern bool saw_errors (void); @@ -29,10 +31,16 @@ void Resolver::resolve (HIR::Crate &crate) { PrivacyContext ctx; + auto mappings = Analysis::Mappings::get (); + + auto resolver = VisibilityResolver (*mappings); + resolver.go (crate); + auto ty_ctx = ::Rust::Resolver::TypeCheckContext::get (); auto visitor = ReachabilityVisitor (ctx, *ty_ctx); const auto &items = crate.items; + for (auto &item : items) { if (item->get_hir_kind () == HIR::Node::VIS_ITEM) diff --git a/gcc/rust/privacy/rust-privacy-check.h b/gcc/rust/privacy/rust-privacy-check.h index 47fe7df..290b5ea 100644 --- a/gcc/rust/privacy/rust-privacy-check.h +++ b/gcc/rust/privacy/rust-privacy-check.h @@ -19,7 +19,6 @@ #ifndef RUST_PRIVACY_CHECK_H #define RUST_PRIVACY_CHECK_H -#include "rust-hir-map.h" #include "rust-hir.h" #include "rust-hir-expr.h" #include "rust-hir-stmt.h" diff --git a/gcc/rust/privacy/rust-privacy-common.h b/gcc/rust/privacy/rust-privacy-common.h new file mode 100644 index 0000000..145eac7 --- /dev/null +++ b/gcc/rust/privacy/rust-privacy-common.h @@ -0,0 +1,64 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-mapping-common.h" + +namespace Rust { +namespace Privacy { + +/** + * Visibility class related specifically to DefIds. This class allows defining + * the visibility of an item with regard to a specific module. + */ +class ModuleVisibility +{ +public: + enum Type + { + Unknown, + Private, + Public, + Restricted, + }; + + ModuleVisibility () : kind (Unknown), module_id (UNKNOWN_DEFID) {} + + static ModuleVisibility create_restricted (DefId module_id) + { + return ModuleVisibility (Type::Restricted, module_id); + } + + static ModuleVisibility create_public () + { + return ModuleVisibility (Type::Public, UNKNOWN_DEFID); + } + + Type get_kind () const { return kind; } + + const DefId &get_module_id () const { return module_id; } + +private: + ModuleVisibility (Type kind, DefId module_id) + : kind (kind), module_id (module_id) + {} + + Type kind; + DefId module_id; +}; +} // namespace Privacy +} // namespace Rust diff --git a/gcc/rust/privacy/rust-reachability.h b/gcc/rust/privacy/rust-reachability.h index e61fbdf..e0bc4f5 100644 --- a/gcc/rust/privacy/rust-reachability.h +++ b/gcc/rust/privacy/rust-reachability.h @@ -46,6 +46,8 @@ public: : current_level (ReachLevel::Reachable), ctx (ctx), ty_ctx (ty_ctx) {} + // FIXME: Add `go` method which takes an `HIR::Crate &` as argument + /** * Visit all the predicates of all the generic types of a given item, marking * them as reachable or not. diff --git a/gcc/rust/privacy/rust-visibility-resolver.cc b/gcc/rust/privacy/rust-visibility-resolver.cc new file mode 100644 index 0000000..0b7a529 --- /dev/null +++ b/gcc/rust/privacy/rust-visibility-resolver.cc @@ -0,0 +1,163 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-visibility-resolver.h" +#include "rust-ast.h" +#include "rust-hir.h" +#include "rust-hir-item.h" + +namespace Rust { +namespace Privacy { + +VisibilityResolver::VisibilityResolver (Analysis::Mappings &mappings) + : mappings (mappings) +{} + +void +VisibilityResolver::go (HIR::Crate &crate) +{ + module_stack.push_back (crate.get_mappings ().get_defid ()); + mappings.insert_visibility (crate.get_mappings ().get_defid (), + ModuleVisibility::create_public ()); + + for (auto &item : crate.items) + { + if (item->get_hir_kind () == HIR::Node::VIS_ITEM) + { + auto vis_item = static_cast<HIR::VisItem *> (item.get ()); + vis_item->accept_vis (*this); + } + } +} + +bool +VisibilityResolver::resolve_visibility (const HIR::Visibility &visibility, + ModuleVisibility &to_resolve) +{ + switch (visibility.get_vis_type ()) + { + case HIR::Visibility::PRIVATE: + to_resolve = ModuleVisibility::create_restricted (peek_module ()); + return true; + case HIR::Visibility::PUBLIC: + // FIXME: We need to handle the restricted path here + // FIXME: We also need to handle 2015 vs 2018 edition conflicts + to_resolve = ModuleVisibility::create_public (); + return true; + default: + return false; + } +} + +DefId +VisibilityResolver::peek_module () +{ + // We're always inserting a top module - the crate + // But we have to check otherwise `.back()` is UB + rust_assert (!module_stack.empty ()); + + return module_stack.back (); +} + +void +VisibilityResolver::visit (HIR::Module &mod) +{ + module_stack.push_back (mod.get_mappings ().get_defid ()); + + for (auto &item : mod.get_items ()) + { + if (item->get_hir_kind () == HIR::Node::VIS_ITEM) + { + auto vis_item = static_cast<HIR::VisItem *> (item.get ()); + vis_item->accept_vis (*this); + } + } + + module_stack.pop_back (); +} + +void +VisibilityResolver::visit (HIR::ExternCrate &crate) +{} + +void +VisibilityResolver::visit (HIR::UseDeclaration &use_decl) +{} + +void +VisibilityResolver::visit (HIR::Function &func) +{} + +void +VisibilityResolver::visit (HIR::TypeAlias &type_alias) +{} + +void +VisibilityResolver::visit (HIR::StructStruct &struct_item) +{} + +void +VisibilityResolver::visit (HIR::TupleStruct &tuple_struct) +{} + +void +VisibilityResolver::visit (HIR::Enum &enum_item) +{ + ModuleVisibility vis; + if (!resolve_visibility (enum_item.get_visibility (), vis)) + return; + + mappings.insert_visibility (enum_item.get_mappings ().get_defid (), vis); + for (auto &variant : enum_item.get_variants ()) + mappings.insert_visibility (variant->get_mappings ().get_defid (), vis); +} + +void +VisibilityResolver::visit (HIR::Union &union_item) +{} + +void +VisibilityResolver::visit (HIR::ConstantItem &const_item) +{} + +void +VisibilityResolver::visit (HIR::StaticItem &static_item) +{} + +void +VisibilityResolver::visit (HIR::Trait &trait) +{ + ModuleVisibility vis; + if (!resolve_visibility (trait.get_visibility (), vis)) + return; + + mappings.insert_visibility (trait.get_mappings ().get_defid (), vis); + for (auto &item : trait.get_trait_items ()) + mappings.insert_visibility (item->get_mappings ().get_defid (), vis); +} + +void +VisibilityResolver::visit (HIR::ImplBlock &impl) +{} + +void +VisibilityResolver::visit (HIR::ExternBlock &block) +{} + +} // namespace Privacy +} // namespace Rust diff --git a/gcc/rust/privacy/rust-visibility-resolver.h b/gcc/rust/privacy/rust-visibility-resolver.h new file mode 100644 index 0000000..394c3d4 --- /dev/null +++ b/gcc/rust/privacy/rust-visibility-resolver.h @@ -0,0 +1,89 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_VISIBILITY_H +#define RUST_VISIBILITY_H + +#include "rust-hir.h" +#include "rust-hir-expr.h" +#include "rust-hir-stmt.h" +#include "rust-hir-item.h" +#include "rust-hir-map.h" +#include "rust-hir-visitor.h" + +namespace Rust { +namespace Privacy { + +class VisibilityResolver : public HIR::HIRVisItemVisitor +{ +public: + VisibilityResolver (Analysis::Mappings &mappings); + + /** + * Perform visibility resolving on an entire crate + */ + void go (HIR::Crate &crate); + + /** + * Resolve the visibility of an item to its ModuleVisibility. This function + * emits errors if necessary. The contents of the to_resolve parameter will be + * overwritten on success. + * + * @param visibility Visibility of the item to resolve + * @param to_resolve ModuleVisibility reference to fill on success. + * + * @return false on error, true if the resolving was successful. + */ + bool resolve_visibility (const HIR::Visibility &visibility, + ModuleVisibility &to_resolve); + + /** + * Get the DefId of the parent module we are currently visiting. + * + * @return UNKNOWN_DEFID if the module stack is empty, a valid `DefId` + * otherwise + */ + DefId peek_module (); + + virtual void visit (HIR::Module &mod); + virtual void visit (HIR::ExternCrate &crate); + virtual void visit (HIR::UseDeclaration &use_decl); + virtual void visit (HIR::Function &func); + virtual void visit (HIR::TypeAlias &type_alias); + virtual void visit (HIR::StructStruct &struct_item); + virtual void visit (HIR::TupleStruct &tuple_struct); + virtual void visit (HIR::Enum &enum_item); + virtual void visit (HIR::Union &union_item); + virtual void visit (HIR::ConstantItem &const_item); + virtual void visit (HIR::StaticItem &static_item); + virtual void visit (HIR::Trait &trait); + virtual void visit (HIR::ImplBlock &impl); + virtual void visit (HIR::ExternBlock &block); + +private: + /* Mappings to insert visibilities into */ + Analysis::Mappings &mappings; + + /* Stack of modules visited by this visitor */ + std::vector<DefId> module_stack; +}; + +} // namespace Privacy +} // namespace Rust + +#endif // !RUST_VISIBILITY_H diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index b08258c..ac1cf70 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -781,5 +781,22 @@ Mappings::lookup_macro_def (NodeId id, AST::MacroRulesDefinition **def) return true; } +void +Mappings::insert_visibility (DefId id, Privacy::ModuleVisibility visibility) +{ + visibility_map.insert ({id, visibility}); +} + +bool +Mappings::lookup_visibility (DefId id, Privacy::ModuleVisibility *def) +{ + auto it = visibility_map.find (id); + if (it == visibility_map.end ()) + return false; + + *def = it->second; + return true; +} + } // namespace Analysis } // namespace Rust diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index 9bac328..74fabdf 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -26,6 +26,7 @@ #include "rust-ast-full-decls.h" #include "rust-hir-full-decls.h" #include "rust-lang-item.h" +#include "rust-privacy-common.h" namespace Rust { namespace Analysis { @@ -295,6 +296,9 @@ public: bool lookup_macro_def (NodeId id, AST::MacroRulesDefinition **def); + void insert_visibility (DefId id, Privacy::ModuleVisibility visibility); + bool lookup_visibility (DefId id, Privacy::ModuleVisibility *def); + private: Mappings (); @@ -353,6 +357,9 @@ private: // crate names std::map<CrateNum, std::string> crate_names; + + // Low level visibility map for each DefId + std::map<DefId, Privacy::ModuleVisibility> visibility_map; }; } // namespace Analysis |