diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 27e62a923a5c..09e71bce745d 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -1299,7 +1299,7 @@ TraitImpl::as_string () const else str += "false"; - str += "\n TypePath (to trait): " + trait_path.as_string (); + str += "\n TypePath (to trait): " + trait_path->as_string (); str += "\n Type (struct to impl on): " + trait_type->as_string (); @@ -1561,7 +1561,7 @@ QualifiedPathType::as_string () const str += type_to_invoke_on->as_string (); if (has_as_clause ()) - str += " as " + trait_path.as_string (); + str += " as " + trait_path->as_string (); return str + ">"; } diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 3969398f27ef..02b305d816ee 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -3172,7 +3172,7 @@ class TraitImpl : public Impl { bool has_unsafe; bool has_exclam; - TypePath trait_path; + std::unique_ptr trait_path; // bool has_impl_items; std::vector> impl_items; @@ -3184,7 +3184,7 @@ class TraitImpl : public Impl bool has_impl_items () const { return !impl_items.empty (); } // Mega-constructor - TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam, + TraitImpl (std::unique_ptr trait_path, bool is_unsafe, bool has_exclam, std::vector> impl_items, std::vector> generic_params, std::unique_ptr trait_type, WhereClause where_clause, @@ -3197,10 +3197,26 @@ class TraitImpl : public Impl trait_path (std::move (trait_path)), impl_items (std::move (impl_items)) {} + // Helper constructor with a typepath + TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam, + std::vector> impl_items, + std::vector> generic_params, + std::unique_ptr trait_type, WhereClause where_clause, + Visibility vis, std::vector inner_attrs, + std::vector outer_attrs, location_t locus) + : Impl (std::move (generic_params), std::move (trait_type), + std::move (where_clause), std::move (vis), std::move (inner_attrs), + std::move (outer_attrs), locus), + has_unsafe (is_unsafe), has_exclam (has_exclam), + trait_path (std::unique_ptr (new TypePath (trait_path))), + impl_items (std::move (impl_items)) + {} + // Copy constructor with vector clone TraitImpl (TraitImpl const &other) : Impl (other), has_unsafe (other.has_unsafe), - has_exclam (other.has_exclam), trait_path (other.trait_path) + has_exclam (other.has_exclam), + trait_path (other.trait_path->clone_path ()) { impl_items.reserve (other.impl_items.size ()); for (const auto &e : other.impl_items) @@ -3211,7 +3227,7 @@ class TraitImpl : public Impl TraitImpl &operator= (TraitImpl const &other) { Impl::operator= (other); - trait_path = other.trait_path; + trait_path = other.trait_path->clone_path (); has_unsafe = other.has_unsafe; has_exclam = other.has_exclam; @@ -3242,10 +3258,17 @@ class TraitImpl : public Impl } // TODO: is this better? Or is a "vis_block" better? - TypePath &get_trait_path () + Path &get_trait_path () { // TODO: assert that trait path is not empty? - return trait_path; + return *trait_path; + } + + Type &get_trait_path_type () + { + rust_assert (trait_path->get_path_kind () == Path::Kind::Type); + + return (AST::Type &) static_cast (*trait_path); } protected: diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc index 58bfbb47f7c9..3a7e6e34d867 100644 --- a/gcc/rust/ast/rust-path.cc +++ b/gcc/rust/ast/rust-path.cc @@ -152,8 +152,7 @@ RegularPath::as_string () const std::string LangItemPath::as_string () const { - // FIXME: Handle #[lang] paths - rust_unreachable (); + return "#[lang = \"" + LangItem::ToString (kind) + "\"]"; } SimplePath diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 2df1506923d7..93171321ea9c 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -589,6 +589,7 @@ class Path : public Pattern { LangItem, Regular, + Type, }; virtual Kind get_path_kind () const = 0; @@ -598,9 +599,6 @@ class Path : public Pattern return Pattern::Kind::Path; } - location_t get_locus () const override final { return locus; } - NodeId get_node_id () const override final { return node_id; } - std::unique_ptr clone_path () { return std::unique_ptr (clone_path_impl ()); @@ -612,22 +610,19 @@ class Path : public Pattern } protected: - location_t locus; - NodeId node_id; - - Path (location_t locus, NodeId node_id) : locus (locus), node_id (node_id) {} - virtual Path *clone_path_impl () const = 0; }; class RegularPath : public Path { std::vector segments; + NodeId node_id; + location_t locus; public: explicit RegularPath (std::vector &&segments, location_t locus, NodeId node_id) - : Path (locus, node_id), segments (std::move (segments)) + : segments (std::move (segments)), node_id (node_id), locus (locus) {} std::string as_string () const override; @@ -656,16 +651,25 @@ class RegularPath : public Path return new RegularPath (std::vector (segments), locus, node_id); } + + NodeId get_node_id () const override { return node_id; } + location_t get_locus () const override { return locus; } }; class LangItemPath : public Path { - NodeId lang_item; - // TODO: Add LangItemKind or w/ever here as well + LangItem::Kind kind; + NodeId node_id; + location_t locus; - // TODO: This constructor is wrong - explicit LangItemPath (NodeId lang_item, location_t locus) - : Path (locus, lang_item), lang_item (lang_item) + LangItemPath (LangItem::Kind kind, NodeId node_id, location_t locus) + : kind (kind), node_id (node_id), locus (locus) + {} + +public: + explicit LangItemPath (LangItem::Kind kind, location_t locus) + : kind (kind), node_id (Analysis::Mappings::get ().get_next_node_id ()), + locus (locus) {} Path::Kind get_path_kind () const override { return Path::Kind::LangItem; } @@ -674,10 +678,15 @@ class LangItemPath : public Path Path *clone_path_impl () const override { - return new LangItemPath (lang_item, locus); + return new LangItemPath (kind, node_id, locus); } std::string as_string () const override; + + LangItem::Kind get_lang_item_kind () { return kind; } + + NodeId get_node_id () const override { return node_id; } + location_t get_locus () const override { return locus; } }; /* AST node representing a path-in-expression pattern (path that allows @@ -735,11 +744,10 @@ class PathInExpression : public Pattern, public ExprWithoutBlock // Returns whether path in expression is in an error state. bool is_error () const { - // FIXME: Cleanup if (path->get_path_kind () == Path::Kind::Regular) return !static_cast (*path).has_segments (); - return false; + rust_unreachable (); } /* Converts PathInExpression to SimplePath if possible (i.e. no generic @@ -818,7 +826,7 @@ class PathInExpression : public Pattern, public ExprWithoutBlock if (path->get_path_kind () == Path::Kind::Regular) return static_cast (*path).get_segments ().size () == 1; - return false; + rust_unreachable (); } Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; } @@ -1197,8 +1205,7 @@ class TypePathSegmentFunction : public TypePathSegment } }; -// Path used inside types -class TypePath : public TypeNoBounds +class TypePath : public TypeNoBounds, public Path { bool has_opening_scope_resolution; std::vector > segments; @@ -1277,6 +1284,10 @@ class TypePath : public TypeNoBounds TraitBound *to_trait_bound (bool in_parens) const override; location_t get_locus () const override final { return locus; } + NodeId get_node_id () const override final { return node_id; } + + void mark_for_strip () override {} + bool is_marked_for_strip () const override { return false; } void accept_vis (ASTVisitor &vis) override; @@ -1291,13 +1302,17 @@ class TypePath : public TypeNoBounds } size_t get_num_segments () const { return segments.size (); } + + Path::Kind get_path_kind () const override { return Path::Kind::Type; } + + Path *clone_path_impl () const override { return new TypePath (*this); } }; struct QualifiedPathType { private: std::unique_ptr type_to_invoke_on; - TypePath trait_path; + std::unique_ptr trait_path; location_t locus; NodeId node_id; @@ -1307,13 +1322,13 @@ struct QualifiedPathType location_t locus = UNDEF_LOCATION, TypePath trait_path = TypePath::create_error ()) : type_to_invoke_on (std::move (invoke_on_type)), - trait_path (std::move (trait_path)), locus (locus), - node_id (Analysis::Mappings::get ().get_next_node_id ()) + trait_path (std::unique_ptr (new TypePath (trait_path))), + locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // Copy constructor uses custom deep copy for Type to preserve polymorphism QualifiedPathType (QualifiedPathType const &other) - : trait_path (other.trait_path), locus (other.locus) + : trait_path (other.trait_path->clone_path ()), locus (other.locus) { node_id = other.node_id; // guard to prevent null dereference @@ -1328,7 +1343,7 @@ struct QualifiedPathType QualifiedPathType &operator= (QualifiedPathType const &other) { node_id = other.node_id; - trait_path = other.trait_path; + trait_path = other.trait_path->clone_path (); locus = other.locus; // guard to prevent null dereference @@ -1345,7 +1360,11 @@ struct QualifiedPathType QualifiedPathType &operator= (QualifiedPathType &&other) = default; // Returns whether the qualified path type has a rebind as clause. - bool has_as_clause () const { return !trait_path.is_error (); } + bool has_as_clause () const + { + rust_assert (trait_path->get_path_kind () == Path::Kind::Type); + return !static_cast (*trait_path).is_error (); + } // Returns whether the qualified path type is in an error state. bool is_error () const { return type_to_invoke_on == nullptr; } @@ -1374,10 +1393,10 @@ struct QualifiedPathType } // TODO: is this better? Or is a "vis_pattern" better? - TypePath &get_as_type_path () + Path &get_as_type_path () { rust_assert (has_as_clause ()); - return trait_path; + return *trait_path; } NodeId get_node_id () const { return node_id; } @@ -1475,7 +1494,7 @@ class QualifiedPathInExpression : public Pattern, public ExprWithoutBlock if (path->get_path_kind () == Path::Kind::Regular) return static_cast (*path).get_segments ().size () == 1; - return false; + rust_unreachable (); } protected: diff --git a/gcc/rust/expand/rust-derive-copy.cc b/gcc/rust/expand/rust-derive-copy.cc index 070a7cd63bc5..b36011dab48a 100644 --- a/gcc/rust/expand/rust-derive-copy.cc +++ b/gcc/rust/expand/rust-derive-copy.cc @@ -18,6 +18,8 @@ #include "rust-derive-copy.h" #include "rust-ast-full.h" +#include "rust-mapping-common.h" +#include "rust-path.h" namespace Rust { namespace AST { @@ -44,7 +46,7 @@ DeriveCopy::copy_impl ( // `$crate::core::marker::Copy` instead auto segments = std::vector> (); segments.emplace_back (builder.type_path_segment ("Copy")); - auto copy = TypePath (std::move (segments), loc); + auto copy = Rust::make_unique (LangItem::Kind::COPY, loc); // we need to build up the generics for this impl block which will be just a // clone of the types specified ones @@ -116,7 +118,7 @@ DeriveCopy::copy_impl ( : builder.single_generic_type_path (name, generic_args_for_self); return std::unique_ptr ( - new TraitImpl (copy, /* unsafe */ false, + new TraitImpl (std::move (copy), /* unsafe */ false, /* exclam */ false, /* trait items */ {}, std::move (impl_generics), std::move (self_type_path), WhereClause::create_empty (), Visibility::create_private (), diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc index 553c9c9612da..2c124d1a16ba 100644 --- a/gcc/rust/hir/rust-ast-lower-type.cc +++ b/gcc/rust/hir/rust-ast-lower-type.cc @@ -17,17 +17,31 @@ // . #include "rust-ast-lower-type.h" -#include "optional.h" -#include "rust-attribute-values.h" +#include "rust-hir-map.h" +#include "rust-hir-path.h" +#include "rust-path.h" +#include "rust-pattern.h" namespace Rust { namespace HIR { HIR::TypePath * -ASTLowerTypePath::translate (AST::TypePath &type) +ASTLowerTypePath::translate (AST::Path &type) { ASTLowerTypePath resolver; - type.accept_vis (resolver); + + switch (type.get_path_kind ()) + { + case AST::Path::Kind::LangItem: + resolver.visit (static_cast (type)); + break; + case AST::Path::Kind::Type: + resolver.visit (static_cast (type)); + break; + default: + rust_unreachable (); + } + rust_assert (resolver.translated != nullptr); return resolver.translated; } @@ -126,6 +140,26 @@ ASTLowerTypePath::visit (AST::TypePath &path) path.has_opening_scope_resolution_op ()); } +void +ASTLowerTypePath::visit (AST::LangItemPath &path) +{ + auto crate_num = mappings.get_current_crate (); + auto hirid = mappings.get_next_hir_id (crate_num); + + Analysis::NodeMapping mapping (crate_num, path.get_node_id (), hirid, + mappings.get_next_localdef_id (crate_num)); + + std::vector> translated_segments; + translated_segments.emplace_back (std::unique_ptr ( + new HIR::TypePathSegment (mapping, + LangItem::ToString (path.get_lang_item_kind ()), + false, path.get_locus ()))); + + translated + = new HIR::TypePath (std::move (mapping), std::move (translated_segments), + path.get_locus ()); +} + HIR::QualifiedPathInType * ASTLowerQualifiedPathInType::translate (AST::QualifiedPathInType &type) { diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index 5207ce27b55a..2509276dec22 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -21,6 +21,7 @@ #include "rust-ast-lower-base.h" #include "rust-ast-lower-expr.h" +#include "rust-hir-path.h" namespace Rust { namespace HIR { @@ -31,18 +32,22 @@ class ASTLowerTypePath : public ASTLoweringBase using Rust::HIR::ASTLoweringBase::visit; public: - static HIR::TypePath *translate (AST::TypePath &type); + static HIR::TypePath *translate (AST::Path &type); void visit (AST::TypePathSegmentFunction &segment) override; void visit (AST::TypePathSegment &segment) override; void visit (AST::TypePathSegmentGeneric &segment) override; void visit (AST::TypePath &path) override; + void visit (AST::LangItemPath &path) override; protected: HIR::TypePathSegment *translated_segment; private: HIR::TypePath *translated; + + static HIR::TypePath *translate_type_path (AST::TypePath &type); + static HIR::TypePath *translate_lang_item_type_path (AST::LangItemPath &type); }; class ASTLowerQualifiedPathInType : public ASTLowerTypePath diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc index 185b82aa7f73..619efb00ac41 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ b/gcc/rust/resolve/rust-ast-resolve-item.cc @@ -678,16 +678,32 @@ ResolveItem::visit (AST::TraitImpl &impl_block) return; } + bool ok = true; + // setup paths CanonicalPath canonical_trait_type = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (impl_block.get_trait_path (), - canonical_trait_type); - if (!ok) + if (impl_block.get_trait_path ().get_path_kind () + == AST::Path::Kind::LangItem) { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; + auto &lang_item + = static_cast (impl_block.get_trait_path ()); + + canonical_trait_type + = CanonicalPath::new_seg (lang_item.get_node_id (), + LangItem::ToString ( + lang_item.get_lang_item_kind ())); + } + else + { + ok = ResolveTypeToCanonicalPath::go (impl_block.get_trait_path_type (), + canonical_trait_type); + if (!ok) + { + resolver->get_name_scope ().pop (); + resolver->get_type_scope ().pop (); + resolver->get_label_scope ().pop (); + return; + } } rust_debug ("AST::TraitImpl resolve trait type: {%s}", diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 50dd890c4e31..763838ea488b 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -21,6 +21,10 @@ #include "rust-ast-resolve-base.h" #include "rust-ast-resolve-expr.h" +#include "rust-diagnostics.h" +#include "rust-hir-map.h" +#include "rust-path.h" +#include "util/rust-hir-map.h" namespace Rust { namespace Resolver { @@ -56,6 +60,37 @@ class ResolveType : public ResolverBase using Rust::Resolver::ResolverBase::visit; public: + static NodeId go (AST::TypePath &type_path) + { + return ResolveType::go ((AST::Type &) type_path); + } + + static NodeId go (AST::Path &type_path) + { + if (type_path.get_path_kind () == AST::Path::Kind::LangItem) + { + auto &type = static_cast (type_path); + + auto lang_item = Analysis::Mappings::get () + .lookup_lang_item_node (type.get_lang_item_kind ()) + .value (); + + auto resolver = Resolver::get (); + resolver->insert_resolved_type (type.get_node_id (), lang_item); + + return lang_item; + } + + rust_assert (type_path.get_path_kind () == AST::Path::Kind::Type); + + // We have to do this dance to first downcast to a typepath, and then upcast + // to a Type. The altnernative is to split `go` into `go` and `go_inner` or + // something, but eventually this will need to change as we'll need + // `ResolveType::` to resolve other kinds of `Path`s as well. + return ResolveType::go ( + (AST::Type &) static_cast (type_path)); + } + static NodeId go (AST::Type &type) { ResolveType resolver; diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index a96dc1ccf346..f2245c987397 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -18,6 +18,7 @@ #include "optional.h" #include "rust-ast-full.h" +#include "rust-diagnostics.h" #include "rust-hir-map.h" #include "rust-late-name-resolver-2.0.h" #include "rust-default-resolver.h" @@ -247,6 +248,25 @@ Late::visit (AST::PathInExpression &expr) Definition (resolved->get_node_id ())); } +void +Late::visit (AST::LangItemPath &type) +{ + auto &mappings = Rust::Analysis::Mappings::get (); + auto lang_item = mappings.lookup_lang_item_node (type.get_lang_item_kind ()); + + if (!lang_item) + { + rust_fatal_error ( + type.get_locus (), "use of undeclared lang item %qs", + LangItem::ToString (type.get_lang_item_kind ()).c_str ()); + return; + } + + ctx.map_usage (Usage (type.get_node_id ()), Definition (lang_item.value ())); + + DefaultResolver::visit (type); +} + void Late::visit (AST::TypePath &type) { diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index 59077035ce3c..98cf09205bf4 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -46,6 +46,7 @@ class Late : public DefaultResolver // resolutions void visit (AST::IdentifierExpr &) override; void visit (AST::PathInExpression &) override; + void visit (AST::LangItemPath &) override; void visit (AST::TypePath &) override; void visit (AST::StructExprStruct &) override; void visit (AST::StructExprStructBase &) override;