aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-08-20 14:52:37 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-08-22 14:56:26 +0100
commit95ad46b905b6e49c6888f2923347d0b85c466b96 (patch)
treef2313e0f7f5aea2288b09dc1237a27e070e51e7a /gcc
parente9746f445cf57c12f70d0016722835ec504cc655 (diff)
downloadgcc-95ad46b905b6e49c6888f2923347d0b85c466b96.zip
gcc-95ad46b905b6e49c6888f2923347d0b85c466b96.tar.gz
gcc-95ad46b905b6e49c6888f2923347d0b85c466b96.tar.bz2
Extract header Path type-check code into cc file
Part of the ongoing effort to extract code into cc files to help compilation times.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/Make-lang.in1
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h434
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-path.cc461
3 files changed, 467 insertions, 429 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 7ed380e..9c69b44 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -84,6 +84,7 @@ GRS_OBJS = \
rust/rust-hir-trait-resolve.o \
rust/rust-hir-const-fold.o \
rust/rust-lint-marklive.o \
+ rust/rust-hir-type-check-path.o \
$(END)
# removed object files from here
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index e3347ea..a95a4e9 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -925,169 +925,9 @@ public:
infered = resolved->get_field_type ();
}
- void visit (HIR::QualifiedPathInExpression &expr) override
- {
- HIR::QualifiedPathType qual_path_type = expr.get_path_type ();
- TyTy::BaseType *root
- = TypeCheckType::Resolve (qual_path_type.get_type ().get ());
- if (root->get_kind () == TyTy::TypeKind::ERROR)
- return;
-
- if (!qual_path_type.has_as_clause ())
- {
- // then this is just a normal path-in-expression
- NodeId root_resolved_node_id = UNKNOWN_NODEID;
- bool ok = resolver->lookup_resolved_type (
- qual_path_type.get_type ()->get_mappings ().get_nodeid (),
- &root_resolved_node_id);
- rust_assert (ok);
-
- resolve_segments (root_resolved_node_id, expr.get_segments (), 0, root,
- expr.get_mappings (), expr.get_locus ());
- }
-
- // Resolve the trait now
- TraitReference *trait_ref
- = TraitResolver::Resolve (*qual_path_type.get_trait ().get ());
- if (trait_ref->is_error ())
- return;
-
- // does this type actually implement this type-bound?
- if (!TypeBoundsProbe::is_bound_satisfied_for_type (root, trait_ref))
- return;
-
- // then we need to look at the next segment to create perform the correct
- // projection type
- if (expr.get_segments ().empty ())
- return;
-
- // we need resolve to the impl block
- NodeId impl_resolved_id = UNKNOWN_NODEID;
- bool ok = resolver->lookup_resolved_name (
- qual_path_type.get_mappings ().get_nodeid (), &impl_resolved_id);
- rust_assert (ok);
-
- HirId impl_block_id;
- ok = mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (),
- impl_resolved_id, &impl_block_id);
- rust_assert (ok);
-
- AssociatedImplTrait *lookup_associated = nullptr;
- bool found_impl_trait
- = context->lookup_associated_trait_impl (impl_block_id,
- &lookup_associated);
- rust_assert (found_impl_trait);
-
- DefId resolved_item_id = UNKNOWN_DEFID;
- HIR::PathExprSegment &item_seg = expr.get_segments ().at (0);
-
- const TraitItemReference *trait_item_ref = nullptr;
- ok = trait_ref->lookup_trait_item (item_seg.get_segment ().as_string (),
- &trait_item_ref);
- if (!ok)
- {
- rust_error_at (item_seg.get_locus (), "unknown associated item");
- return;
- }
- resolved_item_id = trait_item_ref->get_mappings ().get_defid ();
-
- infered = lookup_associated->get_projected_type (
- trait_item_ref, root, item_seg.get_mappings ().get_hirid (),
- item_seg.get_locus ());
-
- // turbo-fish segment path::<ty>
- if (item_seg.has_generic_args ())
- {
- if (!infered->can_substitute ())
- {
- rust_error_at (item_seg.get_locus (),
- "substitutions not supported for %s",
- infered->as_string ().c_str ());
- infered = new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
- return;
- }
- infered = SubstMapper::Resolve (infered, expr.get_locus (),
- &item_seg.get_generic_args ());
- }
-
- TyTy::ProjectionType *projection
- = new TyTy::ProjectionType (qual_path_type.get_mappings ().get_hirid (),
- TyTy::TyVar (root->get_ref ()), trait_ref,
- resolved_item_id, lookup_associated);
- context->insert_type (qual_path_type.get_mappings (), projection);
-
- // continue on as a path-in-expression
- NodeId root_resolved_node_id
- = trait_item_ref->get_mappings ().get_nodeid ();
- bool fully_resolved = expr.get_segments ().size () <= 1;
-
- if (fully_resolved)
- {
- // lookup if the name resolver was able to canonically resolve this or
- // not
- NodeId path_resolved_id = UNKNOWN_NODEID;
- if (resolver->lookup_resolved_name (expr.get_mappings ().get_nodeid (),
- &path_resolved_id))
- {
- rust_assert (path_resolved_id == root_resolved_node_id);
- }
- // check the type scope
- else if (resolver->lookup_resolved_type (
- expr.get_mappings ().get_nodeid (), &path_resolved_id))
- {
- rust_assert (path_resolved_id == root_resolved_node_id);
- }
- else
- {
- resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
- root_resolved_node_id);
- }
-
- context->insert_receiver (expr.get_mappings ().get_hirid (), root);
- return;
- }
-
- resolve_segments (root_resolved_node_id, expr.get_segments (), 1, infered,
- expr.get_mappings (), expr.get_locus ());
- }
-
- void visit (HIR::PathInExpression &expr) override
- {
- NodeId resolved_node_id = UNKNOWN_NODEID;
-
- size_t offset = -1;
- TyTy::BaseType *tyseg
- = resolve_root_path (expr, &offset, &resolved_node_id);
-
- if (tyseg == nullptr)
- {
- rust_debug_loc (expr.get_locus (), "failed to resolve root_seg");
- }
- rust_assert (tyseg != nullptr);
+ void visit (HIR::QualifiedPathInExpression &expr) override;
- if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
- return;
-
- if (expr.get_num_segments () == 1)
- {
- Location locus = expr.get_segments ().back ().get_locus ();
-
- bool is_big_self
- = expr.get_segments ().front ().get_segment ().as_string ().compare (
- "Self")
- == 0;
- if (!is_big_self && tyseg->needs_generic_substitutions ())
- {
- tyseg = SubstMapper::InferSubst (tyseg, locus);
- }
-
- infered = tyseg;
- return;
- }
-
- resolve_segments (resolved_node_id, expr.get_segments (), offset, tyseg,
- expr.get_mappings (), expr.get_locus ());
- }
+ void visit (HIR::PathInExpression &expr) override;
void visit (HIR::LoopExpr &expr) override
{
@@ -1235,277 +1075,13 @@ private:
// Beware: currently returns Tyty::ErrorType or nullptr in case of error.
TyTy::BaseType *resolve_root_path (HIR::PathInExpression &expr,
size_t *offset,
- NodeId *root_resolved_node_id)
- {
- TyTy::BaseType *root_tyty = nullptr;
- *offset = 0;
- for (size_t i = 0; i < expr.get_num_segments (); i++)
- {
- HIR::PathExprSegment &seg = expr.get_segments ().at (i);
-
- bool have_more_segments = (expr.get_num_segments () - 1 != i);
- 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))
- {
- // 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 is the NodeId that the segments refers to.
- 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))
- {
- if (is_root)
- {
- rust_error_at (seg.get_locus (), "456 reverse lookup failure");
- rust_debug_loc (
- seg.get_locus (),
- "failure with [%s] mappings [%s] ref_node_id [%u]",
- seg.as_string ().c_str (),
- seg.get_mappings ().as_string ().c_str (), ref_node_id);
-
- return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
- }
-
- return root_tyty;
- }
-
- auto seg_is_module
- = (nullptr
- != mappings->lookup_module (expr.get_mappings ().get_crate_num (),
- ref));
-
- if (seg_is_module)
- {
- // A::B::C::this_is_a_module::D::E::F
- // ^^^^^^^^^^^^^^^^
- // Currently handling this.
- if (have_more_segments)
- {
- (*offset)++;
- continue;
- }
-
- // In the case of :
- // A::B::C::this_is_a_module
- // ^^^^^^^^^^^^^^^^
- // This is an error, we are not expecting a module.
- rust_error_at (seg.get_locus (), "expected value");
- 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;
- }
-
- // if we have a previous segment type
- if (root_tyty != nullptr)
- {
- // 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);
- }
- }
- }
-
- // 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 root_tyty;
- }
+ NodeId *root_resolved_node_id);
void resolve_segments (NodeId root_resolved_node_id,
std::vector<HIR::PathExprSegment> &segments,
size_t offset, TyTy::BaseType *tyseg,
const Analysis::NodeMapping &expr_mappings,
- Location expr_locus)
- {
- NodeId resolved_node_id = root_resolved_node_id;
- TyTy::BaseType *prev_segment = tyseg;
- for (size_t i = offset; i < segments.size (); i++)
- {
- HIR::PathExprSegment &seg = segments.at (i);
-
- bool reciever_is_generic
- = prev_segment->get_kind () == TyTy::TypeKind::PARAM;
- bool probe_bounds = true;
- bool probe_impls = !reciever_is_generic;
- bool ignore_mandatory_trait_items = !reciever_is_generic;
-
- // probe the path
- auto candidates
- = PathProbeType::Probe (prev_segment, seg.get_segment (), probe_impls,
- probe_bounds, ignore_mandatory_trait_items);
- if (candidates.size () == 0)
- {
- rust_error_at (
- seg.get_locus (),
- "failed to resolve path segment using an impl Probe");
- return;
- }
- else if (candidates.size () > 1)
- {
- ReportMultipleCandidateError::Report (candidates,
- seg.get_segment (),
- seg.get_locus ());
- return;
- }
-
- auto &candidate = candidates.at (0);
- prev_segment = tyseg;
- tyseg = candidate.ty;
-
- if (candidate.is_impl_candidate ())
- {
- resolved_node_id
- = candidate.item.impl.impl_item->get_impl_mappings ()
- .get_nodeid ();
- }
- else
- {
- resolved_node_id
- = candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
-
- // lookup the associated-impl-trait
- HIR::ImplBlock *impl = candidate.item.trait.impl;
- if (impl != nullptr)
- {
- AssociatedImplTrait *lookup_associated = nullptr;
- bool found_impl_trait = context->lookup_associated_trait_impl (
- impl->get_mappings ().get_hirid (), &lookup_associated);
- rust_assert (found_impl_trait);
-
- lookup_associated->setup_associated_types ();
-
- // we need a new ty_ref_id for this trait item
- tyseg = tyseg->clone ();
- tyseg->set_ty_ref (mappings->get_next_hir_id ());
- }
- }
-
- if (seg.has_generic_args ())
- {
- if (!tyseg->can_substitute ())
- {
- rust_error_at (expr_locus, "substitutions not supported for %s",
- tyseg->as_string ().c_str ());
- return;
- }
-
- tyseg = SubstMapper::Resolve (tyseg, expr_locus,
- &seg.get_generic_args ());
- if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
- return;
- }
- }
-
- context->insert_receiver (expr_mappings.get_hirid (), prev_segment);
- if (tyseg->needs_generic_substitutions ())
- {
- Location locus = segments.back ().get_locus ();
- if (!prev_segment->needs_generic_substitutions ())
- {
- auto used_args_in_prev_segment
- = GetUsedSubstArgs::From (prev_segment);
- if (!used_args_in_prev_segment.is_error ())
- tyseg = SubstMapperInternal::Resolve (tyseg,
- used_args_in_prev_segment);
- }
- else
- {
- tyseg = SubstMapper::InferSubst (tyseg, locus);
- }
-
- if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
- return;
- }
-
- rust_assert (resolved_node_id != UNKNOWN_NODEID);
-
- // lookup if the name resolver was able to canonically resolve this or not
- NodeId path_resolved_id = UNKNOWN_NODEID;
- if (resolver->lookup_resolved_name (expr_mappings.get_nodeid (),
- &path_resolved_id))
- {
- rust_assert (path_resolved_id == resolved_node_id);
- }
- // check the type scope
- else if (resolver->lookup_resolved_type (expr_mappings.get_nodeid (),
- &path_resolved_id))
- {
- rust_assert (path_resolved_id == resolved_node_id);
- }
- else
- {
- resolver->insert_resolved_name (expr_mappings.get_nodeid (),
- resolved_node_id);
- }
-
- infered = tyseg;
- }
+ Location expr_locus);
bool
validate_arithmetic_type (TyTy::BaseType *type,
@@ -1569,7 +1145,7 @@ private:
Location root_array_expr_locus;
bool inside_loop;
-}; // namespace Resolver
+};
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
new file mode 100644
index 0000000..657c45c
--- /dev/null
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -0,0 +1,461 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-type-check-expr.h"
+
+namespace Rust {
+namespace Resolver {
+
+void
+TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
+{
+ HIR::QualifiedPathType qual_path_type = expr.get_path_type ();
+ TyTy::BaseType *root
+ = TypeCheckType::Resolve (qual_path_type.get_type ().get ());
+ if (root->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+
+ if (!qual_path_type.has_as_clause ())
+ {
+ // then this is just a normal path-in-expression
+ NodeId root_resolved_node_id = UNKNOWN_NODEID;
+ bool ok = resolver->lookup_resolved_type (
+ qual_path_type.get_type ()->get_mappings ().get_nodeid (),
+ &root_resolved_node_id);
+ rust_assert (ok);
+
+ resolve_segments (root_resolved_node_id, expr.get_segments (), 0, root,
+ expr.get_mappings (), expr.get_locus ());
+ }
+
+ // Resolve the trait now
+ TraitReference *trait_ref
+ = TraitResolver::Resolve (*qual_path_type.get_trait ().get ());
+ if (trait_ref->is_error ())
+ return;
+
+ // does this type actually implement this type-bound?
+ if (!TypeBoundsProbe::is_bound_satisfied_for_type (root, trait_ref))
+ return;
+
+ // then we need to look at the next segment to create perform the correct
+ // projection type
+ if (expr.get_segments ().empty ())
+ return;
+
+ // we need resolve to the impl block
+ NodeId impl_resolved_id = UNKNOWN_NODEID;
+ bool ok = resolver->lookup_resolved_name (
+ qual_path_type.get_mappings ().get_nodeid (), &impl_resolved_id);
+ rust_assert (ok);
+
+ HirId impl_block_id;
+ ok = mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (),
+ impl_resolved_id, &impl_block_id);
+ rust_assert (ok);
+
+ AssociatedImplTrait *lookup_associated = nullptr;
+ bool found_impl_trait
+ = context->lookup_associated_trait_impl (impl_block_id, &lookup_associated);
+ rust_assert (found_impl_trait);
+
+ DefId resolved_item_id = UNKNOWN_DEFID;
+ HIR::PathExprSegment &item_seg = expr.get_segments ().at (0);
+
+ const TraitItemReference *trait_item_ref = nullptr;
+ ok = trait_ref->lookup_trait_item (item_seg.get_segment ().as_string (),
+ &trait_item_ref);
+ if (!ok)
+ {
+ rust_error_at (item_seg.get_locus (), "unknown associated item");
+ return;
+ }
+ resolved_item_id = trait_item_ref->get_mappings ().get_defid ();
+
+ infered = lookup_associated->get_projected_type (
+ trait_item_ref, root, item_seg.get_mappings ().get_hirid (),
+ item_seg.get_locus ());
+
+ // turbo-fish segment path::<ty>
+ if (item_seg.has_generic_args ())
+ {
+ if (!infered->can_substitute ())
+ {
+ rust_error_at (item_seg.get_locus (),
+ "substitutions not supported for %s",
+ infered->as_string ().c_str ());
+ infered = new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
+ return;
+ }
+ infered = SubstMapper::Resolve (infered, expr.get_locus (),
+ &item_seg.get_generic_args ());
+ }
+
+ TyTy::ProjectionType *projection
+ = new TyTy::ProjectionType (qual_path_type.get_mappings ().get_hirid (),
+ TyTy::TyVar (root->get_ref ()), trait_ref,
+ resolved_item_id, lookup_associated);
+ context->insert_type (qual_path_type.get_mappings (), projection);
+
+ // continue on as a path-in-expression
+ NodeId root_resolved_node_id = trait_item_ref->get_mappings ().get_nodeid ();
+ bool fully_resolved = expr.get_segments ().size () <= 1;
+
+ if (fully_resolved)
+ {
+ // lookup if the name resolver was able to canonically resolve this or
+ // not
+ NodeId path_resolved_id = UNKNOWN_NODEID;
+ if (resolver->lookup_resolved_name (expr.get_mappings ().get_nodeid (),
+ &path_resolved_id))
+ {
+ rust_assert (path_resolved_id == root_resolved_node_id);
+ }
+ // check the type scope
+ else if (resolver->lookup_resolved_type (
+ expr.get_mappings ().get_nodeid (), &path_resolved_id))
+ {
+ rust_assert (path_resolved_id == root_resolved_node_id);
+ }
+ else
+ {
+ resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
+ root_resolved_node_id);
+ }
+
+ context->insert_receiver (expr.get_mappings ().get_hirid (), root);
+ return;
+ }
+
+ resolve_segments (root_resolved_node_id, expr.get_segments (), 1, infered,
+ expr.get_mappings (), expr.get_locus ());
+}
+
+void
+TypeCheckExpr::visit (HIR::PathInExpression &expr)
+{
+ NodeId resolved_node_id = UNKNOWN_NODEID;
+
+ size_t offset = -1;
+ TyTy::BaseType *tyseg = resolve_root_path (expr, &offset, &resolved_node_id);
+
+ if (tyseg == nullptr)
+ {
+ rust_debug_loc (expr.get_locus (), "failed to resolve root_seg");
+ }
+ rust_assert (tyseg != nullptr);
+
+ if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+
+ if (expr.get_num_segments () == 1)
+ {
+ Location locus = expr.get_segments ().back ().get_locus ();
+
+ bool is_big_self
+ = expr.get_segments ().front ().get_segment ().as_string ().compare (
+ "Self")
+ == 0;
+ if (!is_big_self && tyseg->needs_generic_substitutions ())
+ {
+ tyseg = SubstMapper::InferSubst (tyseg, locus);
+ }
+
+ infered = tyseg;
+ return;
+ }
+
+ resolve_segments (resolved_node_id, expr.get_segments (), offset, tyseg,
+ expr.get_mappings (), expr.get_locus ());
+}
+
+TyTy::BaseType *
+TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
+ NodeId *root_resolved_node_id)
+{
+ TyTy::BaseType *root_tyty = nullptr;
+ *offset = 0;
+ for (size_t i = 0; i < expr.get_num_segments (); i++)
+ {
+ HIR::PathExprSegment &seg = expr.get_segments ().at (i);
+
+ bool have_more_segments = (expr.get_num_segments () - 1 != i);
+ 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))
+ {
+ // 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 is the NodeId that the segments refers to.
+ 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))
+ {
+ if (is_root)
+ {
+ rust_error_at (seg.get_locus (), "456 reverse lookup failure");
+ rust_debug_loc (
+ seg.get_locus (),
+ "failure with [%s] mappings [%s] ref_node_id [%u]",
+ seg.as_string ().c_str (),
+ seg.get_mappings ().as_string ().c_str (), ref_node_id);
+
+ return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
+ }
+
+ return root_tyty;
+ }
+
+ auto seg_is_module
+ = (nullptr
+ != mappings->lookup_module (expr.get_mappings ().get_crate_num (),
+ ref));
+
+ if (seg_is_module)
+ {
+ // A::B::C::this_is_a_module::D::E::F
+ // ^^^^^^^^^^^^^^^^
+ // Currently handling this.
+ if (have_more_segments)
+ {
+ (*offset)++;
+ continue;
+ }
+
+ // In the case of :
+ // A::B::C::this_is_a_module
+ // ^^^^^^^^^^^^^^^^
+ // This is an error, we are not expecting a module.
+ rust_error_at (seg.get_locus (), "expected value");
+ 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;
+ }
+
+ // if we have a previous segment type
+ if (root_tyty != nullptr)
+ {
+ // 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);
+ }
+ }
+ }
+
+ // 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 root_tyty;
+}
+
+void
+TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
+ std::vector<HIR::PathExprSegment> &segments,
+ size_t offset, TyTy::BaseType *tyseg,
+ const Analysis::NodeMapping &expr_mappings,
+ Location expr_locus)
+{
+ NodeId resolved_node_id = root_resolved_node_id;
+ TyTy::BaseType *prev_segment = tyseg;
+ for (size_t i = offset; i < segments.size (); i++)
+ {
+ HIR::PathExprSegment &seg = segments.at (i);
+
+ bool reciever_is_generic
+ = prev_segment->get_kind () == TyTy::TypeKind::PARAM;
+ bool probe_bounds = true;
+ bool probe_impls = !reciever_is_generic;
+ bool ignore_mandatory_trait_items = !reciever_is_generic;
+
+ // probe the path
+ auto candidates
+ = PathProbeType::Probe (prev_segment, seg.get_segment (), probe_impls,
+ probe_bounds, ignore_mandatory_trait_items);
+ if (candidates.size () == 0)
+ {
+ rust_error_at (seg.get_locus (),
+ "failed to resolve path segment using an impl Probe");
+ return;
+ }
+ else if (candidates.size () > 1)
+ {
+ ReportMultipleCandidateError::Report (candidates, seg.get_segment (),
+ seg.get_locus ());
+ return;
+ }
+
+ auto &candidate = candidates.at (0);
+ prev_segment = tyseg;
+ tyseg = candidate.ty;
+
+ if (candidate.is_impl_candidate ())
+ {
+ resolved_node_id
+ = candidate.item.impl.impl_item->get_impl_mappings ().get_nodeid ();
+ }
+ else
+ {
+ resolved_node_id
+ = candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
+
+ // lookup the associated-impl-trait
+ HIR::ImplBlock *impl = candidate.item.trait.impl;
+ if (impl != nullptr)
+ {
+ AssociatedImplTrait *lookup_associated = nullptr;
+ bool found_impl_trait = context->lookup_associated_trait_impl (
+ impl->get_mappings ().get_hirid (), &lookup_associated);
+ rust_assert (found_impl_trait);
+
+ lookup_associated->setup_associated_types ();
+
+ // we need a new ty_ref_id for this trait item
+ tyseg = tyseg->clone ();
+ tyseg->set_ty_ref (mappings->get_next_hir_id ());
+ }
+ }
+
+ if (seg.has_generic_args ())
+ {
+ if (!tyseg->can_substitute ())
+ {
+ rust_error_at (expr_locus, "substitutions not supported for %s",
+ tyseg->as_string ().c_str ());
+ return;
+ }
+
+ tyseg = SubstMapper::Resolve (tyseg, expr_locus,
+ &seg.get_generic_args ());
+ if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+ }
+ }
+
+ context->insert_receiver (expr_mappings.get_hirid (), prev_segment);
+ if (tyseg->needs_generic_substitutions ())
+ {
+ Location locus = segments.back ().get_locus ();
+ if (!prev_segment->needs_generic_substitutions ())
+ {
+ auto used_args_in_prev_segment
+ = GetUsedSubstArgs::From (prev_segment);
+ if (!used_args_in_prev_segment.is_error ())
+ tyseg
+ = SubstMapperInternal::Resolve (tyseg, used_args_in_prev_segment);
+ }
+ else
+ {
+ tyseg = SubstMapper::InferSubst (tyseg, locus);
+ }
+
+ if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+ }
+
+ rust_assert (resolved_node_id != UNKNOWN_NODEID);
+
+ // lookup if the name resolver was able to canonically resolve this or not
+ NodeId path_resolved_id = UNKNOWN_NODEID;
+ if (resolver->lookup_resolved_name (expr_mappings.get_nodeid (),
+ &path_resolved_id))
+ {
+ rust_assert (path_resolved_id == resolved_node_id);
+ }
+ // check the type scope
+ else if (resolver->lookup_resolved_type (expr_mappings.get_nodeid (),
+ &path_resolved_id))
+ {
+ rust_assert (path_resolved_id == resolved_node_id);
+ }
+ else
+ {
+ resolver->insert_resolved_name (expr_mappings.get_nodeid (),
+ resolved_node_id);
+ }
+
+ infered = tyseg;
+}
+
+} // namespace Resolver
+} // namespace Rust