aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-08-14 18:19:06 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-08-19 15:30:19 +0100
commit3475f10cbf58ff748298be438a4bf8cf98fec4ab (patch)
treeb8d15877eb5f6790d4a382acb66746c10fab2a04 /gcc
parent71cf0d44d3fceb235c95d5acaf92b498f8cf923b (diff)
downloadgcc-3475f10cbf58ff748298be438a4bf8cf98fec4ab.zip
gcc-3475f10cbf58ff748298be438a4bf8cf98fec4ab.tar.gz
gcc-3475f10cbf58ff748298be438a4bf8cf98fec4ab.tar.bz2
Add QualifiedPathInExpression name resolution
Qualified paths such as: <Foo as Bar>::A give the ability to resolve to trait-impls or trait-items directly. It is a type of projection. Remember trait impl blocks have the relevant canonical path so we can resolve with canonical paths and reuse the existing path in expression code.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/ast/rust-path.h17
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h17
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-toplevel.h13
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.cc117
4 files changed, 143 insertions, 21 deletions
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index 011ac3e..74ea795 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -771,11 +771,9 @@ struct QualifiedPathType
{
private:
std::unique_ptr<Type> type_to_invoke_on;
-
- // bool has_as_clause;
TypePath trait_path;
-
Location locus;
+ NodeId node_id;
public:
// Constructor
@@ -783,13 +781,15 @@ public:
Location locus = Location (),
TypePath trait_path = TypePath::create_error ())
: type_to_invoke_on (std::move (invoke_on_type)),
- trait_path (std::move (trait_path)), locus (locus)
+ trait_path (std::move (trait_path)), locus (locus),
+ node_id (Analysis::Mappings::get ()->get_next_node_id ())
{}
// Copy constructor uses custom deep copy for Type to preserve polymorphism
QualifiedPathType (QualifiedPathType const &other)
: trait_path (other.trait_path), locus (other.locus)
{
+ node_id = other.node_id;
// guard to prevent null dereference
if (other.type_to_invoke_on != nullptr)
type_to_invoke_on = other.type_to_invoke_on->clone_type ();
@@ -801,6 +801,7 @@ public:
// overload assignment operator to use custom clone method
QualifiedPathType &operator= (QualifiedPathType const &other)
{
+ node_id = other.node_id;
trait_path = other.trait_path;
locus = other.locus;
@@ -846,6 +847,8 @@ public:
rust_assert (has_as_clause ());
return trait_path;
}
+
+ NodeId get_node_id () const { return node_id; }
};
/* AST node representing a qualified path-in-expression pattern (path that
@@ -855,6 +858,7 @@ class QualifiedPathInExpression : public PathPattern, public PathExpr
std::vector<Attribute> outer_attrs;
QualifiedPathType path_type;
Location locus;
+ NodeId _node_id;
public:
std::string as_string () const override;
@@ -864,7 +868,8 @@ public:
std::vector<Attribute> outer_attrs, Location locus)
: PathPattern (std::move (path_segments)),
outer_attrs (std::move (outer_attrs)),
- path_type (std::move (qual_path_type)), locus (locus)
+ path_type (std::move (qual_path_type)), locus (locus),
+ _node_id (Analysis::Mappings::get ()->get_next_node_id ())
{}
/* TODO: maybe make a shortcut constructor that has QualifiedPathType elements
@@ -907,6 +912,8 @@ public:
outer_attrs = std::move (new_attrs);
}
+ NodeId get_node_id () const override { return _node_id; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h
index e7e37d4..c5f88f9 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.h
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.h
@@ -39,10 +39,22 @@ public:
resolver.resolve_path (expr);
}
+ static void go (AST::QualifiedPathInExpression *expr, NodeId parent)
+ {
+ ResolvePath resolver (parent);
+ resolver.resolve_path (expr);
+ }
+
private:
ResolvePath (NodeId parent) : ResolverBase (parent) {}
void resolve_path (AST::PathInExpression *expr);
+
+ void resolve_path (AST::QualifiedPathInExpression *expr);
+
+ void resolve_segments (CanonicalPath prefix, size_t offs,
+ std::vector<AST::PathExprSegment> &segs,
+ NodeId expr_node_id, Location expr_locus);
};
class ResolveExpr : public ResolverBase
@@ -75,6 +87,11 @@ public:
ResolvePath::go (&expr, parent);
}
+ void visit (AST::QualifiedPathInExpression &expr) override
+ {
+ ResolvePath::go (&expr, parent);
+ }
+
void visit (AST::ReturnExpr &expr) override
{
if (expr.has_returned_expr ())
diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
index 2c1de66..1239206 100644
--- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h
+++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
@@ -206,6 +206,19 @@ public:
impl_type_seg);
CanonicalPath impl_prefix = prefix.append (projection);
+ resolver->get_name_scope ().insert (
+ impl_prefix, impl_block.get_node_id (), impl_block.get_locus (), false,
+ [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+ RichLocation r (impl_block.get_locus ());
+ r.add_range (locus);
+ rust_error_at (r, "redefined multiple times");
+ });
+ resolver->insert_new_definition (impl_block.get_node_id (),
+ Definition{impl_block.get_node_id (),
+ impl_block.get_node_id ()});
+ resolver->insert_resolved_name (impl_block.get_node_id (),
+ impl_block.get_node_id ());
+
for (auto &impl_item : impl_block.get_impl_items ())
ResolveToplevelImplItem::go (impl_item.get (), impl_prefix);
}
diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc
index 5b24816..5b6bb24 100644
--- a/gcc/rust/resolve/rust-ast-resolve.cc
+++ b/gcc/rust/resolve/rust-ast-resolve.cc
@@ -483,12 +483,13 @@ void
ResolvePath::resolve_path (AST::PathInExpression *expr)
{
// resolve root segment first then apply segments in turn
- AST::PathExprSegment &root_segment = expr->get_segments ().at (0);
+ std::vector<AST::PathExprSegment> &segs = expr->get_segments ();
+ AST::PathExprSegment &root_segment = segs.at (0);
AST::PathIdentSegment &root_ident_seg = root_segment.get_ident_segment ();
bool segment_is_type = false;
CanonicalPath root_seg_path
- = CanonicalPath::new_seg (expr->get_node_id (),
+ = CanonicalPath::new_seg (root_segment.get_node_id (),
root_ident_seg.as_string ());
// name scope first
@@ -515,7 +516,7 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
{
rust_error_at (expr->get_locus (),
"Cannot find path %<%s%> in this scope",
- expr->as_string ().c_str ());
+ root_segment.as_string ().c_str ());
return;
}
@@ -531,7 +532,8 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
}
}
- if (expr->is_single_segment ())
+ bool is_single_segment = segs.size () == 1;
+ if (is_single_segment)
{
if (segment_is_type)
resolver->insert_resolved_type (expr->get_node_id (), resolved_node);
@@ -544,11 +546,97 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
return;
}
+ resolve_segments (root_seg_path, 1, expr->get_segments (),
+ expr->get_node_id (), expr->get_locus ());
+}
+
+void
+ResolvePath::resolve_path (AST::QualifiedPathInExpression *expr)
+{
+ AST::QualifiedPathType &root_segment = expr->get_qualified_path_type ();
+
+ bool canonicalize_type_with_generics = false;
+ ResolveType::go (&root_segment.get_as_type_path (),
+ root_segment.get_node_id (),
+ canonicalize_type_with_generics);
+
+ ResolveType::go (root_segment.get_type ().get (), root_segment.get_node_id (),
+ canonicalize_type_with_generics);
+
+ bool canonicalize_type_args = true;
+ bool type_resolve_generic_args = true;
+
+ CanonicalPath impl_type_seg
+ = ResolveTypeToCanonicalPath::resolve (*root_segment.get_type ().get (),
+ canonicalize_type_args,
+ type_resolve_generic_args);
+
+ CanonicalPath trait_type_seg
+ = ResolveTypeToCanonicalPath::resolve (root_segment.get_as_type_path (),
+ canonicalize_type_args,
+ type_resolve_generic_args);
+ CanonicalPath root_seg_path
+ = TraitImplProjection::resolve (root_segment.get_node_id (), trait_type_seg,
+ impl_type_seg);
+ bool segment_is_type = false;
+
+ // name scope first
+ if (resolver->get_name_scope ().lookup (root_seg_path, &resolved_node))
+ {
+ segment_is_type = false;
+ resolver->insert_resolved_name (root_segment.get_node_id (),
+ resolved_node);
+ resolver->insert_new_definition (root_segment.get_node_id (),
+ Definition{expr->get_node_id (),
+ parent});
+ }
+ // check the type scope
+ else if (resolver->get_type_scope ().lookup (root_seg_path, &resolved_node))
+ {
+ segment_is_type = true;
+ resolver->insert_resolved_type (root_segment.get_node_id (),
+ resolved_node);
+ resolver->insert_new_definition (root_segment.get_node_id (),
+ Definition{expr->get_node_id (),
+ parent});
+ }
+ else
+ {
+ rust_error_at (expr->get_locus (),
+ "Cannot find path %<%s%> in this scope",
+ root_segment.as_string ().c_str ());
+ return;
+ }
+
+ bool is_single_segment = expr->get_segments ().empty ();
+ if (is_single_segment)
+ {
+ if (segment_is_type)
+ resolver->insert_resolved_type (expr->get_node_id (), resolved_node);
+ else
+ resolver->insert_resolved_name (expr->get_node_id (), resolved_node);
+
+ resolver->insert_new_definition (expr->get_node_id (),
+ Definition{expr->get_node_id (),
+ parent});
+ return;
+ }
+
+ resolve_segments (root_seg_path, 0, expr->get_segments (),
+ expr->get_node_id (), expr->get_locus ());
+}
+
+void
+ResolvePath::resolve_segments (CanonicalPath prefix, size_t offs,
+ std::vector<AST::PathExprSegment> &segs,
+ NodeId expr_node_id, Location expr_locus)
+{
// we can attempt to resolve this path fully
- CanonicalPath path = root_seg_path;
- for (size_t i = 1; i < expr->get_segments ().size (); i++)
+ CanonicalPath path = prefix;
+ bool segment_is_type = false;
+ for (size_t i = offs; i < segs.size (); i++)
{
- AST::PathExprSegment &seg = expr->get_segments ().at (i);
+ AST::PathExprSegment &seg = segs.at (i);
auto s = ResolvePathSegmentToCanonicalPath::resolve (seg);
path = path.append (s);
@@ -560,8 +648,7 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
{
resolver->insert_resolved_name (seg.get_node_id (), resolved_node);
resolver->insert_new_definition (seg.get_node_id (),
- Definition{expr->get_node_id (),
- parent});
+ Definition{expr_node_id, parent});
}
// check the type scope
else if (resolver->get_type_scope ().lookup (path, &resolved_node))
@@ -569,8 +656,7 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
segment_is_type = true;
resolver->insert_resolved_type (seg.get_node_id (), resolved_node);
resolver->insert_new_definition (seg.get_node_id (),
- Definition{expr->get_node_id (),
- parent});
+ Definition{expr_node_id, parent});
}
else
{
@@ -621,13 +707,12 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
if (resolved_node != UNKNOWN_NODEID)
{
if (segment_is_type)
- resolver->insert_resolved_type (expr->get_node_id (), resolved_node);
+ resolver->insert_resolved_type (expr_node_id, resolved_node);
else
- resolver->insert_resolved_name (expr->get_node_id (), resolved_node);
+ resolver->insert_resolved_name (expr_node_id, resolved_node);
- resolver->insert_new_definition (expr->get_node_id (),
- Definition{expr->get_node_id (),
- parent});
+ resolver->insert_new_definition (expr_node_id,
+ Definition{expr_node_id, parent});
}
}