aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-06-05 16:40:13 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-06-05 16:40:13 +0100
commitf1526062d9c16d3224d350967788dec9e4e2bbee (patch)
treeaa26273a573d9308a63f0a753ab7c06fe21b19b2 /gcc
parent1b3d621f215c8dfe39f43b0c25f72a29aea89908 (diff)
downloadgcc-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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/ast/rust-item.h2
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-implitem.h90
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.h127
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-toplevel.h30
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.h37
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.cc6
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 &param : 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 ());