diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-bounds.h | 12 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 300 |
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) |