diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-06-05 16:40:13 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-06-05 16:40:13 +0100 |
commit | f1526062d9c16d3224d350967788dec9e4e2bbee (patch) | |
tree | aa26273a573d9308a63f0a753ab7c06fe21b19b2 | |
parent | 1b3d621f215c8dfe39f43b0c25f72a29aea89908 (diff) | |
download | gcc-f1526062d9c16d3224d350967788dec9e4e2bbee.zip gcc-f1526062d9c16d3224d350967788dec9e4e2bbee.tar.gz gcc-f1526062d9c16d3224d350967788dec9e4e2bbee.tar.bz2 |
Add initial name resolution for traits and trait impls
We need to add name resolution for traits and trait impls. We cannot start
working with trait obligations untill we can actually implment a basic trait first.
Addresses: #395
-rw-r--r-- | gcc/rust/ast/rust-item.h | 2 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-implitem.h | 90 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-item.h | 127 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-toplevel.h | 30 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-type.h | 37 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve.cc | 6 |
6 files changed, 292 insertions, 0 deletions
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index fecb862..a9da337 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -3420,6 +3420,8 @@ public: // Returns whether trait has inner attributes. bool has_inner_attrs () const { return !inner_attrs.empty (); } + Identifier get_identifier () const { return name; } + // Mega-constructor Trait (Identifier name, bool is_unsafe, std::vector<std::unique_ptr<GenericParam> > generic_params, diff --git a/gcc/rust/resolve/rust-ast-resolve-implitem.h b/gcc/rust/resolve/rust-ast-resolve-implitem.h index fe0eecb..576cd3e 100644 --- a/gcc/rust/resolve/rust-ast-resolve-implitem.h +++ b/gcc/rust/resolve/rust-ast-resolve-implitem.h @@ -37,6 +37,12 @@ public: item->accept_vis (resolver); } + static void go (AST::TraitImplItem *item, const CanonicalPath &prefix) + { + ResolveToplevelImplItem resolver (prefix); + item->accept_vis (resolver); + } + void visit (AST::ConstantItem &constant) override { auto path @@ -95,6 +101,90 @@ private: const CanonicalPath &prefix; }; +class ResolveTopLevelTraitItems : public ResolverBase +{ + using Rust::Resolver::ResolverBase::visit; + +public: + static void go (AST::TraitItem *item, + const CanonicalPath &prefix = CanonicalPath::create_empty ()) + { + ResolveTopLevelTraitItems resolver (prefix); + item->accept_vis (resolver); + }; + + void visit (AST::TraitItemFunc &function) override + { + auto path = prefix.append ( + ResolveTraitItemFunctionToCanonicalPath::resolve (function)); + resolver->get_name_scope ().insert ( + path, function.get_node_id (), function.get_locus (), false, + [&] (const CanonicalPath &, NodeId, Location locus) -> void { + RichLocation r (function.get_locus ()); + r.add_range (locus); + rust_error_at (r, "redefined multiple times"); + }); + resolver->insert_new_definition (function.get_node_id (), + Definition{function.get_node_id (), + function.get_node_id ()}); + } + + void visit (AST::TraitItemMethod &method) override + { + auto path + = prefix.append (ResolveTraitItemMethodToCanonicalPath::resolve (method)); + resolver->get_name_scope ().insert ( + path, method.get_node_id (), method.get_locus (), false, + [&] (const CanonicalPath &, NodeId, Location locus) -> void { + RichLocation r (method.get_locus ()); + r.add_range (locus); + rust_error_at (r, "redefined multiple times"); + }); + resolver->insert_new_definition (method.get_node_id (), + Definition{method.get_node_id (), + method.get_node_id ()}); + } + + void visit (AST::TraitItemConst &constant) override + { + auto path = prefix.append ( + ResolveTraitItemConstToCanonicalPath::resolve (constant)); + resolver->get_name_scope ().insert ( + path, constant.get_node_id (), constant.get_locus (), false, + [&] (const CanonicalPath &, NodeId, Location locus) -> void { + RichLocation r (constant.get_locus ()); + r.add_range (locus); + rust_error_at (r, "redefined multiple times"); + }); + resolver->insert_new_definition (constant.get_node_id (), + Definition{constant.get_node_id (), + constant.get_node_id ()}); + } + + void visit (AST::TraitItemType &type) override + { + auto path + = prefix.append (ResolveTraitItemTypeToCanonicalPath::resolve (type)); + resolver->get_name_scope ().insert ( + path, type.get_node_id (), type.get_locus (), false, + [&] (const CanonicalPath &, NodeId, Location locus) -> void { + RichLocation r (type.get_locus ()); + r.add_range (locus); + rust_error_at (r, "redefined multiple times"); + }); + resolver->insert_new_definition (type.get_node_id (), + Definition{type.get_node_id (), + type.get_node_id ()}); + } + +private: + ResolveTopLevelTraitItems (const CanonicalPath &prefix) + : ResolverBase (UNKNOWN_NODEID), prefix (prefix) + {} + + const CanonicalPath &prefix; +}; + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index dc16573..3800350 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -259,6 +259,133 @@ public: resolver->get_label_scope ().pop (); } + void visit (AST::TraitImpl &impl_block) override + { + NodeId scope_node_id = impl_block.get_node_id (); + resolver->get_type_scope ().push (scope_node_id); + + if (impl_block.has_generics ()) + { + for (auto &generic : impl_block.get_generic_params ()) + { + ResolveGenericParam::go (generic.get (), impl_block.get_node_id ()); + } + } + + bool canonicalize_type_with_generics = false; + NodeId trait_resolved_node + = ResolveType::go (&impl_block.get_trait_path (), + impl_block.get_node_id (), + canonicalize_type_with_generics); + if (trait_resolved_node == UNKNOWN_NODEID) + { + resolver->get_type_scope ().pop (); + return; + } + + NodeId type_resolved_node + = ResolveType::go (impl_block.get_type ().get (), + impl_block.get_node_id (), + canonicalize_type_with_generics); + if (type_resolved_node == UNKNOWN_NODEID) + { + resolver->get_type_scope ().pop (); + return; + } + + resolver->get_type_scope ().insert ( + CanonicalPath::get_big_self (), impl_block.get_type ()->get_node_id (), + impl_block.get_type ()->get_locus_slow ()); + + for (auto &impl_item : impl_block.get_impl_items ()) + impl_item->accept_vis (*this); + + resolver->get_type_scope ().peek ()->clear_name ( + CanonicalPath::get_big_self (), impl_block.get_type ()->get_node_id ()); + resolver->get_type_scope ().pop (); + } + + void visit (AST::Trait &trait) override + { + NodeId scope_node_id = trait.get_node_id (); + resolver->get_type_scope ().push (scope_node_id); + + // TODO + // we need to inject an implicit self TypeParam here + // see: https://doc.rust-lang.org/reference/items/traits.html + + if (trait.has_generics ()) + { + for (auto &generic : trait.get_generic_params ()) + { + ResolveGenericParam::go (generic.get (), trait.get_node_id ()); + } + } + + for (auto &item : trait.get_trait_items ()) + item->accept_vis (*this); + + resolver->get_type_scope ().pop (); + } + + void visit (AST::TraitItemFunc &func) override + { + NodeId scope_node_id = func.get_node_id (); + resolver->get_name_scope ().push (scope_node_id); + resolver->get_type_scope ().push (scope_node_id); + resolver->get_label_scope ().push (scope_node_id); + resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); + resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); + resolver->push_new_label_rib (resolver->get_type_scope ().peek ()); + + AST::TraitFunctionDecl &function = func.get_trait_function_decl (); + if (function.has_generics ()) + { + for (auto &generic : function.get_generic_params ()) + ResolveGenericParam::go (generic.get (), func.get_node_id ()); + } + + if (function.has_return_type ()) + ResolveType::go (function.get_return_type ().get (), func.get_node_id ()); + + // we make a new scope so the names of parameters are resolved and shadowed + // correctly + for (auto ¶m : function.get_function_params ()) + { + ResolveType::go (param.get_type ().get (), param.get_node_id ()); + PatternDeclaration::go (param.get_pattern ().get (), + param.get_node_id ()); + + // the mutability checker needs to verify for immutable decls the number + // of assignments are <1. This marks an implicit assignment + resolver->mark_assignment_to_decl (param.get_pattern ()->get_node_id (), + param.get_node_id ()); + } + + // trait items have an optional body + if (func.has_definition ()) + ResolveExpr::go (func.get_definition ().get (), func.get_node_id ()); + + resolver->get_name_scope ().pop (); + resolver->get_type_scope ().pop (); + resolver->get_label_scope ().pop (); + } + + void visit (AST::TraitItemMethod &) override + { + // TODO + } + + void visit (AST::TraitItemConst &) override + { + // TODO + } + + void visit (AST::TraitItemType &) override + { + // TODO + } + private: ResolveItem () : ResolverBase (UNKNOWN_NODEID) {} }; diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h index fa3f8a5..95685bc 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -145,6 +145,36 @@ public: ResolveToplevelImplItem::go (impl_item.get (), impl_prefix); } + void visit (AST::TraitImpl &impl_block) override + { + bool canonicalize_type_args = !impl_block.has_generics (); + bool type_resolve_generic_args = false; + CanonicalPath impl_type + = ResolveTypeToCanonicalPath::resolve (*impl_block.get_type ().get (), + canonicalize_type_args, + type_resolve_generic_args); + CanonicalPath impl_prefix = prefix.append (impl_type); + + for (auto &impl_item : impl_block.get_impl_items ()) + ResolveToplevelImplItem::go (impl_item.get (), impl_prefix); + } + + void visit (AST::Trait &trait) override + { + CanonicalPath path + = prefix.append (CanonicalPath (trait.get_identifier ())); + resolver->get_type_scope ().insert ( + path, trait.get_node_id (), trait.get_locus (), false, + [&] (const CanonicalPath &, NodeId, Location locus) -> void { + RichLocation r (trait.get_locus ()); + r.add_range (locus); + rust_error_at (r, "redefined multiple times"); + }); + + for (auto &item : trait.get_trait_items ()) + ResolveTopLevelTraitItems::go (item.get ()); + } + private: ResolveTopLevel (const CanonicalPath &prefix) : ResolverBase (UNKNOWN_NODEID), prefix (prefix) diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index a1dcb4c..05b347c3 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -52,6 +52,43 @@ public: } }; +class ResolveTraitItemFunctionToCanonicalPath +{ +public: + static CanonicalPath resolve (AST::TraitItemFunc &function) + { + return CanonicalPath ( + function.get_trait_function_decl ().get_identifier ()); + } +}; + +class ResolveTraitItemMethodToCanonicalPath +{ +public: + static CanonicalPath resolve (AST::TraitItemMethod &method) + { + return CanonicalPath (method.get_trait_method_decl ().get_identifier ()); + } +}; + +class ResolveTraitItemConstToCanonicalPath +{ +public: + static CanonicalPath resolve (AST::TraitItemConst &constant) + { + return CanonicalPath (constant.get_identifier ()); + } +}; + +class ResolveTraitItemTypeToCanonicalPath +{ +public: + static CanonicalPath resolve (AST::TraitItemType &type) + { + return CanonicalPath (type.get_identifier ()); + } +}; + class ResolveTypeToCanonicalPath : public ResolverBase { using Rust::Resolver::ResolverBase::visit; diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 41c6938..f97c97b 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -41,6 +41,9 @@ } \ while (0) +extern bool +saw_errors (void); + namespace Rust { namespace Resolver { @@ -322,6 +325,9 @@ NameResolution::go (AST::Crate &crate) for (auto it = crate.items.begin (); it != crate.items.end (); it++) ResolveTopLevel::go (it->get ()); + if (saw_errors ()) + return; + // next we can drill down into the items and their scopes for (auto it = crate.items.begin (); it != crate.items.end (); it++) ResolveItem::go (it->get ()); |