Skip to content

Commit 636ad7d

Browse files
bors[bot]philberty
andauthored
Merge #358
358: Canonical Paths for Name Resolution and handle TurboFish properly r=philberty a=philberty Add Canonical paths to name resolution In order to support name resolution and checks for duplicate definitions of names we need canonical paths for all DefId items such as inherent impl items and normal items. Consider: ```rust struct Foo<T>(T); impl Foo<f32> { fn name()... } impl Foo<i32> { fn name()... } ``` Each of the impl blocks have a name function but these are separate due to the concrete impl of the Parameter type passed in. The caveat here is that to call this Function name the programmer must be explicit in which implentation they wish to call such as: ```rust let a = Foo::<f32>::name(); ``` This lets the Path probe lookup the appropriate impl block. The problem here is that rust also allows for the compiler to infer the impl you wish such as: ```rust let a = Foo::name(); ``` This should fail since there are multiple candidates possible for this Path. Unless there might have only been one name function in which case it would have worked. This patch is also responsible to implement PathInExpression by iterating each segment and applying generic arguments as we go. Fixes #355 #335 #325 #353 Co-authored-by: Philip Herron <[email protected]>
2 parents ca8744d + 4ee35b6 commit 636ad7d

36 files changed

+2347
-440
lines changed

gcc/rust/backend/rust-compile-expr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ class CompileExpr : public HIRCompileBase
526526

527527
void visit (HIR::PathInExpression &expr) override
528528
{
529-
translated = ResolvePathRef::Compile (&expr, ctx);
529+
translated = ResolvePathRef::Compile (expr, ctx);
530530
}
531531

532532
void visit (HIR::LoopExpr &expr) override

gcc/rust/backend/rust-compile-resolve-path.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ class ResolvePathRef : public HIRCompileBase
3030
using Rust::Compile::HIRCompileBase::visit;
3131

3232
public:
33-
static Bexpression *Compile (HIR::Expr *expr, Context *ctx)
33+
static Bexpression *Compile (HIR::PathInExpression &expr, Context *ctx)
3434
{
3535
ResolvePathRef resolver (ctx);
36-
expr->accept_vis (resolver);
36+
expr.accept_vis (resolver);
3737
return resolver.resolved;
3838
}
3939

gcc/rust/hir/rust-ast-lower-item.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,12 +360,14 @@ class ASTLoweringItem : public ASTLoweringBase
360360
mappings->get_next_localdef_id (crate_num));
361361

362362
std::vector<std::unique_ptr<HIR::InherentImplItem> > impl_items;
363+
std::vector<HirId> impl_item_ids;
363364
for (auto &impl_item : impl_block.get_impl_items ())
364365
{
365366
HIR::InherentImplItem *lowered
366367
= ASTLowerImplItem::translate (impl_item.get (),
367368
mapping.get_hirid ());
368369
impl_items.push_back (std::unique_ptr<HIR::InherentImplItem> (lowered));
370+
impl_item_ids.push_back (lowered->get_impl_mappings ().get_hirid ());
369371
}
370372

371373
translated
@@ -381,6 +383,13 @@ class ASTLoweringItem : public ASTLoweringBase
381383
translated);
382384
mappings->insert_location (crate_num, mapping.get_hirid (),
383385
impl_block.get_locus ());
386+
387+
for (auto &impl_item_id : impl_item_ids)
388+
{
389+
mappings->insert_impl_item_mapping (impl_item_id,
390+
static_cast<HIR::InherentImpl *> (
391+
translated));
392+
}
384393
}
385394

386395
private:

gcc/rust/hir/tree/rust-hir-path.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,12 @@ class PathPattern : public Pattern
255255
}
256256
}
257257

258+
size_t get_num_segments () const { return segments.size (); }
259+
260+
std::vector<PathExprSegment> &get_segments () { return segments; }
261+
262+
PathExprSegment &get_root_seg () { return segments.at (0); }
263+
258264
PathExprSegment get_final_segment () const { return segments.back (); }
259265
};
260266

gcc/rust/resolve/rust-ast-resolve-expr.h

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,16 @@ class ResolveExpr : public ResolverBase
109109

110110
void visit (AST::IdentifierExpr &expr) override
111111
{
112-
if (resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node))
112+
if (resolver->get_name_scope ().lookup (CanonicalPath (expr.as_string ()),
113+
&resolved_node))
113114
{
114115
resolver->insert_resolved_name (expr.get_node_id (), resolved_node);
115116
resolver->insert_new_definition (expr.get_node_id (),
116117
Definition{expr.get_node_id (),
117118
parent});
118119
}
119-
else if (resolver->get_type_scope ().lookup (expr.as_string (),
120-
&resolved_node))
120+
else if (resolver->get_type_scope ().lookup (
121+
CanonicalPath (expr.as_string ()), &resolved_node))
121122
{
122123
resolver->insert_resolved_type (expr.get_node_id (), resolved_node);
123124
resolver->insert_new_definition (expr.get_node_id (),
@@ -255,8 +256,9 @@ class ResolveExpr : public ResolverBase
255256
auto label_name = label.get_lifetime ().get_lifetime_name ();
256257
auto label_lifetime_node_id = label.get_lifetime ().get_node_id ();
257258
resolver->get_label_scope ().insert (
258-
label_name, label_lifetime_node_id, label.get_locus (), false,
259-
[&] (std::string, NodeId, Location locus) -> void {
259+
CanonicalPath (label_name), label_lifetime_node_id,
260+
label.get_locus (), false,
261+
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
260262
rust_error_at (label.get_locus (),
261263
"label redefined multiple times");
262264
rust_error_at (locus, "was defined here");
@@ -281,8 +283,8 @@ class ResolveExpr : public ResolverBase
281283
}
282284

283285
NodeId resolved_node = UNKNOWN_NODEID;
284-
if (!resolver->get_label_scope ().lookup (label.get_lifetime_name (),
285-
&resolved_node))
286+
if (!resolver->get_label_scope ().lookup (
287+
CanonicalPath (label.get_lifetime_name ()), &resolved_node))
286288
{
287289
rust_error_at (expr.get_label ().get_locus (),
288290
"failed to resolve label");
@@ -311,8 +313,9 @@ class ResolveExpr : public ResolverBase
311313
auto label_name = label.get_lifetime ().get_lifetime_name ();
312314
auto label_lifetime_node_id = label.get_lifetime ().get_node_id ();
313315
resolver->get_label_scope ().insert (
314-
label_name, label_lifetime_node_id, label.get_locus (), false,
315-
[&] (std::string, NodeId, Location locus) -> void {
316+
CanonicalPath (label_name), label_lifetime_node_id,
317+
label.get_locus (), false,
318+
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
316319
rust_error_at (label.get_locus (),
317320
"label redefined multiple times");
318321
rust_error_at (locus, "was defined here");
@@ -338,8 +341,8 @@ class ResolveExpr : public ResolverBase
338341
}
339342

340343
NodeId resolved_node = UNKNOWN_NODEID;
341-
if (!resolver->get_label_scope ().lookup (label.get_lifetime_name (),
342-
&resolved_node))
344+
if (!resolver->get_label_scope ().lookup (
345+
CanonicalPath (label.get_lifetime_name ()), &resolved_node))
343346
{
344347
rust_error_at (expr.get_label ().get_locus (),
345348
"failed to resolve label");

gcc/rust/resolve/rust-ast-resolve-implitem.h

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -31,25 +31,19 @@ class ResolveToplevelImplItem : public ResolverBase
3131
using Rust::Resolver::ResolverBase::visit;
3232

3333
public:
34-
static void go (AST::InherentImplItem *item, AST::Type *base)
34+
static void go (AST::InherentImplItem *item, const CanonicalPath &prefix)
3535
{
36-
ResolveToplevelImplItem resolver (base);
37-
if (resolver.base_path.is_empty ())
38-
{
39-
rust_error_at (base->get_locus_slow (),
40-
"failed to resolve simple path");
41-
return;
42-
}
36+
ResolveToplevelImplItem resolver (prefix);
4337
item->accept_vis (resolver);
4438
}
4539

4640
void visit (AST::ConstantItem &constant) override
4741
{
48-
std::string identifier
49-
= base_path.as_string () + "::" + constant.get_identifier ();
42+
auto path
43+
= prefix.append (ResolveConstantItemToCanonicalPath::resolve (constant));
5044
resolver->get_name_scope ().insert (
51-
identifier, constant.get_node_id (), constant.get_locus (), false,
52-
[&] (std::string, NodeId, Location locus) -> void {
45+
path, constant.get_node_id (), constant.get_locus (), false,
46+
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
5347
rust_error_at (constant.get_locus (), "redefined multiple times");
5448
rust_error_at (locus, "was defined here");
5549
});
@@ -60,11 +54,11 @@ class ResolveToplevelImplItem : public ResolverBase
6054

6155
void visit (AST::Function &function) override
6256
{
63-
std::string identifier
64-
= base_path.as_string () + "::" + function.get_function_name ();
57+
auto path
58+
= prefix.append (ResolveFunctionItemToCanonicalPath::resolve (function));
6559
resolver->get_name_scope ().insert (
66-
identifier, function.get_node_id (), function.get_locus (), false,
67-
[&] (std::string, NodeId, Location locus) -> void {
60+
path, function.get_node_id (), function.get_locus (), false,
61+
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
6862
rust_error_at (function.get_locus (), "redefined multiple times");
6963
rust_error_at (locus, "was defined here");
7064
});
@@ -75,11 +69,11 @@ class ResolveToplevelImplItem : public ResolverBase
7569

7670
void visit (AST::Method &method) override
7771
{
78-
std::string identifier
79-
= base_path.as_string () + "::" + method.get_method_name ();
72+
auto path
73+
= prefix.append (ResolveMethodItemToCanonicalPath::resolve (method));
8074
resolver->get_name_scope ().insert (
81-
identifier, method.get_node_id (), method.get_locus (), false,
82-
[&] (std::string, NodeId, Location locus) -> void {
75+
path, method.get_node_id (), method.get_locus (), false,
76+
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
8377
rust_error_at (method.get_locus (), "redefined multiple times");
8478
rust_error_at (locus, "was defined here");
8579
});
@@ -89,15 +83,13 @@ class ResolveToplevelImplItem : public ResolverBase
8983
}
9084

9185
private:
92-
ResolveToplevelImplItem (AST::Type *base)
93-
: ResolverBase (UNKNOWN_NODEID), base (base),
94-
base_path (AST::SimplePath::create_empty ())
86+
ResolveToplevelImplItem (const CanonicalPath &prefix)
87+
: ResolverBase (UNKNOWN_NODEID), prefix (prefix)
9588
{
96-
ResolveTypeToSimplePath::go (base, base_path, true);
89+
rust_assert (!prefix.is_error ());
9790
}
9891

99-
AST::Type *base;
100-
AST::SimplePath base_path;
92+
const CanonicalPath &prefix;
10193
};
10294

10395
} // namespace Resolver

gcc/rust/resolve/rust-ast-resolve-item.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,18 +179,21 @@ class ResolveItem : public ResolverBase
179179
}
180180
}
181181

182+
bool canonicalize_type_with_generics = false;
182183
NodeId resolved_node = ResolveType::go (impl_block.get_type ().get (),
183-
impl_block.get_node_id ());
184+
impl_block.get_node_id (),
185+
canonicalize_type_with_generics);
184186
if (resolved_node == UNKNOWN_NODEID)
185187
return;
186188

189+
auto Self = CanonicalPath::get_big_self ();
187190
resolver->get_type_scope ().insert (
188-
"Self", resolved_node, impl_block.get_type ()->get_locus_slow ());
191+
Self, resolved_node, impl_block.get_type ()->get_locus_slow ());
189192

190193
for (auto &impl_item : impl_block.get_impl_items ())
191194
impl_item->accept_vis (*this);
192195

193-
resolver->get_type_scope ().peek ()->clear_name ("Self", resolved_node);
196+
resolver->get_type_scope ().peek ()->clear_name (Self, resolved_node);
194197
resolver->get_type_scope ().pop ();
195198
}
196199

gcc/rust/resolve/rust-ast-resolve-pattern.h

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ class ResolvePattern : public ResolverBase
3333
static void go (AST::Pattern *pattern, NodeId parent)
3434
{
3535
ResolvePattern resolver (parent);
36-
3736
pattern->accept_vis (resolver);
3837
if (resolver.resolved_node == UNKNOWN_NODEID)
3938
{
@@ -42,12 +41,10 @@ class ResolvePattern : public ResolverBase
4241
}
4342
};
4443

45-
~ResolvePattern () {}
46-
4744
void visit (AST::IdentifierPattern &pattern) override
4845
{
49-
if (resolver->get_name_scope ().lookup (pattern.get_ident (),
50-
&resolved_node))
46+
if (resolver->get_name_scope ().lookup (
47+
CanonicalPath (pattern.get_ident ()), &resolved_node))
5148
{
5249
resolver->insert_resolved_name (pattern.get_node_id (), resolved_node);
5350
resolver->insert_new_definition (pattern.get_node_id (),
@@ -68,23 +65,14 @@ class PatternDeclaration : public ResolverBase
6865
static void go (AST::Pattern *pattern, NodeId parent)
6966
{
7067
PatternDeclaration resolver (parent);
71-
7268
pattern->accept_vis (resolver);
73-
if (resolver.resolved_node != UNKNOWN_NODEID)
74-
{
75-
// print both locations?!
76-
rust_error_at (resolver.locus, "duplicate pattern %s",
77-
pattern->as_string ().c_str ());
78-
}
7969
};
8070

81-
~PatternDeclaration () {}
82-
8371
void visit (AST::IdentifierPattern &pattern) override
8472
{
8573
// if we have a duplicate id this then allows for shadowing correctly
8674
// as new refs to this decl will match back here so it is ok to overwrite
87-
resolver->get_name_scope ().insert (pattern.get_ident (),
75+
resolver->get_name_scope ().insert (CanonicalPath (pattern.get_ident ()),
8876
pattern.get_node_id (),
8977
pattern.get_locus ());
9078
resolver->insert_new_definition (pattern.get_node_id (),

0 commit comments

Comments
 (0)