diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-10-22 11:08:44 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-22 11:08:44 +0000 |
commit | 8e6c5a32b6e2c1ade6f1a835be2c2a26788db544 (patch) | |
tree | ccc8b527c45cfecc42e26a052f5fce21d0117e99 /gcc | |
parent | df61b8f0ee5c419c4d1b1dcdfc06812646d9f2f9 (diff) | |
parent | 92a31969774e1e9b46800c6475d1a58ccc5ca436 (diff) | |
download | gcc-8e6c5a32b6e2c1ade6f1a835be2c2a26788db544.zip gcc-8e6c5a32b6e2c1ade6f1a835be2c2a26788db544.tar.gz gcc-8e6c5a32b6e2c1ade6f1a835be2c2a26788db544.tar.bz2 |
Merge #752
752: Bugfix ICE in trait resolution r=philberty a=philberty
This is a series of patches which need to go in order to fix the linked bugs.
- Fix type resolution of associated types in the generic context
- Ensure autoderef is applied on generic receivers
- Support generic substitutions on type-bounds
Fixes #743 #753 #744 #741
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/typecheck/rust-hir-dot-operator.h | 6 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h | 2 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-path-probe.h | 222 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 2 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-implitem.h | 6 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-path.cc | 7 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-type.cc | 2 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-type.h | 20 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check.h | 2 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty-bounds.cc | 81 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty-cmp.h | 227 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 165 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 131 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/trait6.rs | 41 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/trait7.rs | 41 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/trait8.rs | 41 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/trait9.rs | 38 |
17 files changed, 778 insertions, 256 deletions
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h index 9c0cc43..98ae5ab 100644 --- a/gcc/rust/typecheck/rust-hir-dot-operator.h +++ b/gcc/rust/typecheck/rust-hir-dot-operator.h @@ -115,7 +115,7 @@ private: if (fn->is_method ()) { TyTy::BaseType *fn_self = fn->get_self_type (); - if (receiver->can_eq (fn_self, false)) + if (receiver->can_eq (fn_self, false, true)) { return &c; } @@ -143,7 +143,7 @@ private: if (fn->is_method ()) { TyTy::BaseType *fn_self = fn->get_self_type (); - if (receiver->can_eq (fn_self, false)) + if (receiver->can_eq (fn_self, false, true)) { return &c; } @@ -165,7 +165,7 @@ private: if (fn->is_method ()) { TyTy::BaseType *fn_self = fn->get_self_type (); - if (receiver->can_eq (fn_self, false)) + if (receiver->can_eq (fn_self, false, true)) { return &c; } diff --git a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h index 9a2c7fe..eac86b0 100644 --- a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h +++ b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h @@ -122,7 +122,7 @@ public: if (query == candidate) continue; - if (query->can_eq (candidate, false)) + if (query->can_eq (candidate, false, false)) possible_collision (it->second, iy->second); } } diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h index dd51f83..6e39fa3 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.h +++ b/gcc/rust/typecheck/rust-hir-path-probe.h @@ -130,24 +130,26 @@ public: if (!probe_bounds) return probe.candidates; - std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> probed_bounds - = TypeBoundsProbe::Probe (receiver); + if (!probe.is_reciever_generic ()) + { + std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> probed_bounds + = TypeBoundsProbe::Probe (receiver); + for (auto &candidate : probed_bounds) + { + const TraitReference *trait_ref = candidate.first; + HIR::ImplBlock *impl = candidate.second; + probe.process_associated_trait_for_candidates ( + trait_ref, impl, ignore_mandatory_trait_items); + } + } - std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> - specified_bounds; for (const TyTy::TypeBoundPredicate &predicate : receiver->get_specified_bounds ()) { - const TraitReference *trait_item = predicate.get (); - - // FIXME lookup impl_block for this trait impl for this receiver - specified_bounds.push_back ({trait_item, nullptr}); + probe.process_predicate_for_candidates (predicate, + ignore_mandatory_trait_items); } - std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> - union_type_bounds = probe.union_bounds (probed_bounds, specified_bounds); - probe.process_traits_for_candidates (union_type_bounds, - ignore_mandatory_trait_items); return probe.candidates; } @@ -227,103 +229,137 @@ protected: bool ok = context->lookup_type (impl_ty_id, &impl_block_ty); rust_assert (ok); - if (!receiver->can_eq (impl_block_ty, false)) + if (!receiver->can_eq (impl_block_ty, false, false)) return; // lets visit the impl_item item->accept_vis (*this); } - void process_traits_for_candidates ( - const std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> - traits, - bool ignore_mandatory_trait_items) + void + process_associated_trait_for_candidates (const TraitReference *trait_ref, + HIR::ImplBlock *impl, + bool ignore_mandatory_trait_items) { - for (auto &ref : traits) + const TraitItemReference *trait_item_ref = nullptr; + if (!trait_ref->lookup_trait_item (search.as_string (), &trait_item_ref)) + return; + + bool trait_item_needs_implementation = !trait_item_ref->is_optional (); + if (ignore_mandatory_trait_items && trait_item_needs_implementation) + return; + + PathProbeCandidate::CandidateType candidate_type; + switch (trait_item_ref->get_trait_item_type ()) { - const TraitReference *trait_ref = ref.first; - HIR::ImplBlock *impl = ref.second; + case TraitItemReference::TraitItemType::FN: + candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC; + break; + case TraitItemReference::TraitItemType::CONST: + candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST; + break; + case TraitItemReference::TraitItemType::TYPE: + candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS; + break; + + case TraitItemReference::TraitItemType::ERROR: + default: + gcc_unreachable (); + break; + } - const TraitItemReference *trait_item_ref = nullptr; - if (!trait_ref->lookup_trait_item (search.as_string (), - &trait_item_ref)) - continue; + TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty (); + if (impl != nullptr && !is_reciever_generic ()) - bool trait_item_needs_implementation = !trait_item_ref->is_optional (); - if (ignore_mandatory_trait_items && trait_item_needs_implementation) - continue; + { + HirId impl_block_id = impl->get_mappings ().get_hirid (); + AssociatedImplTrait *lookup_associated = nullptr; + bool found_impl_trait + = context->lookup_associated_trait_impl (impl_block_id, + &lookup_associated); + // see testsuite/rust/compile/torture/traits10.rs this can be false + if (found_impl_trait) + lookup_associated->setup_associated_types (); + } - PathProbeCandidate::CandidateType candidate_type; - switch (trait_item_ref->get_trait_item_type ()) + // we can substitute the Self with the receiver here + if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF) + { + TyTy::FnType *fn = static_cast<TyTy::FnType *> (trait_item_tyty); + TyTy::SubstitutionParamMapping *param = nullptr; + for (auto ¶m_mapping : fn->get_substs ()) { - case TraitItemReference::TraitItemType::FN: - candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC; - break; - case TraitItemReference::TraitItemType::CONST: - candidate_type - = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST; - break; - case TraitItemReference::TraitItemType::TYPE: - candidate_type - = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS; - break; - - case TraitItemReference::TraitItemType::ERROR: - default: - gcc_unreachable (); - break; + const HIR::TypeParam &type_param + = param_mapping.get_generic_param (); + if (type_param.get_type_representation ().compare ("Self") == 0) + { + param = ¶m_mapping; + break; + } } + rust_assert (param != nullptr); - TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty (); + std::vector<TyTy::SubstitutionArg> mappings; + mappings.push_back (TyTy::SubstitutionArg (param, receiver->clone ())); - if (impl != nullptr) - { - HirId impl_block_id = impl->get_mappings ().get_hirid (); - AssociatedImplTrait *lookup_associated = nullptr; - bool found_impl_trait - = context->lookup_associated_trait_impl (impl_block_id, - &lookup_associated); - // see testsuite/rust/compile/torture/traits10.rs this can be false - if (found_impl_trait) - lookup_associated->setup_associated_types (); - } + Location locus; // FIXME + TyTy::SubstitutionArgumentMappings args (std::move (mappings), locus); + trait_item_tyty = SubstMapperInternal::Resolve (trait_item_tyty, args); + } - // we can substitute the Self with the receiver here - if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF) - { - TyTy::FnType *fn = static_cast<TyTy::FnType *> (trait_item_tyty); - TyTy::SubstitutionParamMapping *param = nullptr; - for (auto ¶m_mapping : fn->get_substs ()) - { - const HIR::TypeParam &type_param - = param_mapping.get_generic_param (); - if (type_param.get_type_representation ().compare ("Self") == 0) - { - param = ¶m_mapping; - break; - } - } - rust_assert (param != nullptr); + PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref, + trait_item_ref, + impl}; + PathProbeCandidate candidate{candidate_type, + trait_item_tyty, + trait_ref->get_locus (), + {trait_item_candidate}}; + candidates.push_back (std::move (candidate)); + } - std::vector<TyTy::SubstitutionArg> mappings; - mappings.push_back ( - TyTy::SubstitutionArg (param, receiver->clone ())); + void + process_predicate_for_candidates (const TyTy::TypeBoundPredicate &predicate, + bool ignore_mandatory_trait_items) + { + const TraitReference *trait_ref = predicate.get (); - Location locus; // FIXME - TyTy::SubstitutionArgumentMappings args (std::move (mappings), - locus); - trait_item_tyty - = SubstMapperInternal::Resolve (trait_item_tyty, args); - } + TyTy::TypeBoundPredicateItem item + = predicate.lookup_associated_item (search.as_string ()); + if (item.is_error ()) + return; - PathProbeCandidate::TraitItemCandidate trait_item_candidate{ - trait_ref, trait_item_ref, impl}; - PathProbeCandidate candidate{candidate_type, - trait_item_tyty, - trait_ref->get_locus (), - {trait_item_candidate}}; - candidates.push_back (std::move (candidate)); + if (ignore_mandatory_trait_items && item.needs_implementation ()) + return; + + const TraitItemReference *trait_item_ref = item.get_raw_item (); + PathProbeCandidate::CandidateType candidate_type; + switch (trait_item_ref->get_trait_item_type ()) + { + case TraitItemReference::TraitItemType::FN: + candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC; + break; + case TraitItemReference::TraitItemType::CONST: + candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST; + break; + case TraitItemReference::TraitItemType::TYPE: + candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS; + break; + + case TraitItemReference::TraitItemType::ERROR: + default: + gcc_unreachable (); + break; } + + TyTy::BaseType *trait_item_tyty = item.get_tyty_for_receiver (receiver); + PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref, + trait_item_ref, + nullptr}; + PathProbeCandidate candidate{candidate_type, + trait_item_tyty, + trait_item_ref->get_locus (), + {trait_item_candidate}}; + candidates.push_back (std::move (candidate)); } protected: @@ -358,6 +394,14 @@ protected: return union_set; } + bool is_reciever_generic () const + { + const TyTy::BaseType *root = receiver->get_root (); + bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM; + bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC; + return receiver_is_type_param || receiver_is_dyn; + } + const TyTy::BaseType *receiver; const HIR::PathIdentSegment &search; std::vector<PathProbeCandidate> candidates; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 83fafa6..8c415ebd 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -320,7 +320,7 @@ public: // always be at the end of the list auto s = fn->get_self_type ()->get_root (); - rust_assert (s->can_eq (adt, false)); + rust_assert (s->can_eq (adt, false, false)); rust_assert (s->get_kind () == TyTy::TypeKind::ADT); const TyTy::ADTType *self_adt = static_cast<const TyTy::ADTType *> (s); diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index 1260c2e..f3a0870 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -377,7 +377,7 @@ public: return; // check the types are compatible - if (!resolved_trait_item.get_tyty ()->can_eq (lookup, true)) + if (!resolved_trait_item.get_tyty ()->can_eq (lookup, true, false)) { RichLocation r (constant.get_locus ()); r.add_range (resolved_trait_item.get_locus ()); @@ -413,7 +413,7 @@ public: return; // check the types are compatible - if (!resolved_trait_item.get_tyty ()->can_eq (lookup, true)) + if (!resolved_trait_item.get_tyty ()->can_eq (lookup, true, false)) { RichLocation r (type.get_locus ()); r.add_range (resolved_trait_item.get_locus ()); @@ -487,7 +487,7 @@ public: = trait_item_fntype->handle_substitions (implicit_self_substs); // check the types are compatible - if (!trait_item_fntype->can_eq (fntype, true)) + if (!trait_item_fntype->can_eq (fntype, true, false)) { RichLocation r (function.get_locus ()); r.add_range (resolved_trait_item.get_locus ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index 0aea8ca..c74ac85 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -376,9 +376,12 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id, 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 (); + // setup associated mappings if possible we might be resolving a + // path within a default implementation of a trait function + // see: testsuite/rust/compile/torture/traits16.rs + if (found_impl_trait) + lookup_associated->setup_associated_types (); // we need a new ty_ref_id for this trait item tyseg = tyseg->clone (); diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index a479581..ed21d53 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -445,7 +445,7 @@ TypeCheckType::resolve_segments ( // lookup the associated-impl-trait HIR::ImplBlock *impl = candidate.item.trait.impl; - if (impl != nullptr) + if (impl != nullptr && !reciever_is_generic) { AssociatedImplTrait *lookup_associated = nullptr; bool found_impl_trait = context->lookup_associated_trait_impl ( diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index e0c0e91..91c49e0 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -234,10 +234,28 @@ public: HIR::TraitBound *b = static_cast<HIR::TraitBound *> (bound.get ()); - TraitReference *trait = resolve_trait_path (b->get_path ()); + auto &type_path = b->get_path (); + TraitReference *trait = resolve_trait_path (type_path); TyTy::TypeBoundPredicate predicate ( trait->get_mappings ().get_defid (), b->get_locus ()); + auto &final_seg = type_path.get_final_segment (); + if (final_seg->is_generic_segment ()) + { + auto final_generic_seg + = static_cast<HIR::TypePathSegmentGeneric *> ( + final_seg.get ()); + if (final_generic_seg->has_generic_args ()) + { + HIR::GenericArgs &generic_args + = final_generic_seg->get_generic_args (); + + // this is applying generic arguments to a trait + // reference + predicate.apply_generic_arguments (&generic_args); + } + } + specified_bounds.push_back (std::move (predicate)); } break; diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index d3dc4c9..5760c4e 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -187,7 +187,7 @@ public: for (auto &item : it->second) { - if (item.first->can_eq (self, false)) + if (item.first->can_eq (self, false, false)) { *mapping = item.second; return true; diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index 5f69deb..88c94d2 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -40,7 +40,7 @@ TypeBoundsProbe::scan () if (!ok) return true; - if (!receiver->can_eq (impl_type, false)) + if (!receiver->can_eq (impl_type, false, false)) return true; possible_trait_paths.push_back ({impl->get_trait_ref ().get (), impl}); @@ -108,5 +108,84 @@ TypeBoundPredicate::is_object_safe (bool emit_error, Location locus) const return trait->is_object_safe (emit_error, locus); } +void +TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args) +{ + args = generic_args; + // TODO verify these arguments are valid and not too many were added +} + +bool +TypeBoundPredicate::contains_item (const std::string &search) const +{ + auto trait_ref = get (); + const Resolver::TraitItemReference *trait_item_ref = nullptr; + return trait_ref->lookup_trait_item (search, &trait_item_ref); +} + +TypeBoundPredicateItem +TypeBoundPredicate::lookup_associated_item (const std::string &search) const +{ + auto trait_ref = get (); + const Resolver::TraitItemReference *trait_item_ref = nullptr; + if (!trait_ref->lookup_trait_item (search, &trait_item_ref)) + return TypeBoundPredicateItem::error (); + + return TypeBoundPredicateItem (this, trait_item_ref); +} + +BaseType * +TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver) +{ + TyTy::BaseType *trait_item_tyty = get_raw_item ()->get_tyty (); + if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF) + { + TyTy::FnType *fn = static_cast<TyTy::FnType *> (trait_item_tyty); + TyTy::SubstitutionParamMapping *param = nullptr; + for (auto ¶m_mapping : fn->get_substs ()) + { + const HIR::TypeParam &type_param = param_mapping.get_generic_param (); + if (type_param.get_type_representation ().compare ("Self") == 0) + { + param = ¶m_mapping; + break; + } + } + rust_assert (param != nullptr); + + std::vector<TyTy::SubstitutionArg> mappings; + mappings.push_back (TyTy::SubstitutionArg (param, receiver->clone ())); + + Location locus; // FIXME + TyTy::SubstitutionArgumentMappings args (std::move (mappings), locus); + trait_item_tyty + = Resolver::SubstMapperInternal::Resolve (trait_item_tyty, args); + } + + if (!parent->has_generic_args ()) + return trait_item_tyty; + + // FIXME LEAK this should really be const + const HIR::GenericArgs *args = parent->get_generic_args (); + HIR::GenericArgs *generic_args = new HIR::GenericArgs (*args); + TyTy::BaseType *resolved + = Resolver::SubstMapper::Resolve (trait_item_tyty, parent->get_locus (), + generic_args); + + return resolved; +} + +const Resolver::TraitItemReference * +TypeBoundPredicateItem::get_raw_item () const +{ + return trait_item_ref; +} + +bool +TypeBoundPredicateItem::needs_implementation () const +{ + return !get_raw_item ()->is_optional (); +} + } // namespace TyTy } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h index 519501f..9ebd564 100644 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ b/gcc/rust/typecheck/rust-tyty-cmp.h @@ -371,8 +371,18 @@ public: virtual void visit (const ParamType &type) override { - // it is ok for types to can eq to a ParamType - ok = true; + ok = false; + if (emit_error_flag) + { + Location ref_locus = mappings->lookup_location (type.get_ref ()); + Location base_locus + = mappings->lookup_location (get_base ()->get_ref ()); + RichLocation r (ref_locus); + r.add_range (base_locus); + rust_error_at (r, "expected [%s] got [%s]", + get_base ()->as_string ().c_str (), + type.as_string ().c_str ()); + } } virtual void visit (const DynamicObjectType &type) override @@ -408,10 +418,10 @@ public: } protected: - BaseCmp (const BaseType *base, bool emit_errors) + BaseCmp (const BaseType *base, bool emit_errors, bool autoderef_mode) : mappings (Analysis::Mappings::get ()), context (Resolver::TypeCheckContext::get ()), ok (false), - emit_error_flag (emit_errors) + emit_error_flag (emit_errors), autoderef_mode_flag (autoderef_mode) {} Analysis::Mappings *mappings; @@ -419,6 +429,7 @@ protected: bool ok; bool emit_error_flag; + bool autoderef_mode_flag; private: /* Returns a pointer to the ty that created this rule. */ @@ -430,8 +441,8 @@ class InferCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - InferCmp (const InferType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + InferCmp (const InferType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const BoolType &type) override @@ -641,18 +652,7 @@ public: BaseCmp::visit (type); } - void visit (const ParamType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } + void visit (const ParamType &) override { ok = true; } void visit (const DynamicObjectType &type) override { @@ -690,8 +690,8 @@ class FnCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - FnCmp (const FnType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + FnCmp (const FnType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const InferType &type) override @@ -712,7 +712,7 @@ public: auto a = base->param_at (i).second; auto b = type.param_at (i).second; - if (!a->can_eq (b, emit_error_flag)) + if (!a->can_eq (b, emit_error_flag, autoderef_mode_flag)) { emit_error_flag = false; BaseCmp::visit (type); @@ -721,7 +721,8 @@ public: } if (!base->get_return_type ()->can_eq (type.get_return_type (), - emit_error_flag)) + emit_error_flag, + autoderef_mode_flag)) { emit_error_flag = false; BaseCmp::visit (type); @@ -741,8 +742,8 @@ class FnptrCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - FnptrCmp (const FnPtr *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + FnptrCmp (const FnPtr *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const InferType &type) override @@ -766,7 +767,8 @@ public: auto this_ret_type = base->get_return_type (); auto other_ret_type = type.get_return_type (); - if (!this_ret_type->can_eq (other_ret_type, emit_error_flag)) + if (!this_ret_type->can_eq (other_ret_type, emit_error_flag, + autoderef_mode_flag)) { BaseCmp::visit (type); return; @@ -776,7 +778,8 @@ public: { auto this_param = base->param_at (i); auto other_param = type.param_at (i); - if (!this_param->can_eq (other_param, emit_error_flag)) + if (!this_param->can_eq (other_param, emit_error_flag, + autoderef_mode_flag)) { BaseCmp::visit (type); return; @@ -796,7 +799,8 @@ public: auto this_ret_type = base->get_return_type (); auto other_ret_type = type.get_return_type (); - if (!this_ret_type->can_eq (other_ret_type, emit_error_flag)) + if (!this_ret_type->can_eq (other_ret_type, emit_error_flag, + autoderef_mode_flag)) { BaseCmp::visit (type); return; @@ -806,7 +810,8 @@ public: { auto this_param = base->param_at (i); auto other_param = type.param_at (i).second; - if (!this_param->can_eq (other_param, emit_error_flag)) + if (!this_param->can_eq (other_param, emit_error_flag, + autoderef_mode_flag)) { BaseCmp::visit (type); return; @@ -826,8 +831,8 @@ class ClosureCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - ClosureCmp (const ClosureType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + ClosureCmp (const ClosureType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} private: @@ -840,8 +845,8 @@ class ArrayCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - ArrayCmp (const ArrayType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + ArrayCmp (const ArrayType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const ArrayType &type) override @@ -856,7 +861,8 @@ public: // check base type const BaseType *base_element = base->get_element_type (); const BaseType *other_element = type.get_element_type (); - if (!base_element->can_eq (other_element, emit_error_flag)) + if (!base_element->can_eq (other_element, emit_error_flag, + autoderef_mode_flag)) { BaseCmp::visit (type); return; @@ -865,6 +871,8 @@ public: ok = true; } + void visit (const ParamType &type) override { ok = true; } + private: const BaseType *get_base () const override { return base; } const ArrayType *base; @@ -875,8 +883,8 @@ class BoolCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - BoolCmp (const BoolType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + BoolCmp (const BoolType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const BoolType &type) override { ok = true; } @@ -886,6 +894,8 @@ public: ok = type.get_infer_kind () == InferType::InferTypeKind::GENERAL; } + void visit (const ParamType &type) override { ok = true; } + private: const BaseType *get_base () const override { return base; } const BoolType *base; @@ -896,8 +906,8 @@ class IntCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - IntCmp (const IntType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + IntCmp (const IntType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const InferType &type) override @@ -910,6 +920,8 @@ public: ok = type.get_int_kind () == base->get_int_kind (); } + void visit (const ParamType &type) override { ok = true; } + private: const BaseType *get_base () const override { return base; } const IntType *base; @@ -920,8 +932,8 @@ class UintCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - UintCmp (const UintType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + UintCmp (const UintType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const InferType &type) override @@ -934,6 +946,8 @@ public: ok = type.get_uint_kind () == base->get_uint_kind (); } + void visit (const ParamType &type) override { ok = true; } + private: const BaseType *get_base () const override { return base; } const UintType *base; @@ -944,8 +958,8 @@ class FloatCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - FloatCmp (const FloatType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + FloatCmp (const FloatType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const InferType &type) override @@ -958,6 +972,8 @@ public: ok = type.get_float_kind () == base->get_float_kind (); } + void visit (const ParamType &type) override { ok = true; } + private: const BaseType *get_base () const override { return base; } const FloatType *base; @@ -968,8 +984,8 @@ class ADTCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - ADTCmp (const ADTType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + ADTCmp (const ADTType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const ADTType &type) override @@ -994,7 +1010,8 @@ public: TyTy::BaseType *this_field_ty = base_field->get_field_type (); TyTy::BaseType *other_field_ty = other_field->get_field_type (); - if (!this_field_ty->can_eq (other_field_ty, emit_error_flag)) + if (!this_field_ty->can_eq (other_field_ty, emit_error_flag, + autoderef_mode_flag)) { BaseCmp::visit (type); return; @@ -1004,6 +1021,8 @@ public: ok = true; } + void visit (const ParamType &type) override { ok = true; } + private: const BaseType *get_base () const override { return base; } const ADTType *base; @@ -1014,8 +1033,8 @@ class TupleCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - TupleCmp (const TupleType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + TupleCmp (const TupleType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const TupleType &type) override @@ -1031,7 +1050,7 @@ public: BaseType *bo = base->get_field (i); BaseType *fo = type.get_field (i); - if (!bo->can_eq (fo, emit_error_flag)) + if (!bo->can_eq (fo, emit_error_flag, autoderef_mode_flag)) { BaseCmp::visit (type); return; @@ -1041,6 +1060,8 @@ public: ok = true; } + void visit (const ParamType &type) override { ok = true; } + private: const BaseType *get_base () const override { return base; } const TupleType *base; @@ -1051,8 +1072,8 @@ class USizeCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - USizeCmp (const USizeType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + USizeCmp (const USizeType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const InferType &type) override @@ -1062,6 +1083,8 @@ public: void visit (const USizeType &type) override { ok = true; } + void visit (const ParamType &type) override { ok = true; } + private: const BaseType *get_base () const override { return base; } const USizeType *base; @@ -1072,8 +1095,8 @@ class ISizeCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - ISizeCmp (const ISizeType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + ISizeCmp (const ISizeType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const InferType &type) override @@ -1083,6 +1106,8 @@ public: void visit (const ISizeType &type) override { ok = true; } + void visit (const ParamType &type) override { ok = true; } + private: const BaseType *get_base () const override { return base; } const ISizeType *base; @@ -1093,8 +1118,8 @@ class CharCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - CharCmp (const CharType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + CharCmp (const CharType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const InferType &type) override @@ -1104,6 +1129,8 @@ public: void visit (const CharType &type) override { ok = true; } + void visit (const ParamType &type) override { ok = true; } + private: const BaseType *get_base () const override { return base; } const CharType *base; @@ -1114,8 +1141,9 @@ class ReferenceCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - ReferenceCmp (const ReferenceType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + ReferenceCmp (const ReferenceType *base, bool emit_errors, + bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const ReferenceType &type) override @@ -1123,7 +1151,8 @@ public: auto base_type = base->get_base (); auto other_base_type = type.get_base (); - ok = base_type->can_eq (other_base_type, emit_error_flag) + ok = base_type->can_eq (other_base_type, emit_error_flag, + autoderef_mode_flag) && (base->is_mutable () == type.is_mutable ()); } @@ -1137,8 +1166,8 @@ class PointerCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - PointerCmp (const PointerType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + PointerCmp (const PointerType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const ReferenceType &type) override @@ -1146,7 +1175,8 @@ public: auto base_type = base->get_base (); auto other_base_type = type.get_base (); - ok = base_type->can_eq (other_base_type, emit_error_flag) + ok = base_type->can_eq (other_base_type, emit_error_flag, + autoderef_mode_flag) && (base->is_mutable () == type.is_mutable ()); } @@ -1160,8 +1190,8 @@ class ParamCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - ParamCmp (const ParamType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + ParamCmp (const ParamType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} // param types are a placeholder we shouldn't have cases where we unify @@ -1183,13 +1213,7 @@ public: bool ok = context->lookup_type (base->get_ty_ref (), &lookup); rust_assert (ok); - if (lookup->get_kind () == TypeKind::PARAM) - { - InferType infer (UNKNOWN_HIRID, InferType::InferTypeKind::GENERAL); - return infer.can_eq (other, emit_error_flag); - } - - return lookup->can_eq (other, emit_error_flag); + return lookup->can_eq (other, emit_error_flag, autoderef_mode_flag); } // imagine the case where we have: @@ -1198,7 +1222,46 @@ public: // impl <X>Foo<X> { ... } // both of these types are compatible so we mostly care about the number of // generic arguments - void visit (const ParamType &type) override { ok = true; } + void visit (const ParamType &) override { ok = true; } + + void visit (const TupleType &) override { ok = true; } + + void visit (const ADTType &) override { ok = true; } + + void visit (const InferType &) override { ok = true; } + + void visit (const FnType &) override { ok = true; } + + void visit (const FnPtr &) override { ok = true; } + + void visit (const ArrayType &) override { ok = true; } + + void visit (const BoolType &) override { ok = true; } + + void visit (const IntType &) override { ok = true; } + + void visit (const UintType &) override { ok = true; } + + void visit (const USizeType &) override { ok = true; } + + void visit (const ISizeType &) override { ok = true; } + + void visit (const FloatType &) override { ok = true; } + + void visit (const CharType &) override { ok = true; } + + void visit (const ReferenceType &) override { ok = !autoderef_mode_flag; } + + void visit (const PointerType &) override { ok = !autoderef_mode_flag; } + + void visit (const StrType &) override { ok = true; } + + void visit (const NeverType &) override { ok = true; } + + void visit (const PlaceholderType &type) override + { + ok = base->get_symbol ().compare (type.get_symbol ()) == 0; + } private: const BaseType *get_base () const override { return base; } @@ -1211,12 +1274,14 @@ class StrCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - StrCmp (const StrType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + StrCmp (const StrType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const StrType &type) override { ok = true; } + void visit (const ParamType &type) override { ok = true; } + private: const BaseType *get_base () const override { return base; } const StrType *base; @@ -1227,12 +1292,14 @@ class NeverCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - NeverCmp (const NeverType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + NeverCmp (const NeverType *base, bool emit_errors, bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const NeverType &type) override { ok = true; } + void visit (const ParamType &type) override { ok = true; } + private: const BaseType *get_base () const override { return base; } const NeverType *base; @@ -1243,8 +1310,9 @@ class PlaceholderCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - PlaceholderCmp (const PlaceholderType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + PlaceholderCmp (const PlaceholderType *base, bool emit_errors, + bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} bool can_eq (const BaseType *other) override @@ -1253,7 +1321,7 @@ public: return BaseCmp::can_eq (other); BaseType *lookup = base->resolve (); - return lookup->can_eq (other, emit_error_flag); + return lookup->can_eq (other, emit_error_flag, autoderef_mode_flag); } void visit (const TupleType &) override { ok = true; } @@ -1308,8 +1376,9 @@ class DynamicCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - DynamicCmp (const DynamicObjectType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) + DynamicCmp (const DynamicObjectType *base, bool emit_errors, + bool autoderef_mode) + : BaseCmp (base, emit_errors, autoderef_mode), base (base) {} void visit (const DynamicObjectType &type) override @@ -1324,6 +1393,8 @@ public: ok = base->bounds_compatible (type, ref_locus, false); } + void visit (const ParamType &type) override { ok = true; } + private: const BaseType *get_base () const override { return base; } diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index f2216f9..37f93b4 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -201,9 +201,10 @@ InferType::unify (BaseType *other) } bool -InferType::can_eq (const BaseType *other, bool emit_errors) const +InferType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - InferCmp r (this, emit_errors); + InferCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -278,7 +279,8 @@ ErrorType::unify (BaseType *other) } bool -ErrorType::can_eq (const BaseType *other, bool emit_errors) const +ErrorType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { return get_kind () == other->get_kind (); } @@ -331,9 +333,11 @@ StructFieldType::clone () const get_field_type ()->clone ()); } -void +bool SubstitutionParamMapping::fill_param_ty (BaseType &type, Location locus) { + auto context = Resolver::TypeCheckContext::get (); + if (type.get_kind () == TyTy::TypeKind::INFER) { type.inherit_bounds (*param); @@ -341,7 +345,7 @@ SubstitutionParamMapping::fill_param_ty (BaseType &type, Location locus) else { if (!param->bounds_compatible (type, locus, true)) - return; + return false; } if (type.get_kind () == TypeKind::PARAM) @@ -351,8 +355,52 @@ SubstitutionParamMapping::fill_param_ty (BaseType &type, Location locus) } else { + // check the substitution is compatible with bounds + if (!param->bounds_compatible (type, locus, true)) + return false; + + // setup any associated type mappings for the specified bonds and this + // type + auto candidates = Resolver::TypeBoundsProbe::Probe (&type); + for (auto &specified_bound : param->get_specified_bounds ()) + { + const Resolver::TraitReference *specified_bound_ref + = specified_bound.get (); + + // since the bounds_compatible check has occurred we should be able to + // assert on finding the trait references + HirId associated_impl_block_id = UNKNOWN_HIRID; + bool found = false; + for (auto &bound : candidates) + { + const Resolver::TraitReference *bound_trait_ref = bound.first; + const HIR::ImplBlock *associated_impl = bound.second; + + found = specified_bound_ref->is_equal (*bound_trait_ref); + if (found) + { + rust_assert (associated_impl != nullptr); + associated_impl_block_id + = associated_impl->get_mappings ().get_hirid (); + break; + } + } + + if (found && associated_impl_block_id != UNKNOWN_HIRID) + { + Resolver::AssociatedImplTrait *lookup_associated = nullptr; + bool found_impl_trait = context->lookup_associated_trait_impl ( + associated_impl_block_id, &lookup_associated); + + if (found_impl_trait) + lookup_associated->setup_associated_types (); + } + } + param->set_ty_ref (type.get_ref ()); } + + return true; } void @@ -595,9 +643,10 @@ ADTType::cast (BaseType *other) } bool -ADTType::can_eq (const BaseType *other, bool emit_errors) const +ADTType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - ADTCmp r (this, emit_errors); + ADTCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -776,9 +825,10 @@ TupleType::cast (BaseType *other) } bool -TupleType::can_eq (const BaseType *other, bool emit_errors) const +TupleType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - TupleCmp r (this, emit_errors); + TupleCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -880,9 +930,10 @@ FnType::cast (BaseType *other) } bool -FnType::can_eq (const BaseType *other, bool emit_errors) const +FnType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - FnCmp r (this, emit_errors); + FnCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -1097,9 +1148,10 @@ FnPtr::cast (BaseType *other) } bool -FnPtr::can_eq (const BaseType *other, bool emit_errors) const +FnPtr::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - FnptrCmp r (this, emit_errors); + FnptrCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -1163,9 +1215,10 @@ ClosureType::unify (BaseType *other) } bool -ClosureType::can_eq (const BaseType *other, bool emit_errors) const +ClosureType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - ClosureCmp r (this, emit_errors); + ClosureCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -1251,9 +1304,10 @@ ArrayType::cast (BaseType *other) } bool -ArrayType::can_eq (const BaseType *other, bool emit_errors) const +ArrayType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - ArrayCmp r (this, emit_errors); + ArrayCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -1326,9 +1380,10 @@ BoolType::cast (BaseType *other) } bool -BoolType::can_eq (const BaseType *other, bool emit_errors) const +BoolType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - BoolCmp r (this, emit_errors); + BoolCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -1392,9 +1447,10 @@ IntType::cast (BaseType *other) } bool -IntType::can_eq (const BaseType *other, bool emit_errors) const +IntType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - IntCmp r (this, emit_errors); + IntCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -1469,9 +1525,10 @@ UintType::cast (BaseType *other) } bool -UintType::can_eq (const BaseType *other, bool emit_errors) const +UintType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - UintCmp r (this, emit_errors); + UintCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -1540,9 +1597,10 @@ FloatType::cast (BaseType *other) } bool -FloatType::can_eq (const BaseType *other, bool emit_errors) const +FloatType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - FloatCmp r (this, emit_errors); + FloatCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -1603,9 +1661,10 @@ USizeType::cast (BaseType *other) } bool -USizeType::can_eq (const BaseType *other, bool emit_errors) const +USizeType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - USizeCmp r (this, emit_errors); + USizeCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -1655,9 +1714,10 @@ ISizeType::cast (BaseType *other) } bool -ISizeType::can_eq (const BaseType *other, bool emit_errors) const +ISizeType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - ISizeCmp r (this, emit_errors); + ISizeCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -1707,9 +1767,10 @@ CharType::cast (BaseType *other) } bool -CharType::can_eq (const BaseType *other, bool emit_errors) const +CharType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - CharCmp r (this, emit_errors); + CharCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -1760,9 +1821,10 @@ ReferenceType::cast (BaseType *other) } bool -ReferenceType::can_eq (const BaseType *other, bool emit_errors) const +ReferenceType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - ReferenceCmp r (this, emit_errors); + ReferenceCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -1846,9 +1908,10 @@ PointerType::cast (BaseType *other) } bool -PointerType::can_eq (const BaseType *other, bool emit_errors) const +PointerType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - PointerCmp r (this, emit_errors); + PointerCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -1941,9 +2004,10 @@ ParamType::cast (BaseType *other) } bool -ParamType::can_eq (const BaseType *other, bool emit_errors) const +ParamType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - ParamCmp r (this, emit_errors); + ParamCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -1998,7 +2062,7 @@ ParamType::is_equal (const BaseType &other) const return false; if (can_resolve ()) - return resolve ()->can_eq (other2.resolve (), false); + return resolve ()->can_eq (other2.resolve (), false, false); return get_symbol ().compare (other2.get_symbol ()) == 0; } @@ -2062,9 +2126,10 @@ StrType::cast (BaseType *other) } bool -StrType::can_eq (const BaseType *other, bool emit_errors) const +StrType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - StrCmp r (this, emit_errors); + StrCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -2114,9 +2179,10 @@ NeverType::cast (BaseType *other) } bool -NeverType::can_eq (const BaseType *other, bool emit_errors) const +NeverType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - NeverCmp r (this, emit_errors); + NeverCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -2169,9 +2235,10 @@ PlaceholderType::cast (BaseType *other) } bool -PlaceholderType::can_eq (const BaseType *other, bool emit_errors) const +PlaceholderType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - PlaceholderCmp r (this, emit_errors); + PlaceholderCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } @@ -2269,9 +2336,10 @@ ProjectionType::cast (BaseType *other) } bool -ProjectionType::can_eq (const BaseType *other, bool emit_errors) const +ProjectionType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - return base->can_eq (other, emit_errors); + return base->can_eq (other, emit_errors, autoderef_mode); } BaseType * @@ -2375,9 +2443,10 @@ DynamicObjectType::unify (BaseType *other) } bool -DynamicObjectType::can_eq (const BaseType *other, bool emit_errors) const +DynamicObjectType::can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const { - DynamicCmp r (this, emit_errors); + DynamicCmp r (this, emit_errors, autoderef_mode); return r.can_eq (other); } diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 054e327..20bad10 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -146,11 +146,42 @@ public: } }; +class BaseType; +class TypeBoundPredicate; +class TypeBoundPredicateItem +{ +public: + TypeBoundPredicateItem (const TypeBoundPredicate *parent, + const Resolver::TraitItemReference *trait_item_ref) + : parent (parent), trait_item_ref (trait_item_ref) + {} + + static TypeBoundPredicateItem error () + { + return TypeBoundPredicateItem (nullptr, nullptr); + } + + bool is_error () const + { + return parent == nullptr || trait_item_ref == nullptr; + } + + BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver); + + const Resolver::TraitItemReference *get_raw_item () const; + + bool needs_implementation () const; + +private: + const TypeBoundPredicate *parent; + const Resolver::TraitItemReference *trait_item_ref; +}; + class TypeBoundPredicate { public: TypeBoundPredicate (DefId reference, Location locus) - : reference (reference), locus (locus) + : reference (reference), locus (locus), args (nullptr) {} std::string as_string () const; @@ -165,9 +196,29 @@ public: // https://doc.rust-lang.org/reference/items/traits.html#object-safety bool is_object_safe (bool emit_error, Location locus) const; + void apply_generic_arguments (HIR::GenericArgs *generic_args); + + bool contains_item (const std::string &search) const; + + TypeBoundPredicateItem + lookup_associated_item (const std::string &search) const; + + HIR::GenericArgs *get_generic_args () { return args; } + + const HIR::GenericArgs *get_generic_args () const { return args; } + + bool has_generic_args () const + { + if (args == nullptr) + return false; + + return args->has_generic_args (); + } + private: DefId reference; Location locus; + HIR::GenericArgs *args; }; class TypeBoundsMappings @@ -259,7 +310,8 @@ public: // // It can also be used to optional emit errors for trait item compatibility // checks - virtual bool can_eq (const BaseType *other, bool emit_errors) const = 0; + virtual bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const = 0; // this is the base coercion interface for types virtual BaseType *coerce (BaseType *other) = 0; @@ -404,7 +456,8 @@ public: BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -442,7 +495,8 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -476,7 +530,8 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -564,7 +619,8 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -626,7 +682,7 @@ public: std::string as_string () const { return param->as_string (); } - void fill_param_ty (BaseType &type, Location locus); + bool fill_param_ty (BaseType &type, Location locus); SubstitutionParamMapping clone () const { @@ -998,7 +1054,8 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1126,7 +1183,8 @@ public: std::string get_identifier () const { return identifier; } BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1234,7 +1292,8 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1294,7 +1353,8 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1346,7 +1406,8 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1388,7 +1449,8 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1424,7 +1486,8 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1467,7 +1530,8 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1508,7 +1572,8 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1541,7 +1606,8 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1567,7 +1633,8 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1593,7 +1660,8 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1623,7 +1691,8 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1670,7 +1739,8 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1715,7 +1785,8 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1751,7 +1822,8 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1784,7 +1856,8 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1812,7 +1885,9 @@ public: bool contains_type_parameters () const override { - rust_assert (can_resolve ()); + if (!can_resolve ()) + return false; + return resolve ()->contains_type_parameters (); } @@ -1850,7 +1925,8 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; @@ -1910,7 +1986,8 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; + bool can_eq (const BaseType *other, bool emit_errors, + bool autoderef_mode) const override final; BaseType *coerce (BaseType *other) override; BaseType *cast (BaseType *other) override; bool is_equal (const BaseType &other) const override; diff --git a/gcc/testsuite/rust/execute/torture/trait6.rs b/gcc/testsuite/rust/execute/torture/trait6.rs new file mode 100644 index 0000000..54023d2 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/trait6.rs @@ -0,0 +1,41 @@ +/* { dg-output "123\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +pub trait Foo { + type A; + + fn bar(self) -> Self::A; + // { dg-warning "unused name" "" { target *-*-* } .-1 } +} + +struct S(i32); +impl Foo for S { + type A = i32; + + fn bar(self) -> Self::A { + // { dg-warning "unused name" "" { target *-*-* } .-1 } + self.0 + } +} + +fn test_bar<T: Foo>(x: T) -> T::A { + x.bar() +} + +fn main() -> i32 { + let a; + a = S(123); + + let bar: i32 = test_bar::<S>(a); + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, bar); + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/trait7.rs b/gcc/testsuite/rust/execute/torture/trait7.rs new file mode 100644 index 0000000..059ba15 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/trait7.rs @@ -0,0 +1,41 @@ +/* { dg-output "123\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +pub trait Foo { + type A; + + fn bar(self) -> Self::A; + // { dg-warning "unused name" "" { target *-*-* } .-1 } +} + +struct S(i32); +impl Foo for S { + type A = i32; + + fn bar(self) -> Self::A { + // { dg-warning "unused name" "" { target *-*-* } .-1 } + self.0 + } +} + +fn test_bar<T: Foo>(x: T) -> T::A { + x.bar() +} + +fn main() -> i32 { + let a; + a = S(123); + + let bar: i32 = test_bar(a); + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, bar); + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/trait8.rs b/gcc/testsuite/rust/execute/torture/trait8.rs new file mode 100644 index 0000000..da8a560 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/trait8.rs @@ -0,0 +1,41 @@ +/* { dg-output "123\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +pub trait Foo { + type A; + + fn bar(&self) -> Self::A; + // { dg-warning "unused name" "" { target *-*-* } .-1 } +} + +struct S(i32); +impl Foo for S { + type A = i32; + + fn bar(&self) -> Self::A { + // { dg-warning "unused name" "" { target *-*-* } .-1 } + self.0 + } +} + +fn test_bar<T: Foo>(x: T) -> T::A { + x.bar() +} + +fn main() -> i32 { + let a; + a = S(123); + + let bar: i32 = test_bar(a); + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, bar); + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/trait9.rs b/gcc/testsuite/rust/execute/torture/trait9.rs new file mode 100644 index 0000000..1fe77e3 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/trait9.rs @@ -0,0 +1,38 @@ +/* { dg-output "3\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +trait FnLike<A, R> { + fn call(&self, arg: A) -> R; + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .arg." "" { target *-*-* } .-2 } +} + +struct S; +impl<T> FnLike<&T, &T> for S { + fn call(&self, arg: &T) -> &T { + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .<S as FnLike>::call." "" { target *-*-* } .-2 } + arg + } +} + +fn indirect<F: FnLike<&isize, &isize>>(f: F) { + let x = 3; + let y = f.call(&x); + + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, *y); + } +} + +fn main() -> i32 { + indirect(S); + + 0 +} |