diff options
Diffstat (limited to 'gcc')
44 files changed, 744 insertions, 249 deletions
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 95e4738..72f2609 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -822,6 +822,8 @@ public: virtual bool is_marked_for_strip () const = 0; NodeId get_node_id () const { return node_id; } + virtual bool is_item () const = 0; + protected: Stmt () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} @@ -847,6 +849,8 @@ public: add_crate_name (std::vector<std::string> &names ATTRIBUTE_UNUSED) const {} + bool is_item () const override final { return true; } + protected: // Clone function implementation as pure virtual method virtual Item *clone_item_impl () const = 0; diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index b83ca11..a1b4e57 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -46,6 +46,8 @@ public: void mark_for_strip () override { marked_for_strip = true; } bool is_marked_for_strip () const override { return marked_for_strip; } + bool is_item () const override final { return false; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -169,6 +171,8 @@ public: return type; } + bool is_item () const override final { return false; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -186,6 +190,8 @@ class ExprStmt : public Stmt public: Location get_locus () const override final { return locus; } + bool is_item () const override final { return false; } + protected: ExprStmt (Location locus) : locus (locus) {} }; diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index b38837c..2414b60 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -162,10 +162,7 @@ public: class TraitObjectType : public Type { bool has_dyn; - // TypeParamBounds type_param_bounds; - std::vector<std::unique_ptr<TypeParamBound> > - type_param_bounds; // inlined form - + std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds; Location locus; protected: @@ -179,7 +176,7 @@ protected: public: TraitObjectType ( std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds, - Location locus, bool is_dyn_dispatch = false) + Location locus, bool is_dyn_dispatch) : has_dyn (is_dyn_dispatch), type_param_bounds (std::move (type_param_bounds)), locus (locus) {} @@ -215,6 +212,8 @@ public: void accept_vis (ASTVisitor &vis) override; + bool is_dyn () const { return has_dyn; } + // TODO: mutable getter seems kinda dodgy std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () { diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index d741598..3184e27 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -177,7 +177,6 @@ public: virtual void visit (HIR::TraitObjectType &type) {} virtual void visit (HIR::ParenthesisedType &type) {} virtual void visit (HIR::ImplTraitTypeOneBound &type) {} - virtual void visit (HIR::TraitObjectTypeOneBound &type) {} virtual void visit (HIR::TupleType &type) {} virtual void visit (HIR::NeverType &type) {} virtual void visit (HIR::RawPointerType &type) {} @@ -210,9 +209,12 @@ protected: const TyTy::DynamicObjectType *ty, Location locus); - Bexpression * - compute_address_for_trait_item (const Resolver::TraitItemReference *ref, - const TyTy::BaseType *receiver); + Bexpression *compute_address_for_trait_item ( + const Resolver::TraitItemReference *ref, + const TyTy::TypeBoundPredicate *predicate, + std::vector<std::pair<Resolver::TraitReference *, HIR::ImplBlock *>> + &receiver_bounds, + const TyTy::BaseType *receiver, const TyTy::BaseType *root, Location locus); }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 551e041..396cb10 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -367,6 +367,9 @@ public: void visit (const TyTy::ParamType ¶m) override { + recursion_count++; + rust_assert (recursion_count < kDefaultRecusionLimit); + param.resolve ()->accept_vis (*this); } @@ -670,12 +673,16 @@ public: private: TyTyResolveCompile (Context *ctx, bool trait_object_mode) - : ctx (ctx), trait_object_mode (trait_object_mode), translated (nullptr) + : ctx (ctx), trait_object_mode (trait_object_mode), translated (nullptr), + recursion_count (0) {} Context *ctx; bool trait_object_mode; ::Btype *translated; + size_t recursion_count; + + static const size_t kDefaultRecusionLimit = 5; }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h index a78cf19..05c7910 100644 --- a/gcc/rust/backend/rust-compile-implitem.h +++ b/gcc/rust/backend/rust-compile-implitem.h @@ -46,12 +46,9 @@ public: if (is_query_mode && ctx->get_backend ()->is_error_expression (compiler.reference)) - { - rust_error_at (ref_locus, "failed to compile impl item: %s", - item->as_string ().c_str ()); - rust_assert ( - !ctx->get_backend ()->is_error_expression (compiler.reference)); - } + rust_internal_error_at (ref_locus, "failed to compile impl item: %s", + item->as_string ().c_str ()); + return compiler.reference; } @@ -331,7 +328,7 @@ class CompileTraitItem : public HIRCompileBase using Rust::Compile::HIRCompileBase::visit; public: - static Bexpression *Compile (TyTy::BaseType *self, HIR::TraitItem *item, + static Bexpression *Compile (const TyTy::BaseType *self, HIR::TraitItem *item, Context *ctx, TyTy::BaseType *concrete, bool is_query_mode = false, Location ref_locus = Location ()) @@ -341,12 +338,9 @@ public: if (is_query_mode && ctx->get_backend ()->is_error_expression (compiler.reference)) - { - rust_error_at (ref_locus, "failed to compile trait item: %s", - item->as_string ().c_str ()); - rust_assert ( - !ctx->get_backend ()->is_error_expression (compiler.reference)); - } + rust_internal_error_at (ref_locus, "failed to compile trait item: %s", + item->as_string ().c_str ()); + return compiler.reference; } @@ -575,14 +569,14 @@ public: } private: - CompileTraitItem (TyTy::BaseType *self, Context *ctx, + CompileTraitItem (const TyTy::BaseType *self, Context *ctx, TyTy::BaseType *concrete, Location ref_locus) : HIRCompileBase (ctx), self (self), concrete (concrete), reference (ctx->get_backend ()->error_expression ()), ref_locus (ref_locus) {} - TyTy::BaseType *self; + const TyTy::BaseType *self; TyTy::BaseType *concrete; Bexpression *reference; Location ref_locus; diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index b64f6f0..6691c2a 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -48,12 +48,9 @@ public: if (is_query_mode && ctx->get_backend ()->is_error_expression (compiler.reference)) - { - rust_error_at (ref_locus, "failed to compile item: %s", - item->as_string ().c_str ()); - rust_assert ( - !ctx->get_backend ()->is_error_expression (compiler.reference)); - } + rust_internal_error_at (ref_locus, "failed to compile item: %s", + item->as_string ().c_str ()); + return compiler.reference; } diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index a5d32b1..e9aca2c 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -22,6 +22,7 @@ #include "rust-compile-struct-field-expr.h" #include "rust-hir-trait-resolve.h" #include "rust-hir-path-probe.h" +#include "rust-hir-type-bounds.h" #include "rust-hir-dot-operator.h" namespace Rust { @@ -243,8 +244,9 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) size_t offs = 0; const Resolver::TraitItemReference *ref = nullptr; - for (auto &item : dyn->get_object_items ()) + for (auto &bound : dyn->get_object_items ()) { + const Resolver::TraitItemReference *item = bound.first; auto t = item->get_tyty (); rust_assert (t->get_kind () == TyTy::TypeKind::FNDEF); auto ft = static_cast<TyTy::FnType *> (t); @@ -790,18 +792,25 @@ HIRCompileBase::coerce_to_dyn_object (Bexpression *compiled_ref, // __trait_object_ptr // [list of function ptrs] + auto root = actual->get_root (); + std::vector<std::pair<Resolver::TraitReference *, HIR::ImplBlock *>> + probed_bounds_for_receiver = Resolver::TypeBoundsProbe::Probe (root); + std::vector<Bexpression *> vals; vals.push_back (compiled_ref); - for (auto &item : ty->get_object_items ()) + for (auto &bound : ty->get_object_items ()) { - // compute the address of each method item - auto address = compute_address_for_trait_item (item, actual->get_root ()); + const Resolver::TraitItemReference *item = bound.first; + const TyTy::TypeBoundPredicate *predicate = bound.second; + + auto address = compute_address_for_trait_item (item, predicate, + probed_bounds_for_receiver, + actual, root, locus); vals.push_back (address); } Bexpression *constructed_trait_object = ctx->get_backend ()->constructor_expression (dynamic_object, vals, -1, - locus); fncontext fnctx = ctx->peek_fn (); @@ -851,44 +860,148 @@ HIRCompileBase::coerce_to_dyn_object (Bexpression *compiled_ref, Bexpression * HIRCompileBase::compute_address_for_trait_item ( - const Resolver::TraitItemReference *trait_item_ref, - const TyTy::BaseType *receiver) + const Resolver::TraitItemReference *ref, + const TyTy::TypeBoundPredicate *predicate, + std::vector<std::pair<Resolver::TraitReference *, HIR::ImplBlock *>> + &receiver_bounds, + const TyTy::BaseType *receiver, const TyTy::BaseType *root, Location locus) { - TyTy::BaseType *item_type = trait_item_ref->get_tyty (); - rust_assert (item_type->get_kind () == TyTy::TypeKind::FNDEF); - TyTy::FnType *fntype = static_cast<TyTy::FnType *> (item_type); - - auto root = receiver->get_root (); - HIR::PathIdentSegment segment_name (trait_item_ref->get_identifier ()); - std::vector<Resolver::PathProbeCandidate> candidates - = Resolver::PathProbeType::Probe (root, segment_name, true, false, true); - - // FIXME for default trait item resolution + // There are two cases here one where its an item which has an implementation + // within a trait-impl-block. Then there is the case where there is a default + // implementation for this within the trait. // - // if (candidates.size () == 0) - // { - // rust_assert (trait_item_ref->is_optional ()); // has definition + // The awkward part here is that this might be a generic trait and we need to + // figure out the correct monomorphized type for this so we can resolve the + // address of the function , this is stored as part of the + // type-bound-predicate // - // CompileTraitItem::Compile (self_type, - // trait_item_ref->get_hir_trait_item (), ctx, - // fntype); - // if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &fn)) - // { - // return ctx->get_backend ()->error_expression (); - // } - // } - - rust_assert (!candidates.empty ()); - rust_assert (candidates.size () == 1); - - Resolver::PathProbeCandidate *candidate = &candidates.at (0); - rust_assert (candidate->is_impl_candidate ()); - - HIR::ImplItem *impl_item = candidate->item.impl.impl_item; - - return CompileInherentImplItem::Compile (receiver->get_root (), impl_item, - ctx, true, fntype, true, - Location () /* FIXME */); + // Algo: + // check if there is an impl-item for this trait-item-ref first + // else assert that the trait-item-ref has an implementation + + TyTy::TypeBoundPredicateItem predicate_item + = predicate->lookup_associated_item (ref->get_identifier ()); + rust_assert (!predicate_item.is_error ()); + + // this is the expected end type + TyTy::BaseType *trait_item_type = predicate_item.get_tyty_for_receiver (root); + rust_assert (trait_item_type->get_kind () == TyTy::TypeKind::FNDEF); + TyTy::FnType *trait_item_fntype + = static_cast<TyTy::FnType *> (trait_item_type); + + // find impl-block for this trait-item-ref + HIR::ImplBlock *associated_impl_block = nullptr; + const Resolver::TraitReference *predicate_trait_ref = predicate->get (); + for (auto &item : receiver_bounds) + { + Resolver::TraitReference *trait_ref = item.first; + HIR::ImplBlock *impl_block = item.second; + if (predicate_trait_ref->is_equal (*trait_ref)) + { + associated_impl_block = impl_block; + break; + } + } + + // FIXME this probably should just return error_mark_node but this helps + // debug for now since we are wrongly returning early on type-resolution + // failures, until we take advantage of more error types and error_mark_node + rust_assert (associated_impl_block != nullptr); + + // lookup self for the associated impl + std::unique_ptr<HIR::Type> &self_type_path + = associated_impl_block->get_type (); + TyTy::BaseType *self = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type ( + self_type_path->get_mappings ().get_hirid (), &self); + rust_assert (ok); + + // lookup the predicate item from the self + TyTy::TypeBoundPredicate *self_bound = nullptr; + for (auto &bound : self->get_specified_bounds ()) + { + const Resolver::TraitReference *bound_ref = bound.get (); + const Resolver::TraitReference *specified_ref = predicate->get (); + if (bound_ref->is_equal (*specified_ref)) + { + self_bound = &bound; + break; + } + } + rust_assert (self_bound != nullptr); + + // lookup the associated item from the associated impl block + TyTy::TypeBoundPredicateItem associated_self_item + = self_bound->lookup_associated_item (ref->get_identifier ()); + rust_assert (!associated_self_item.is_error ()); + + // apply any generic arguments from this predicate + TyTy::BaseType *mono1 = associated_self_item.get_tyty_for_receiver (self); + TyTy::BaseType *mono2 = nullptr; + if (predicate->has_generic_args ()) + { + mono2 = associated_self_item.get_tyty_for_receiver ( + self, predicate->get_generic_args ()); + } + else + { + mono2 = associated_self_item.get_tyty_for_receiver (self); + } + rust_assert (mono1 != nullptr); + rust_assert (mono1->get_kind () == TyTy::TypeKind::FNDEF); + TyTy::FnType *assocated_item_ty1 = static_cast<TyTy::FnType *> (mono1); + + rust_assert (mono2 != nullptr); + rust_assert (mono2->get_kind () == TyTy::TypeKind::FNDEF); + TyTy::FnType *assocated_item_ty2 = static_cast<TyTy::FnType *> (mono2); + + // Lookup the impl-block for the associated impl_item if it exists + HIR::Function *associated_function = nullptr; + for (auto &impl_item : associated_impl_block->get_impl_items ()) + { + bool is_function = impl_item->get_impl_item_type () + == HIR::ImplItem::ImplItemType::FUNCTION; + if (!is_function) + continue; + + HIR::Function *fn = static_cast<HIR::Function *> (impl_item.get ()); + bool found_associated_item + = fn->get_function_name ().compare (ref->get_identifier ()) == 0; + if (found_associated_item) + associated_function = fn; + } + + // we found an impl_item for this + if (associated_function != nullptr) + { + // lookup the associated type for this item + TyTy::BaseType *lookup = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type ( + associated_function->get_mappings ().get_hirid (), &lookup); + rust_assert (ok); + rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF); + TyTy::FnType *lookup_fntype = static_cast<TyTy::FnType *> (lookup); + + if (lookup_fntype->needs_substitution ()) + { + TyTy::SubstitutionArgumentMappings mappings + = assocated_item_ty1->solve_missing_mappings_from_this ( + *assocated_item_ty2, *lookup_fntype); + lookup_fntype = lookup_fntype->handle_substitions (mappings); + } + + return CompileInherentImplItem::Compile (root, associated_function, ctx, + true, lookup_fntype, true, + locus); + } + + // we can only compile trait-items with a body + bool trait_item_has_definition = ref->is_optional (); + rust_assert (trait_item_has_definition); + + HIR::TraitItem *trait_item = ref->get_hir_trait_item (); + return CompileTraitItem::Compile (root, trait_item, ctx, trait_item_fntype, + true, locus); } } // namespace Compile diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index c667932..858984c 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -293,6 +293,8 @@ public: void visit (AST::TraitObjectTypeOneBound &type) override; + void visit (AST::TraitObjectType &type) override; + private: ASTLoweringType () : ASTLoweringBase (), translated (nullptr) {} diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index 5f269b1..d8d53eb 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -517,21 +517,43 @@ ASTLowerQualifiedPathInType::visit (AST::QualifiedPathInType &path) void ASTLoweringType::visit (AST::TraitObjectTypeOneBound &type) { - HIR::TypeParamBound *b + std::vector<std::unique_ptr<HIR::TypeParamBound> > bounds; + HIR::TypeParamBound *translated_bound = ASTLoweringTypeBounds::translate (&type.get_trait_bound ()); - rust_assert (b->get_bound_type () == HIR::TypeParamBound::TRAITBOUND); - HIR::TraitBound *bb = static_cast<HIR::TraitBound *> (b); - HIR::TraitBound bound (*bb); - delete bb; + bounds.push_back (std::unique_ptr<HIR::TypeParamBound> (translated_bound)); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), mappings->get_next_hir_id (crate_num), mappings->get_next_localdef_id (crate_num)); - translated - = new HIR::TraitObjectTypeOneBound (mapping, std::move (bound), - type.get_locus (), type.is_dyn ()); + translated = new HIR::TraitObjectType (mapping, std::move (bounds), + type.get_locus (), type.is_dyn ()); + + mappings->insert_hir_type (mapping.get_crate_num (), mapping.get_hirid (), + translated); +} + +void +ASTLoweringType::visit (AST::TraitObjectType &type) +{ + std::vector<std::unique_ptr<HIR::TypeParamBound> > bounds; + + for (auto &bound : type.get_type_param_bounds ()) + { + HIR::TypeParamBound *translated_bound + = ASTLoweringTypeBounds::translate (bound.get ()); + bounds.push_back ( + std::unique_ptr<HIR::TypeParamBound> (translated_bound)); + } + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, type.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + + translated = new HIR::TraitObjectType (mapping, std::move (bounds), + type.get_locus (), type.is_dyn ()); mappings->insert_hir_type (mapping.get_crate_num (), mapping.get_hirid (), translated); diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index c472cab..575d1f6 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -2007,15 +2007,6 @@ public: void accept_vis (HIRVisitor &vis) override; - void iterate_stmts (std::function<bool (Stmt *)> cb) - { - for (auto it = statements.begin (); it != statements.end (); it++) - { - if (!cb (it->get ())) - return; - } - } - bool is_final_stmt (Stmt *stmt) { return statements.back ().get () == stmt; } Location get_closing_locus () diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h b/gcc/rust/hir/tree/rust-hir-full-decls.h index 384ddf5..3e9d8b2 100644 --- a/gcc/rust/hir/tree/rust-hir-full-decls.h +++ b/gcc/rust/hir/tree/rust-hir-full-decls.h @@ -218,7 +218,6 @@ class ImplTraitType; class TraitObjectType; class ParenthesisedType; class ImplTraitTypeOneBound; -class TraitObjectTypeOneBound; class TupleType; class NeverType; class RawPointerType; diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc index a7c2e9f9..bacef82 100644 --- a/gcc/rust/hir/tree/rust-hir-full-test.cc +++ b/gcc/rust/hir/tree/rust-hir-full-test.cc @@ -2893,25 +2893,6 @@ TypePathSegmentGeneric::as_string () const } std::string -TraitObjectTypeOneBound::as_string () const -{ - std::string str ("TraitObjectTypeOneBound: \n Has dyn dispatch: "); - - if (has_dyn) - { - str += "true"; - } - else - { - str += "false"; - } - - str += "\n TraitBound: " + trait_bound.as_string (); - - return str; -} - -std::string TypePathFunction::as_string () const { std::string str ("("); @@ -4462,12 +4443,6 @@ ImplTraitTypeOneBound::accept_vis (HIRVisitor &vis) } void -TraitObjectTypeOneBound::accept_vis (HIRVisitor &vis) -{ - vis.visit (*this); -} - -void TupleType::accept_vis (HIRVisitor &vis) { vis.visit (*this); diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index c5a8d06..0dd7ac8 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -1122,6 +1122,11 @@ public: // Returns whether function has a where clause. bool has_where_clause () const { return !where_clause.is_empty (); } + ImplItemType get_impl_item_type () const override final + { + return ImplItem::ImplItemType::FUNCTION; + } + // Mega-constructor with all possible fields Function (Analysis::NodeMapping mappings, Identifier function_name, FunctionQualifiers qualifiers, @@ -1273,6 +1278,11 @@ public: // Returns whether type alias has a where clause. bool has_where_clause () const { return !where_clause.is_empty (); } + ImplItemType get_impl_item_type () const override final + { + return ImplItem::ImplItemType::TYPE_ALIAS; + } + // Mega-constructor with all possible fields TypeAlias (Analysis::NodeMapping mappings, Identifier new_type_name, std::vector<std::unique_ptr<GenericParam>> generic_params, @@ -2075,6 +2085,11 @@ public: return get_mappings (); }; + ImplItemType get_impl_item_type () const override final + { + return ImplItem::ImplItemType::CONSTANT; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ diff --git a/gcc/rust/hir/tree/rust-hir-stmt.h b/gcc/rust/hir/tree/rust-hir-stmt.h index cc61142..29e98fa 100644 --- a/gcc/rust/hir/tree/rust-hir-stmt.h +++ b/gcc/rust/hir/tree/rust-hir-stmt.h @@ -41,6 +41,8 @@ public: void accept_vis (HIRVisitor &vis) override; + bool is_item () const override final { return false; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -119,6 +121,8 @@ public: HIR::Pattern *get_pattern () { return variables_pattern.get (); } + bool is_item () const override final { return false; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -136,6 +140,8 @@ class ExprStmt : public Stmt public: Location get_locus () const override final { return locus; } + bool is_item () const override final { return false; } + protected: ExprStmt (Analysis::NodeMapping mappings, Location locus) : Stmt (std::move (mappings)), locus (locus) diff --git a/gcc/rust/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h index 1a90b29..070b761 100644 --- a/gcc/rust/hir/tree/rust-hir-type.h +++ b/gcc/rust/hir/tree/rust-hir-type.h @@ -145,10 +145,7 @@ public: class TraitObjectType : public Type { bool has_dyn; - // TypeParamBounds type_param_bounds; - std::vector<std::unique_ptr<TypeParamBound> > - type_param_bounds; // inlined form - + std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds; Location locus; protected: @@ -163,7 +160,7 @@ public: TraitObjectType ( Analysis::NodeMapping mappings, std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds, - Location locus, bool is_dyn_dispatch = false) + Location locus, bool is_dyn_dispatch) : Type (mappings), has_dyn (is_dyn_dispatch), type_param_bounds (std::move (type_param_bounds)), locus (locus) {} @@ -199,6 +196,17 @@ public: Location get_locus () const { return locus; } void accept_vis (HIRVisitor &vis) override; + + std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () + { + return type_param_bounds; + } + + const std::vector<std::unique_ptr<TypeParamBound> > & + get_type_param_bounds () const + { + return type_param_bounds; + } }; // A type with parentheses around it, used to avoid ambiguity. @@ -305,46 +313,6 @@ public: void accept_vis (HIRVisitor &vis) override; }; -/* A trait object with a single trait bound. The "trait bound" is really just - * the trait. Basically like using an interface as a type in an OOP language. */ -class TraitObjectTypeOneBound : public TypeNoBounds -{ - bool has_dyn; - TraitBound trait_bound; - Location locus; - -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - TraitObjectTypeOneBound *clone_type_impl () const override - { - return new TraitObjectTypeOneBound (mappings, trait_bound, locus, has_dyn); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - TraitObjectTypeOneBound *clone_type_no_bounds_impl () const override - { - return new TraitObjectTypeOneBound (mappings, trait_bound, locus, has_dyn); - } - -public: - TraitObjectTypeOneBound (Analysis::NodeMapping mappings, - TraitBound trait_bound, Location locus, - bool is_dyn_dispatch) - : TypeNoBounds (mappings), has_dyn (is_dyn_dispatch), - trait_bound (std::move (trait_bound)), locus (locus) - {} - - std::string as_string () const override; - - Location get_locus () const { return locus; } - - void accept_vis (HIRVisitor &vis) override; - - TraitBound &get_trait_bound () { return trait_bound; } -}; - class TypePath; // definition moved to "rust-path.h" /* A type consisting of the "product" of others (the tuple's elements) in a diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h index 96ea4c3..0487446 100644 --- a/gcc/rust/hir/tree/rust-hir-visitor.h +++ b/gcc/rust/hir/tree/rust-hir-visitor.h @@ -149,7 +149,6 @@ public: virtual void visit (TraitObjectType &type) = 0; virtual void visit (ParenthesisedType &type) = 0; virtual void visit (ImplTraitTypeOneBound &type) = 0; - virtual void visit (TraitObjectTypeOneBound &type) = 0; virtual void visit (TupleType &type) = 0; virtual void visit (NeverType &type) = 0; virtual void visit (RawPointerType &type) = 0; diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h index d7977b4..e834553 100644 --- a/gcc/rust/hir/tree/rust-hir.h +++ b/gcc/rust/hir/tree/rust-hir.h @@ -104,6 +104,8 @@ public: const Analysis::NodeMapping &get_mappings () const { return mappings; } + virtual bool is_item () const = 0; + protected: Stmt (Analysis::NodeMapping mappings) : mappings (std::move (mappings)) {} @@ -140,6 +142,8 @@ public: AST::AttrVec &get_outer_attrs () { return outer_attrs; } const AST::AttrVec &get_outer_attrs () const { return outer_attrs; } + bool is_item () const override final { return true; } + protected: // Constructor Item (Analysis::NodeMapping mappings, @@ -642,11 +646,14 @@ public: class ImplItem { -protected: - // Clone function implementation as pure virtual method - virtual ImplItem *clone_inherent_impl_item_impl () const = 0; - public: + enum ImplItemType + { + FUNCTION, + TYPE_ALIAS, + CONSTANT + }; + virtual ~ImplItem () {} // Unique pointer custom clone function @@ -662,6 +669,12 @@ public: virtual Analysis::NodeMapping get_impl_mappings () const = 0; virtual Location get_locus () const = 0; + + virtual ImplItemType get_impl_item_type () const = 0; + +protected: + // Clone function implementation as pure virtual method + virtual ImplItem *clone_inherent_impl_item_impl () const = 0; }; // A crate HIR object - holds all the data for a single compilation unit diff --git a/gcc/rust/lint/rust-lint-marklive-base.h b/gcc/rust/lint/rust-lint-marklive-base.h index e7b0194..b67705b 100644 --- a/gcc/rust/lint/rust-lint-marklive-base.h +++ b/gcc/rust/lint/rust-lint-marklive-base.h @@ -172,7 +172,6 @@ public: virtual void visit (HIR::TraitObjectType &) override {} virtual void visit (HIR::ParenthesisedType &) override {} virtual void visit (HIR::ImplTraitTypeOneBound &) override {} - virtual void visit (HIR::TraitObjectTypeOneBound &) override {} virtual void visit (HIR::TupleType &) override {} virtual void visit (HIR::NeverType &) override {} virtual void visit (HIR::RawPointerType &) override {} diff --git a/gcc/rust/lint/rust-lint-marklive.h b/gcc/rust/lint/rust-lint-marklive.h index 7b7b68f..ca5d894 100644 --- a/gcc/rust/lint/rust-lint-marklive.h +++ b/gcc/rust/lint/rust-lint-marklive.h @@ -97,10 +97,10 @@ public: void visit (HIR::BlockExpr &expr) override { - expr.iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { - s->accept_vis (*this); - return true; - }); + for (auto &s : expr.get_statements ()) + { + s->accept_vis (*this); + } if (expr.has_expr ()) { expr.get_final_expr ()->accept_vis (*this); diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 7f0db1b..f1d376a 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -9065,7 +9065,8 @@ Parser<ManagedTokenSource>::parse_type () = parse_type_param_bounds (); return std::unique_ptr<AST::TraitObjectType> ( - new AST::TraitObjectType (std::move (bounds), t->get_locus ())); + new AST::TraitObjectType (std::move (bounds), t->get_locus (), + false)); } case IDENTIFIER: case SUPER: @@ -9152,7 +9153,7 @@ Parser<ManagedTokenSource>::parse_type () } return std::unique_ptr<AST::TraitObjectType> ( - new AST::TraitObjectType (std::move (bounds), locus)); + new AST::TraitObjectType (std::move (bounds), locus, false)); } default: // assume that this is a type path and not an error @@ -9422,7 +9423,8 @@ Parser<ManagedTokenSource>::parse_paren_prefixed_type () } return std::unique_ptr<AST::TraitObjectType> ( - new AST::TraitObjectType (std::move (bounds), left_delim_locus)); + new AST::TraitObjectType (std::move (bounds), left_delim_locus, + false)); } else { @@ -9532,7 +9534,7 @@ Parser<ManagedTokenSource>::parse_for_prefixed_type () } return std::unique_ptr<AST::TraitObjectType> ( - new AST::TraitObjectType (std::move (bounds), for_locus)); + new AST::TraitObjectType (std::move (bounds), for_locus, false)); } default: // error diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 4708bff..838d173 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -371,6 +371,8 @@ public: void visit (AST::TraitObjectTypeOneBound &type) override; + void visit (AST::TraitObjectType &type) override; + private: ResolveType (NodeId parent, bool canonicalize_type_with_generics) : ResolverBase (parent), diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 83a15a8..921b77c 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -349,7 +349,16 @@ ResolveExpr::visit (AST::BlockExpr &expr) resolver->push_new_label_rib (resolver->get_type_scope ().peek ()); for (auto &s : expr.get_statements ()) - ResolveStmt::go (s.get (), s->get_node_id ()); + { + if (s->is_item ()) + ResolveStmt::go (s.get (), s->get_node_id ()); + } + + for (auto &s : expr.get_statements ()) + { + if (!s->is_item ()) + ResolveStmt::go (s.get (), s->get_node_id ()); + } if (expr.has_tail_expr ()) ResolveExpr::go (expr.get_tail_expr ().get (), expr.get_node_id ()); @@ -726,6 +735,17 @@ ResolveType::visit (AST::TraitObjectTypeOneBound &type) ok = bound_resolved_id != UNKNOWN_NODEID; } +void +ResolveType::visit (AST::TraitObjectType &type) +{ + ok = true; + for (auto &bound : type.get_type_param_bounds ()) + { + /* NodeId bound_resolved_id = */ + ResolveTypeBound::go (bound.get (), type.get_node_id ()); + } +} + // rust-ast-resolve-item.h void diff --git a/gcc/rust/rust-diagnostics.cc b/gcc/rust/rust-diagnostics.cc index a82cac4..9982fa2 100644 --- a/gcc/rust/rust-diagnostics.cc +++ b/gcc/rust/rust-diagnostics.cc @@ -147,6 +147,16 @@ rust_close_quote () } void +rust_internal_error_at (const Location location, const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + rust_be_internal_error_at (location, expand_message (fmt, ap)); + va_end (ap); +} + +void rust_error_at (const Location location, const char *fmt, ...) { va_list ap; diff --git a/gcc/rust/rust-diagnostics.h b/gcc/rust/rust-diagnostics.h index 93f8738..d9461f1 100644 --- a/gcc/rust/rust-diagnostics.h +++ b/gcc/rust/rust-diagnostics.h @@ -50,6 +50,10 @@ // simple location extern void +rust_internal_error_at (const Location, const char *fmt, ...) + RUST_ATTRIBUTE_GCC_DIAG (2, 3) + RUST_ATTRIBUTE_NORETURN; +extern void rust_error_at (const Location, const char *fmt, ...) RUST_ATTRIBUTE_GCC_DIAG (2, 3); extern void @@ -57,7 +61,8 @@ rust_warning_at (const Location, int opt, const char *fmt, ...) RUST_ATTRIBUTE_GCC_DIAG (3, 4); extern void rust_fatal_error (const Location, const char *fmt, ...) - RUST_ATTRIBUTE_GCC_DIAG (2, 3); + RUST_ATTRIBUTE_GCC_DIAG (2, 3) + RUST_ATTRIBUTE_NORETURN; extern void rust_inform (const Location, const char *fmt, ...) RUST_ATTRIBUTE_GCC_DIAG (2, 3); @@ -82,13 +87,17 @@ rust_close_quote (); // implement these routines. extern void +rust_be_internal_error_at (const Location, const std::string &errmsg) + RUST_ATTRIBUTE_NORETURN; +extern void rust_be_error_at (const Location, const std::string &errmsg); extern void rust_be_error_at (const RichLocation &, const std::string &errmsg); extern void rust_be_warning_at (const Location, int opt, const std::string &warningmsg); extern void -rust_be_fatal_error (const Location, const std::string &errmsg); +rust_be_fatal_error (const Location, const std::string &errmsg) + RUST_ATTRIBUTE_NORETURN; extern void rust_be_inform (const Location, const std::string &infomsg); extern void diff --git a/gcc/rust/rust-gcc-diagnostics.cc b/gcc/rust/rust-gcc-diagnostics.cc index db6372e..7106dd4 100644 --- a/gcc/rust/rust-gcc-diagnostics.cc +++ b/gcc/rust/rust-gcc-diagnostics.cc @@ -24,6 +24,16 @@ #include "options.h" void +rust_be_internal_error_at (const Location location, const std::string &errmsg) +{ + std::string loc_str = Linemap::location_to_string (location); + if (loc_str.empty ()) + internal_error ("%s", errmsg.c_str ()); + else + internal_error ("at %s, %s", loc_str.c_str (), errmsg.c_str ()); +} + +void rust_be_error_at (const Location location, const std::string &errmsg) { location_t gcc_loc = location.gcc_location (); diff --git a/gcc/rust/rust-system.h b/gcc/rust/rust-system.h index e47fbdc..fa690d7 100644 --- a/gcc/rust/rust-system.h +++ b/gcc/rust/rust-system.h @@ -59,6 +59,8 @@ #include "diagnostic-core.h" /* For error_at and friends. */ #include "intl.h" /* For _(). */ +#define RUST_ATTRIBUTE_NORETURN ATTRIBUTE_NORETURN + // File separator to use based on whether or not the OS we're working with is // DOS-based #if defined(HAVE_DOS_BASED_FILE_SYSTEM) diff --git a/gcc/rust/typecheck/rust-hir-const-fold-base.h b/gcc/rust/typecheck/rust-hir-const-fold-base.h index 77c68c8..9cbf1ab 100644 --- a/gcc/rust/typecheck/rust-hir-const-fold-base.h +++ b/gcc/rust/typecheck/rust-hir-const-fold-base.h @@ -175,7 +175,6 @@ public: virtual void visit (HIR::TraitObjectType &) override {} virtual void visit (HIR::ParenthesisedType &) override {} virtual void visit (HIR::ImplTraitTypeOneBound &) override {} - virtual void visit (HIR::TraitObjectTypeOneBound &) override {} virtual void visit (HIR::TupleType &) override {} virtual void visit (HIR::NeverType &) override {} virtual void visit (HIR::RawPointerType &) override {} diff --git a/gcc/rust/typecheck/rust-hir-trait-ref.h b/gcc/rust/typecheck/rust-hir-trait-ref.h index 0b64a36..31ebf8b 100644 --- a/gcc/rust/typecheck/rust-hir-trait-ref.h +++ b/gcc/rust/typecheck/rust-hir-trait-ref.h @@ -91,9 +91,7 @@ public: TraitItemType get_trait_item_type () const { return type; } - const HIR::TraitItem *get_hir_trait_item () const { return hir_trait_item; } - - HIR::TraitItem *get_hir_trait_item () { return hir_trait_item; } + HIR::TraitItem *get_hir_trait_item () const { return hir_trait_item; } Location get_locus () const { return locus; } diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h index b1e1050..eb96fd1 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.h +++ b/gcc/rust/typecheck/rust-hir-type-check-base.h @@ -177,7 +177,6 @@ public: virtual void visit (HIR::TraitObjectType &) override {} virtual void visit (HIR::ParenthesisedType &) override {} virtual void visit (HIR::ImplTraitTypeOneBound &) override {} - virtual void visit (HIR::TraitObjectTypeOneBound &) override {} virtual void visit (HIR::TupleType &) override {} virtual void visit (HIR::NeverType &) override {} virtual void visit (HIR::RawPointerType &) override {} diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index fe70035..706f649 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -70,12 +70,34 @@ public: } } + std::vector<TyTy::TypeBoundPredicate> specified_bounds; TraitReference *trait_reference = &TraitReference::error_node (); if (impl_block.has_trait_ref ()) { std::unique_ptr<HIR::TypePath> &ref = impl_block.get_trait_ref (); trait_reference = TraitResolver::Resolve (*ref.get ()); rust_assert (!trait_reference->is_error ()); + + // setup the bound + TyTy::TypeBoundPredicate predicate ( + trait_reference->get_mappings ().get_defid (), ref->get_locus ()); + auto &final_seg = ref->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)); } TyTy::BaseType *self = nullptr; @@ -86,6 +108,8 @@ public: "failed to resolve Self for ImplBlock"); return; } + // inherit the bounds + self->inherit_bounds (specified_bounds); bool is_trait_impl_block = !trait_reference->is_error (); diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index f2d5fe7..f1dbb6b 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -95,7 +95,7 @@ TypeCheckType::visit (HIR::TypePath &path) "TypePath %s declares generic arguments but " "the type %s does not have any", path.as_string ().c_str (), - translated->as_string ().c_str ()); + path_type->as_string ().c_str ()); } else { @@ -525,22 +525,44 @@ TypeCheckType::resolve_segments ( } void -TypeCheckType::visit (HIR::TraitObjectTypeOneBound &type) +TypeCheckType::visit (HIR::TraitObjectType &type) { std::vector<TyTy::TypeBoundPredicate> specified_bounds; + for (auto &bound : type.get_type_param_bounds ()) + { + if (bound->get_bound_type () + != HIR::TypeParamBound::BoundType::TRAITBOUND) + continue; + + HIR::TypeParamBound &b = *bound.get (); + HIR::TraitBound &trait_bound = static_cast<HIR::TraitBound &> (b); + + auto &type_path = trait_bound.get_path (); + TraitReference *trait = resolve_trait_path (type_path); + TyTy::TypeBoundPredicate predicate (trait->get_mappings ().get_defid (), + trait_bound.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 (); - HIR::TraitBound &trait_bound = type.get_trait_bound (); - TraitReference *trait = resolve_trait_path (trait_bound.get_path ()); - TyTy::TypeBoundPredicate predicate (trait->get_mappings ().get_defid (), - trait_bound.get_locus ()); + // this is applying generic arguments to a trait + // reference + predicate.apply_generic_arguments (&generic_args); + } + } - if (predicate.is_object_safe (true, type.get_locus ())) - { - specified_bounds.push_back (std::move (predicate)); - translated - = new TyTy::DynamicObjectType (type.get_mappings ().get_hirid (), - std::move (specified_bounds)); + if (predicate.is_object_safe (true, type.get_locus ())) + specified_bounds.push_back (std::move (predicate)); } + + translated = new TyTy::DynamicObjectType (type.get_mappings ().get_hirid (), + std::move (specified_bounds)); } } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index c2b6d7c..08734ce 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -62,13 +62,9 @@ public: std::vector<TyTy::SubstitutionParamMapping> *subst_mappings = nullptr) { - TypeCheckType resolver (subst_mappings); + TypeCheckType resolver (type->get_mappings ().get_hirid (), subst_mappings); type->accept_vis (resolver); - - if (resolver.translated == nullptr) - resolver.translated - = new TyTy::ErrorType (type->get_mappings ().get_hirid ()); - + rust_assert (resolver.translated != nullptr); resolver.context->insert_type (type->get_mappings (), resolver.translated); return resolver.translated; } @@ -147,11 +143,13 @@ public: TyTy::InferType::InferTypeKind::GENERAL); } - void visit (HIR::TraitObjectTypeOneBound &type) override; + void visit (HIR::TraitObjectType &type) override; private: - TypeCheckType (std::vector<TyTy::SubstitutionParamMapping> *subst_mappings) - : TypeCheckBase (), subst_mappings (subst_mappings), translated (nullptr) + TypeCheckType (HirId id, + std::vector<TyTy::SubstitutionParamMapping> *subst_mappings) + : TypeCheckBase (), subst_mappings (subst_mappings), + translated (new TyTy::ErrorType (id)) {} void diff --git a/gcc/rust/typecheck/rust-hir-type-check-util.h b/gcc/rust/typecheck/rust-hir-type-check-util.h index 78d35a6..4595ca3 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-util.h +++ b/gcc/rust/typecheck/rust-hir-type-check-util.h @@ -170,7 +170,6 @@ public: virtual void visit (HIR::TraitObjectType &) override {} virtual void visit (HIR::ParenthesisedType &) override {} virtual void visit (HIR::ImplTraitTypeOneBound &) override {} - virtual void visit (HIR::TraitObjectTypeOneBound &) override {} virtual void visit (HIR::TupleType &) override {} virtual void visit (HIR::NeverType &) override {} virtual void visit (HIR::RawPointerType &) override {} diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 5237082..ca4842a 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -93,22 +93,37 @@ TypeResolution::Resolve (HIR::Crate &crate) void TypeCheckExpr::visit (HIR::BlockExpr &expr) { - expr.iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { - auto resolved = TypeCheckStmt::Resolve (s, inside_loop); - if (resolved == nullptr) - { - rust_error_at (s->get_locus (), "failure to resolve type"); - return false; - } + for (auto &s : expr.get_statements ()) + { + if (!s->is_item ()) + continue; - if (s->is_unit_check_needed () && !resolved->is_unit ()) - { - auto unit = new TyTy::TupleType (s->get_mappings ().get_hirid ()); - resolved = unit->unify (resolved); - } + auto resolved = TypeCheckStmt::Resolve (s.get (), inside_loop); + if (resolved == nullptr) + { + rust_error_at (s->get_locus (), "failure to resolve type"); + return; + } + } - return true; - }); + for (auto &s : expr.get_statements ()) + { + if (s->is_item ()) + continue; + + auto resolved = TypeCheckStmt::Resolve (s.get (), inside_loop); + if (resolved == nullptr) + { + rust_error_at (s->get_locus (), "failure to resolve type"); + return; + } + + if (s->is_unit_check_needed () && !resolved->is_unit ()) + { + auto unit = new TyTy::TupleType (s->get_mappings ().get_hirid ()); + resolved = unit->unify (resolved); + } + } if (expr.has_expr ()) infered diff --git a/gcc/rust/typecheck/rust-tycheck-dump.h b/gcc/rust/typecheck/rust-tycheck-dump.h index c0681b8..c305d48 100644 --- a/gcc/rust/typecheck/rust-tycheck-dump.h +++ b/gcc/rust/typecheck/rust-tycheck-dump.h @@ -94,12 +94,12 @@ public: { indentation_level++; - expr.iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { - dump += indent (); - s->accept_vis (*this); - dump += ";\n"; - return true; - }); + for (auto &s : expr.get_statements ()) + { + dump += indent (); + s->accept_vis (*this); + dump += ";\n"; + } if (expr.has_expr ()) { diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index 88c94d2..cfb96bb 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -70,7 +70,10 @@ namespace TyTy { std::string TypeBoundPredicate::as_string () const { - return get ()->as_string (); + return get ()->as_string () + + (has_generic_args () + ? std::string ("<") + args->as_string () + std::string (">") + : ""); } const Resolver::TraitReference * @@ -135,7 +138,8 @@ TypeBoundPredicate::lookup_associated_item (const std::string &search) const } BaseType * -TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver) +TypeBoundPredicateItem::get_tyty_for_receiver ( + const TyTy::BaseType *receiver, const HIR::GenericArgs *bound_args) { TyTy::BaseType *trait_item_tyty = get_raw_item ()->get_tyty (); if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF) @@ -166,7 +170,8 @@ TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver) return trait_item_tyty; // FIXME LEAK this should really be const - const HIR::GenericArgs *args = parent->get_generic_args (); + const HIR::GenericArgs *args + = (bound_args != nullptr) ? bound_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 (), diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index b3ceb06..378416f 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -334,6 +334,16 @@ StructFieldType::clone () const } bool +SubstitutionParamMapping::need_substitution () const +{ + if (!param->can_resolve ()) + return true; + + auto resolved = param->resolve (); + return !resolved->is_concrete (); +} + +bool SubstitutionParamMapping::fill_param_ty (BaseType &type, Location locus) { auto context = Resolver::TypeCheckContext::get (); @@ -575,6 +585,57 @@ SubstitutionRef::solve_mappings_from_receiver_for_self ( mappings.get_locus ()); } +SubstitutionArgumentMappings +SubstitutionRef::solve_missing_mappings_from_this (SubstitutionRef &ref, + SubstitutionRef &to) +{ + rust_assert (!ref.needs_substitution ()); + rust_assert (needs_substitution ()); + rust_assert (get_num_substitutions () == ref.get_num_substitutions ()); + + Location locus = used_arguments.get_locus (); + std::vector<SubstitutionArg> resolved_mappings; + + std::map<HirId, std::pair<ParamType *, BaseType *>> substs; + for (size_t i = 0; i < get_num_substitutions (); i++) + { + SubstitutionParamMapping &a = substitutions.at (i); + SubstitutionParamMapping &b = ref.substitutions.at (i); + + if (a.need_substitution ()) + { + const BaseType *root = a.get_param_ty ()->resolve ()->get_root (); + rust_assert (root->get_kind () == TyTy::TypeKind::PARAM); + const ParamType *p = static_cast<const TyTy::ParamType *> (root); + + substs[p->get_ty_ref ()] = {static_cast<ParamType *> (p->clone ()), + b.get_param_ty ()->resolve ()}; + } + } + + for (auto it = substs.begin (); it != substs.end (); it++) + { + HirId param_id = it->first; + BaseType *arg = it->second.second; + + const SubstitutionParamMapping *associate_param = nullptr; + for (SubstitutionParamMapping &p : to.substitutions) + { + if (p.get_param_ty ()->get_ty_ref () == param_id) + { + associate_param = &p; + break; + } + } + + rust_assert (associate_param != nullptr); + SubstitutionArg argument (associate_param, arg); + resolved_mappings.push_back (std::move (argument)); + } + + return SubstitutionArgumentMappings (resolved_mappings, locus); +} + void ADTType::accept_vis (TyVisitor &vis) { @@ -1978,7 +2039,7 @@ ParamType::as_string () const bool ok = context->lookup_type (get_ty_ref (), &lookup); rust_assert (ok); - return lookup->as_string (); + return get_symbol () + "=" + lookup->as_string (); } std::string @@ -2503,10 +2564,13 @@ DynamicObjectType::is_equal (const BaseType &other) const return bounds_compatible (other, Location (), false); } -const std::vector<const Resolver::TraitItemReference *> +const std::vector< + std::pair<const Resolver::TraitItemReference *, const TypeBoundPredicate *>> DynamicObjectType::get_object_items () const { - std::vector<const Resolver::TraitItemReference *> items; + std::vector< + std::pair<const Resolver::TraitItemReference *, const TypeBoundPredicate *>> + items; for (auto &bound : get_specified_bounds ()) { const Resolver::TraitReference *trait = bound.get (); @@ -2515,7 +2579,7 @@ DynamicObjectType::get_object_items () const if (item.get_trait_item_type () == Resolver::TraitItemReference::TraitItemType::FN && item.is_object_safe ()) - items.push_back (&item); + items.push_back ({&item, &bound}); } for (auto &super_trait : trait->get_super_traits ()) @@ -2525,7 +2589,7 @@ DynamicObjectType::get_object_items () const if (item.get_trait_item_type () == Resolver::TraitItemReference::TraitItemType::FN && item.is_object_safe ()) - items.push_back (&item); + items.push_back ({&item, &bound}); } } } diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index c26e193..ae9ff67 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -166,12 +166,16 @@ public: return parent == nullptr || trait_item_ref == nullptr; } - BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver); + BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver, + const HIR::GenericArgs *bound_args + = nullptr); const Resolver::TraitItemReference *get_raw_item () const; bool needs_implementation () const; + const TypeBoundPredicate *get_parent () const { return parent; } + private: const TypeBoundPredicate *parent; const Resolver::TraitItemReference *trait_item_ref; @@ -340,7 +344,7 @@ public: virtual bool is_unit () const { return false; } - virtual bool is_concrete () const { return true; } + virtual bool is_concrete () const = 0; TypeKind get_kind () const { return kind; } @@ -470,7 +474,7 @@ public: bool default_type (BaseType **type) const; - bool is_concrete () const final override { return false; } + bool is_concrete () const final override { return true; } private: InferTypeKind infer_kind; @@ -503,6 +507,8 @@ public: BaseType *clone () const final override; std::string get_name () const override final { return as_string (); } + + bool is_concrete () const final override { return false; } }; class SubstitutionArgumentMappings; @@ -559,6 +565,11 @@ public: return true; } + bool is_concrete () const override final + { + return !contains_type_parameters (); + } + ParamType *handle_substitions (SubstitutionArgumentMappings mappings); private: @@ -587,6 +598,8 @@ public: StructFieldType *clone () const; + bool is_concrete () const { return ty->is_concrete (); } + void debug () const { rust_debug ("%s", as_string ().c_str ()); } private: @@ -710,6 +723,8 @@ public: return var.get_tyty (); } + bool need_substitution () const; + private: const HIR::TypeParam &generic; ParamType *param; @@ -743,8 +758,13 @@ public: bool is_conrete () const { - return argument != nullptr && argument->get_kind () != TyTy::TypeKind::ERROR - && argument->get_kind () != TyTy::TypeKind::PARAM; + if (argument != nullptr) + return true; + + if (argument->get_kind () == TyTy::TypeKind::PARAM) + return false; + + return argument->is_concrete (); } std::string as_string () const @@ -898,16 +918,12 @@ public: bool needs_substitution () const { - if (!has_substitutions ()) - return false; - - if (used_arguments.is_error ()) - return true; - - if (used_arguments.size () != get_num_substitutions ()) - return true; - - return !used_arguments.is_concrete (); + for (auto &sub : substitutions) + { + if (sub.need_substitution ()) + return true; + } + return false; } bool was_substituted () const { return !needs_substitution (); } @@ -973,6 +989,11 @@ public: SubstitutionArgumentMappings solve_mappings_from_receiver_for_self ( SubstitutionArgumentMappings &mappings) const; + // TODO comment + SubstitutionArgumentMappings + solve_missing_mappings_from_this (SubstitutionRef &ref, SubstitutionRef &to); + + // TODO comment BaseType *infer_substitions (Location locus) { std::vector<SubstitutionArg> args; @@ -1217,6 +1238,19 @@ public: return identifier + subst_as_string (); } + bool is_concrete () const override final + { + for (auto &variant : variants) + { + for (auto &field : variant->get_fields ()) + { + if (!field->is_concrete ()) + return false; + } + } + return true; + } + BaseType *clone () const final override; bool needs_generic_substitutions () const override final @@ -1349,6 +1383,17 @@ public: return param_at (0).second; } + bool is_concrete () const override final + { + for (const auto ¶m : params) + { + const BaseType *p = param.second; + if (!p->is_concrete ()) + return false; + } + return get_return_type ()->is_concrete (); + } + std::vector<std::pair<HIR::Pattern *, BaseType *>> &get_params () { return params; @@ -1446,6 +1491,16 @@ public: } } + bool is_concrete () const override final + { + for (auto &p : params) + { + if (!p.get_tyty ()->is_concrete ()) + return false; + } + return result_type.get_tyty ()->is_concrete (); + } + private: std::vector<TyVar> params; TyVar result_type; @@ -1498,6 +1553,17 @@ public: BaseType *clone () const final override; + bool is_concrete () const override final + { + for (auto ¶m : parameter_types) + { + auto p = param.get_tyty (); + if (!p->is_concrete ()) + return false; + } + return result_type.get_tyty ()->is_concrete (); + } + bool needs_generic_substitutions () const override final { return needs_substitution (); @@ -1591,6 +1657,7 @@ public: BaseType *cast (BaseType *other) override; BaseType *clone () const final override; + bool is_concrete () const override final { return true; } }; class IntType : public BaseType @@ -1632,6 +1699,7 @@ public: BaseType *clone () const final override; bool is_equal (const BaseType &other) const override; + bool is_concrete () const override final { return true; } private: IntKind int_kind; @@ -1676,6 +1744,7 @@ public: BaseType *clone () const final override; bool is_equal (const BaseType &other) const override; + bool is_concrete () const override final { return true; } private: UintKind uint_kind; @@ -1718,6 +1787,7 @@ public: BaseType *clone () const final override; bool is_equal (const BaseType &other) const override; + bool is_concrete () const override final { return true; } private: FloatKind float_kind; @@ -1748,6 +1818,7 @@ public: BaseType *cast (BaseType *other) override; BaseType *clone () const final override; + bool is_concrete () const override final { return true; } }; class ISizeType : public BaseType @@ -1775,6 +1846,7 @@ public: BaseType *cast (BaseType *other) override; BaseType *clone () const final override; + bool is_concrete () const override final { return true; } }; class CharType : public BaseType @@ -1802,6 +1874,7 @@ public: BaseType *cast (BaseType *other) override; BaseType *clone () const final override; + bool is_concrete () const override final { return true; } }; class ReferenceType : public BaseType @@ -1841,6 +1914,11 @@ public: return get_base ()->contains_type_parameters (); } + bool is_concrete () const override final + { + return !contains_type_parameters (); + } + ReferenceType *handle_substitions (SubstitutionArgumentMappings mappings); Mutability mutability () const { return mut; } @@ -1889,6 +1967,11 @@ public: return get_base ()->contains_type_parameters (); } + bool is_concrete () const override final + { + return !contains_type_parameters (); + } + PointerType *handle_substitions (SubstitutionArgumentMappings mappings); Mutability mutability () const { return mut; } @@ -1929,6 +2012,7 @@ public: bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; + bool is_concrete () const override final { return true; } }; // https://doc.rust-lang.org/std/primitive.never.html @@ -1968,6 +2052,7 @@ public: std::string get_name () const override final { return as_string (); } bool is_unit () const override { return true; } + bool is_concrete () const override final { return true; } }; // used at the type in associated types in traits @@ -2027,6 +2112,11 @@ public: return resolve ()->contains_type_parameters (); } + bool is_concrete () const override final + { + return !contains_type_parameters (); + } + private: std::string symbol; }; @@ -2092,6 +2182,11 @@ public: return base->contains_type_parameters (); } + bool is_concrete () const override final + { + return !contains_type_parameters (); + } + ProjectionType * handle_substitions (SubstitutionArgumentMappings mappings) override final; @@ -2132,8 +2227,11 @@ public: std::string get_name () const override final; + bool is_concrete () const override final { return true; } + // this returns a flat list of items including super trait bounds - const std::vector<const Resolver::TraitItemReference *> + const std::vector< + std::pair<const Resolver::TraitItemReference *, const TypeBoundPredicate *>> get_object_items () const; }; diff --git a/gcc/testsuite/rust/compile/torture/forward_decl_5.rs b/gcc/testsuite/rust/compile/torture/forward_decl_5.rs new file mode 100644 index 0000000..73a47fe --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/forward_decl_5.rs @@ -0,0 +1,19 @@ +pub fn main() { + let a; + a = foo { a: 123, b: 456f32 }; + + let mut a = 123; + a = bar(a); + + let mut b = 456f32; + b = bar(b); + + fn bar<T>(x: T) -> T { + x + } + + struct foo { + a: i32, + b: f32, + }; +} diff --git a/gcc/testsuite/rust/compile/traits10.rs b/gcc/testsuite/rust/compile/traits10.rs index a4622b2..f8f551b 100644 --- a/gcc/testsuite/rust/compile/traits10.rs +++ b/gcc/testsuite/rust/compile/traits10.rs @@ -12,5 +12,4 @@ pub fn main() { let b: &dyn Bar = &a; // { dg-error "trait bound is not object safe" "" { target *-*-* } .-1 } - // { dg-error "expected" "" { target *-*-* } .-2 } } diff --git a/gcc/testsuite/rust/compile/traits11.rs b/gcc/testsuite/rust/compile/traits11.rs index bf69ff0..d06e47d 100644 --- a/gcc/testsuite/rust/compile/traits11.rs +++ b/gcc/testsuite/rust/compile/traits11.rs @@ -16,5 +16,4 @@ pub fn main() { let b: &dyn B = &a; // { dg-error "trait bound is not object safe" "" { target *-*-* } .-1 } - // { dg-error "expected" "" { target *-*-* } .-2 } } diff --git a/gcc/testsuite/rust/execute/torture/trait12.rs b/gcc/testsuite/rust/execute/torture/trait12.rs new file mode 100644 index 0000000..f14a966 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/trait12.rs @@ -0,0 +1,41 @@ +/* { 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 } +} + +type FnObject<'b> = dyn for<'a> FnLike<&'a isize, &'a isize> + 'b; + +struct Identity; + +impl<'a, T> FnLike<&'a T, &'a T> for Identity { + fn call(&self, arg: &'a T) -> &'a T { + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name" "" { target *-*-* } .-2 } + arg + } +} + +fn call_repeatedly(f: &FnObject) { + 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 { + call_repeatedly(&Identity); + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/trait13.rs b/gcc/testsuite/rust/execute/torture/trait13.rs new file mode 100644 index 0000000..76fb09c --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/trait13.rs @@ -0,0 +1,50 @@ +/* { dg-output "123\n456\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +struct Foo(i32); +trait Bar { + fn baz(&self); + // { dg-warning "unused name" "" { target *-*-* } .-1 } + + fn qux(&self) { + // { dg-warning "unused name" "" { target *-*-* } .-1 } + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, 456); + } + } +} + +impl Bar for Foo { + fn baz(&self) { + // { dg-warning "unused name" "" { target *-*-* } .-1 } + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, self.0); + } + } +} + +fn dynamic_dispatch(t: &dyn Bar) { + t.baz(); + t.qux(); +} + +fn main() -> i32 { + let a; + a = Foo(123); + + let b: &dyn Bar; + b = &a; + dynamic_dispatch(b); + + 0 +} |