aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/typecheck/rust-hir-type-bounds.h12
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h300
2 files changed, 202 insertions, 110 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h b/gcc/rust/typecheck/rust-hir-type-bounds.h
index ce694da..2c06134 100644
--- a/gcc/rust/typecheck/rust-hir-type-bounds.h
+++ b/gcc/rust/typecheck/rust-hir-type-bounds.h
@@ -38,6 +38,18 @@ public:
return probe.trait_references;
}
+ static bool is_bound_satisfied_for_type (TyTy::BaseType *receiver,
+ TraitReference *ref)
+ {
+ std::vector<TraitReference *> bounds = Probe (receiver);
+ for (TraitReference *b : bounds)
+ {
+ if (b == ref)
+ return true;
+ }
+ return false;
+ }
+
private:
void scan ();
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index d39b2ee..d82b5c7 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -28,6 +28,8 @@
#include "rust-hir-path-probe.h"
#include "rust-substitution-mapper.h"
#include "rust-hir-const-fold.h"
+#include "rust-hir-trait-resolve.h"
+#include "rust-hir-type-bounds.h"
namespace Rust {
namespace Resolver {
@@ -923,6 +925,74 @@ 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;
+
+ DefId resolved_item_id = UNKNOWN_DEFID;
+ HIR::PathExprSegment &item_seg = expr.get_segments ().at (0);
+
+ const TraitItemReference *trait_item_ref = nullptr;
+ bool 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;
+ }
+
+ // TODO self and generic arguments
+
+ infered = trait_item_ref->get_tyty ();
+ rust_debug_loc (expr.get_locus (), "resolved to:");
+ infered->debug ();
+
+ TyTy::ProjectionType *projection
+ = new TyTy::ProjectionType (qual_path_type.get_mappings ().get_hirid (),
+ TyTy::TyVar (root->get_ref ()), trait_ref,
+ resolved_item_id);
+ 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 ();
+ 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;
@@ -931,15 +1001,15 @@ public:
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;
- // this is the case where the name resolver has already fully resolved the
- // name, which means all the work is already done.
- bool name_resolved_fully = offset >= expr.get_num_segments ();
-
if (expr.get_num_segments () == 1)
{
Location locus = expr.get_segments ().back ().get_locus ();
@@ -957,112 +1027,8 @@ public:
return;
}
- TyTy::BaseType *prev_segment = tyseg;
- for (size_t i = offset; i < expr.get_num_segments (); i++)
- {
- HIR::PathExprSegment &seg = expr.get_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 (tyseg, 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 ();
- }
-
- if (seg.has_generic_args ())
- {
- if (!tyseg->can_substitute ())
- {
- rust_error_at (expr.get_locus (),
- "substitutions not supported for %s",
- tyseg->as_string ().c_str ());
- return;
- }
-
- tyseg = SubstMapper::Resolve (tyseg, expr.get_locus (),
- &seg.get_generic_args ());
- if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
- return;
- }
- }
-
- context->insert_receiver (expr.get_mappings ().get_hirid (), prev_segment);
- if (tyseg->needs_generic_substitutions ())
- {
- Location locus = expr.get_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.get_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.get_mappings ().get_nodeid (),
- &path_resolved_id))
- {
- rust_assert (path_resolved_id == resolved_node_id);
- }
- else if (!name_resolved_fully)
- {
- resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
- resolved_node_id);
- }
-
- infered = tyseg;
+ resolve_segments (resolved_node_id, expr.get_segments (), offset, tyseg,
+ expr.get_mappings (), expr.get_locus ());
}
void visit (HIR::LoopExpr &expr) override
@@ -1353,6 +1319,120 @@ private:
return root_tyty;
}
+ 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 ();
+ }
+
+ 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;
+ }
+
bool
validate_arithmetic_type (TyTy::BaseType *type,
HIR::ArithmeticOrLogicalExpr::ExprType expr_type)