diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-06-14 16:11:33 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-06-14 16:31:46 +0100 |
commit | de454a17cf5f9cbd7e4af895174c82e4a6890c36 (patch) | |
tree | 2668b0790ca07ad86723b4c08320a16bfcf9bf1a /gcc | |
parent | 75c44883dbe84682beabc92db7c89bc6db491db8 (diff) | |
download | gcc-de454a17cf5f9cbd7e4af895174c82e4a6890c36.zip gcc-de454a17cf5f9cbd7e4af895174c82e4a6890c36.tar.gz gcc-de454a17cf5f9cbd7e4af895174c82e4a6890c36.tar.bz2 |
Fix PathExpression type resolution
There are cases where the name resolver can fully resolve a path such as:
```rust
struct Foo(i32);
impl Foo{
fn new() { ... }
}
fn main() {
let a;
a = Foo::new();
}
```
This case does not require a PathProbe. This enhances the Path resolution
to iterate each segment untill we are unable to resolve the root segment
at that point we can fall back to a PathProbe and lookup any impl item that
might satisfy the path instead.
Addresses #432
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 159 |
1 files changed, 103 insertions, 56 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 3e081ec..1838e35 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -864,11 +864,15 @@ public: void visit (HIR::PathInExpression &expr) override { - // resolve root_segment - TyTy::BaseType *tyseg = resolve_root_path (expr); + NodeId resolved_node_id = UNKNOWN_NODEID; + + size_t offset = -1; + TyTy::BaseType *tyseg + = resolve_root_path (expr, &offset, &resolved_node_id); if (tyseg->get_kind () == TyTy::TypeKind::ERROR) return; - else if (expr.get_num_segments () == 1) + + if (expr.get_num_segments () == 1) { Location locus = expr.get_segments ().back ().get_locus (); @@ -886,8 +890,7 @@ public: } TyTy::BaseType *prev_segment = tyseg; - NodeId resolved_node_id = UNKNOWN_NODEID; - for (size_t i = 1; i < expr.get_num_segments (); i++) + for (size_t i = offset; i < expr.get_num_segments (); i++) { HIR::PathExprSegment &seg = expr.get_segments ().at (i); @@ -1088,69 +1091,113 @@ private: folded_array_capacity (nullptr), inside_loop (inside_loop) {} - TyTy::BaseType *resolve_root_path (HIR::PathInExpression &expr) + TyTy::BaseType *resolve_root_path (HIR::PathInExpression &expr, + size_t *offset, + NodeId *root_resolved_node_id) { - HIR::PathExprSegment &root = expr.get_root_seg (); - NodeId ast_node_id = root.get_mappings ().get_nodeid (); - - // then lookup the reference_node_id - NodeId ref_node_id = UNKNOWN_NODEID; - if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + TyTy::BaseType *root_tyty = nullptr; + *offset = 0; + for (auto &seg : expr.get_segments ()) { - // these ref_node_ids will resolve to a pattern declaration but we are - // interested in the definition that this refers to get the parent id - Definition def; - if (!resolver->lookup_definition (ref_node_id, &def)) + bool is_root = *offset == 0; + NodeId ast_node_id = seg.get_mappings ().get_nodeid (); + + // then lookup the reference_node_id + NodeId ref_node_id = UNKNOWN_NODEID; + if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) { - rust_error_at (expr.get_locus (), - "unknown reference for resolved name"); - return new TyTy::ErrorType (expr.get_mappings ().get_hirid ()); + // these ref_node_ids will resolve to a pattern declaration but we + // are interested in the definition that this refers to get the + // parent id + Definition def; + if (!resolver->lookup_definition (ref_node_id, &def)) + { + rust_error_at (expr.get_locus (), + "unknown reference for resolved name"); + return new TyTy::ErrorType (expr.get_mappings ().get_hirid ()); + } + ref_node_id = def.parent; + } + else + { + resolver->lookup_resolved_type (ast_node_id, &ref_node_id); } - ref_node_id = def.parent; - } - else - { - resolver->lookup_resolved_type (ast_node_id, &ref_node_id); - } - if (ref_node_id == UNKNOWN_NODEID) - { - rust_error_at (root.get_locus (), - "failed to type resolve root segment"); - return new TyTy::ErrorType (expr.get_mappings ().get_hirid ()); - } + if (ref_node_id == UNKNOWN_NODEID) + { + if (is_root) + { + rust_error_at (seg.get_locus (), + "failed to type resolve root segment"); + return new TyTy::ErrorType (expr.get_mappings ().get_hirid ()); + } + return root_tyty; + } - // node back to HIR - HirId ref; - if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (), - ref_node_id, &ref)) - { - rust_error_at (expr.get_locus (), "reverse lookup failure"); - return new TyTy::ErrorType (expr.get_mappings ().get_hirid ()); - } + // node back to HIR + HirId ref; + if (!mappings->lookup_node_to_hir ( + expr.get_mappings ().get_crate_num (), ref_node_id, &ref)) + { + if (is_root) + { + rust_error_at (seg.get_locus (), "reverse lookup failure"); + return new TyTy::ErrorType (expr.get_mappings ().get_hirid ()); + } + return root_tyty; + } - TyTy::BaseType *lookup = nullptr; - if (!context->lookup_type (ref, &lookup)) - { - rust_error_at (expr.get_locus (), "failed to resolve root segment"); - return new TyTy::ErrorType (expr.get_mappings ().get_hirid ()); - } + TyTy::BaseType *lookup = nullptr; + if (!context->lookup_type (ref, &lookup)) + { + if (is_root) + { + rust_error_at (seg.get_locus (), + "failed to resolve root segment"); + return new TyTy::ErrorType (expr.get_mappings ().get_hirid ()); + } + return root_tyty; + } - // turbo-fish segment path::<ty> - if (root.has_generic_args ()) - { - if (!lookup->can_substitute ()) + // if we have a previous segment type + if (root_tyty != nullptr) { - rust_error_at (expr.get_locus (), - "substitutions not supported for %s", - lookup->as_string ().c_str ()); - return new TyTy::ErrorType (lookup->get_ref ()); + // if this next segment needs substitution we must apply the + // previous type arguments + // + // such as: GenericStruct::<_>::new(123, 456) + if (lookup->needs_generic_substitutions ()) + { + if (!root_tyty->needs_generic_substitutions ()) + { + auto used_args_in_prev_segment + = GetUsedSubstArgs::From (root_tyty); + lookup = SubstMapperInternal::Resolve ( + lookup, used_args_in_prev_segment); + } + } } - lookup = SubstMapper::Resolve (lookup, expr.get_locus (), - &root.get_generic_args ()); + + // turbo-fish segment path::<ty> + if (seg.has_generic_args ()) + { + if (!lookup->can_substitute ()) + { + rust_error_at (seg.get_locus (), + "substitutions not supported for %s", + lookup->as_string ().c_str ()); + return new TyTy::ErrorType (lookup->get_ref ()); + } + lookup = SubstMapper::Resolve (lookup, expr.get_locus (), + &seg.get_generic_args ()); + } + + *root_resolved_node_id = ref_node_id; + *offset = *offset + 1; + root_tyty = lookup; } - return lookup; + return root_tyty; } bool |