diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-07-10 21:02:06 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-10 21:02:06 +0000 |
commit | 4560f469ee33536cec6af0f8e5816ff97de60de0 (patch) | |
tree | 9787b1f711ea87021e42dfa9d3316c6b8645a762 /gcc | |
parent | f090e7ca9fa0b19f1cd7df16a0476b6e252c5ef1 (diff) | |
parent | defb583203923bf4edeb0531e85fa28de5015ecb (diff) | |
download | gcc-4560f469ee33536cec6af0f8e5816ff97de60de0.zip gcc-4560f469ee33536cec6af0f8e5816ff97de60de0.tar.gz gcc-4560f469ee33536cec6af0f8e5816ff97de60de0.tar.bz2 |
Merge #551
551: Initial AssociatedType support r=philberty a=philberty
Traits can define Type aliasses which must enforce the correct resolution
onto their respective TraitImplBlocks. This PR adds all the necessary building
blocks for the initial support.
More work is needed in checking for trait-impl-item consistency with its respective
Trait item types.
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc')
35 files changed, 1288 insertions, 382 deletions
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 86da203..011ac3e 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -406,11 +406,6 @@ protected: * ident-only segment) */ class TypePathSegment { - /* TODO: may have to unify TypePathSegment and PathExprSegment (which are - * mostly the same anyway) in order to resolve goddamn syntax ambiguities. One - * difference is that function on TypePathSegment is not allowed if - * GenericArgs are, so could disallow that in constructor, which won't give - * that much size overhead. */ PathIdentSegment ident_segment; Location locus; @@ -418,6 +413,7 @@ protected: /* This is protected because it is only really used by derived classes, not * the base. */ bool has_separating_scope_resolution; + NodeId node_id; // Clone function implementation - not pure virtual as overrided by subclasses virtual TypePathSegment *clone_type_path_segment_impl () const @@ -437,14 +433,16 @@ public: TypePathSegment (PathIdentSegment ident_segment, bool has_separating_scope_resolution, Location locus) : ident_segment (std::move (ident_segment)), locus (locus), - has_separating_scope_resolution (has_separating_scope_resolution) + has_separating_scope_resolution (has_separating_scope_resolution), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} TypePathSegment (std::string segment_name, bool has_separating_scope_resolution, Location locus) : ident_segment (PathIdentSegment (std::move (segment_name))), locus (locus), - has_separating_scope_resolution (has_separating_scope_resolution) + has_separating_scope_resolution (has_separating_scope_resolution), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} virtual std::string as_string () const { return ident_segment.as_string (); } @@ -454,7 +452,7 @@ public: bool is_error () const { return ident_segment.is_error (); } /* Returns whether segment is identifier only (as opposed to generic args or - * function). Overriden in derived classes with other segments. */ + * function). Overridden in derived classes with other segments. */ virtual bool is_ident_only () const { return true; } Location get_locus () const { return locus; } @@ -468,6 +466,8 @@ public: } PathIdentSegment get_ident_segment () { return ident_segment; }; + + NodeId get_node_id () const { return node_id; } }; // Segment used in type path with generic args diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 5d19099..d822937 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -336,6 +336,8 @@ public: void visit (TyTy::InferType &) override { gcc_unreachable (); } + void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); } + void visit (TyTy::ParamType ¶m) override { param.resolve ()->accept_vis (*this); diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index 8576235..d2890e0 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -48,6 +48,8 @@ public: void visit (TyTy::ADTType &) override { gcc_unreachable (); } + void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); } + void visit (TyTy::TupleType &type) override { if (type.num_fields () == 0) diff --git a/gcc/rust/hir/rust-ast-lower-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h index 16c5aa0..b08a166 100644 --- a/gcc/rust/hir/rust-ast-lower-implitem.h +++ b/gcc/rust/hir/rust-ast-lower-implitem.h @@ -52,6 +52,38 @@ public: return resolver.translated; } + void visit (AST::TypeAlias &alias) override + { + std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items; + HIR::WhereClause where_clause (std::move (where_clause_items)); + HIR::Visibility vis = HIR::Visibility::create_public (); + + std::vector<std::unique_ptr<HIR::GenericParam> > generic_params; + if (alias.has_generics ()) + generic_params = lower_generic_params (alias.get_generic_params ()); + + HIR::Type *existing_type + = ASTLoweringType::translate (alias.get_type_aliased ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, alias.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + + translated = new HIR::TypeAlias (mapping, alias.get_new_type_name (), + std::move (generic_params), + std::move (where_clause), + std::unique_ptr<HIR::Type> (existing_type), + std::move (vis), alias.get_outer_attrs (), + alias.get_locus ()); + + mappings->insert_hir_implitem (mapping.get_crate_num (), + mapping.get_hirid (), parent_impl_id, + translated); + mappings->insert_location (crate_num, mapping.get_hirid (), + alias.get_locus ()); + } + void visit (AST::ConstantItem &constant) override { HIR::Visibility vis = HIR::Visibility::create_public (); diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index 7985faa..68324c7 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -379,6 +379,7 @@ public: HIR::ImplItem *lowered = ASTLowerImplItem::translate (impl_item.get (), mapping.get_hirid ()); + rust_assert (lowered != nullptr); impl_items.push_back (std::unique_ptr<HIR::ImplItem> (lowered)); impl_item_ids.push_back (lowered->get_impl_mappings ().get_hirid ()); } @@ -521,6 +522,7 @@ public: HIR::ImplItem *lowered = ASTLowerImplItem::translate (impl_item.get (), mapping.get_hirid ()); + rust_assert (lowered != nullptr); impl_items.push_back (std::unique_ptr<HIR::ImplItem> (lowered)); impl_item_ids.push_back (lowered->get_impl_mappings ().get_hirid ()); } diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index 568a806..0b534d0 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -35,17 +35,22 @@ public: { ASTLowerTypePath resolver; type.accept_vis (resolver); - rust_assert (resolver.translated != nullptr); - return resolver.translated; } + void visit (AST::TypePathSegmentFunction &) override { gcc_unreachable (); } + void visit (AST::TypePathSegment &segment) override { + auto crate_num = mappings->get_current_crate (); + auto hirid = mappings->get_next_hir_id (crate_num); + Analysis::NodeMapping mapping (crate_num, segment.get_node_id (), hirid, + UNKNOWN_LOCAL_DEFID); + HIR::PathIdentSegment ident (segment.get_ident_segment ().as_string ()); translated_segment - = new HIR::TypePathSegment (ident, + = new HIR::TypePathSegment (std::move (mapping), ident, segment.get_separating_scope_resolution (), segment.get_locus ()); } diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index 01abd84..516b5ba 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -383,9 +383,15 @@ ASTLowerTypePath::visit (AST::TypePathSegmentGeneric &segment) type_args.push_back (std::unique_ptr<HIR::Type> (t)); } + auto crate_num = mappings->get_current_crate (); + auto hirid = mappings->get_next_hir_id (crate_num); + Analysis::NodeMapping mapping (crate_num, segment.get_node_id (), hirid, + UNKNOWN_LOCAL_DEFID); + translated_segment = new HIR::TypePathSegmentGeneric ( - segment_name, has_separating_scope_resolution, std::move (lifetime_args), - std::move (type_args), std::move (binding_args), segment.get_locus ()); + std::move (mapping), segment_name, has_separating_scope_resolution, + std::move (lifetime_args), std::move (type_args), std::move (binding_args), + segment.get_locus ()); } } // namespace HIR diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h index 84f3e96..5d9f965 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -351,19 +351,22 @@ protected: * ident-only segment) */ class TypePathSegment { - /* TODO: may have to unify TypePathSegment and PathExprSegment (which are - * mostly the same anyway) in order to resolve goddamn syntax ambiguities. One - * difference is that function on TypePathSegment is not allowed if - * GenericArgs are, so could disallow that in constructor, which won't give - * that much size overhead. */ - PathIdentSegment ident_segment; +public: + enum SegmentType + { + REG, + GENERIC, + FUNCTION + }; +private: + Analysis::NodeMapping mappings; + PathIdentSegment ident_segment; Location locus; protected: - /* This is protected because it is only really used by derived classes, not - * the base. */ bool has_separating_scope_resolution; + SegmentType type; // Clone function implementation - not pure virtual as overrided by subclasses virtual TypePathSegment *clone_type_path_segment_impl () const @@ -374,23 +377,30 @@ protected: public: virtual ~TypePathSegment () {} + virtual SegmentType get_type () const { return SegmentType::REG; } + // Unique pointer custom clone function std::unique_ptr<TypePathSegment> clone_type_path_segment () const { return std::unique_ptr<TypePathSegment> (clone_type_path_segment_impl ()); } - TypePathSegment (PathIdentSegment ident_segment, + TypePathSegment (Analysis::NodeMapping mappings, + PathIdentSegment ident_segment, bool has_separating_scope_resolution, Location locus) - : ident_segment (std::move (ident_segment)), locus (locus), - has_separating_scope_resolution (has_separating_scope_resolution) + : mappings (std::move (mappings)), + ident_segment (std::move (ident_segment)), locus (locus), + has_separating_scope_resolution (has_separating_scope_resolution), + type (SegmentType::REG) {} - TypePathSegment (std::string segment_name, + TypePathSegment (Analysis::NodeMapping mappings, std::string segment_name, bool has_separating_scope_resolution, Location locus) - : ident_segment (PathIdentSegment (std::move (segment_name))), + : mappings (std::move (mappings)), + ident_segment (PathIdentSegment (std::move (segment_name))), locus (locus), - has_separating_scope_resolution (has_separating_scope_resolution) + has_separating_scope_resolution (has_separating_scope_resolution), + type (SegmentType::REG) {} virtual std::string as_string () const { return ident_segment.as_string (); } @@ -407,6 +417,10 @@ public: // not pure virtual as class not abstract virtual void accept_vis (HIRVisitor &vis); + + const Analysis::NodeMapping &get_mappings () const { return mappings; } + + const PathIdentSegment &get_ident_segment () const { return ident_segment; } }; // Segment used in type path with generic args @@ -420,22 +434,24 @@ public: bool is_ident_only () const override { return false; } // Constructor with PathIdentSegment and GenericArgs - TypePathSegmentGeneric (PathIdentSegment ident_segment, + TypePathSegmentGeneric (Analysis::NodeMapping mappings, + PathIdentSegment ident_segment, bool has_separating_scope_resolution, GenericArgs generic_args, Location locus) - : TypePathSegment (std::move (ident_segment), + : TypePathSegment (std::move (mappings), std::move (ident_segment), has_separating_scope_resolution, locus), generic_args (std::move (generic_args)) {} // Constructor from segment name and all args - TypePathSegmentGeneric (std::string segment_name, + TypePathSegmentGeneric (Analysis::NodeMapping mappings, + std::string segment_name, bool has_separating_scope_resolution, std::vector<Lifetime> lifetime_args, std::vector<std::unique_ptr<Type> > type_args, std::vector<GenericArgsBinding> binding_args, Location locus) - : TypePathSegment (std::move (segment_name), + : TypePathSegment (std::move (mappings), std::move (segment_name), has_separating_scope_resolution, locus), generic_args (GenericArgs (std::move (lifetime_args), std::move (type_args), @@ -446,7 +462,12 @@ public: void accept_vis (HIRVisitor &vis) override; - GenericArgs get_generic_args () { return generic_args; } + GenericArgs &get_generic_args () { return generic_args; } + + virtual SegmentType get_type () const override final + { + return SegmentType::GENERIC; + } protected: // Use covariance to override base class method @@ -544,19 +565,21 @@ class TypePathSegmentFunction : public TypePathSegment public: // Constructor with PathIdentSegment and TypePathFn - TypePathSegmentFunction (PathIdentSegment ident_segment, + TypePathSegmentFunction (Analysis::NodeMapping mappings, + PathIdentSegment ident_segment, bool has_separating_scope_resolution, TypePathFunction function_path, Location locus) - : TypePathSegment (std::move (ident_segment), + : TypePathSegment (std::move (mappings), std::move (ident_segment), has_separating_scope_resolution, locus), function_path (std::move (function_path)) {} // Constructor with segment name and TypePathFn - TypePathSegmentFunction (std::string segment_name, + TypePathSegmentFunction (Analysis::NodeMapping mappings, + std::string segment_name, bool has_separating_scope_resolution, TypePathFunction function_path, Location locus) - : TypePathSegment (std::move (segment_name), + : TypePathSegment (std::move (mappings), std::move (segment_name), has_separating_scope_resolution, locus), function_path (std::move (function_path)) {} @@ -567,6 +590,11 @@ public: void accept_vis (HIRVisitor &vis) override; + virtual SegmentType get_type () const override final + { + return SegmentType::FUNCTION; + } + protected: // Use covariance to override base class method TypePathSegmentFunction *clone_type_path_segment_impl () const override @@ -667,16 +695,15 @@ public: size_t get_num_segments () const { return segments.size (); } - void iterate_segments (std::function<bool (TypePathSegment *)> cb) + std::vector<std::unique_ptr<TypePathSegment> > &get_segments () { - for (auto &seg : segments) - { - if (!cb (seg.get ())) - return; - } + return segments; } - TypePathSegment *get_final_segment () { return segments.back ().get (); } + std::unique_ptr<TypePathSegment> &get_final_segment () + { + return segments.back (); + } }; struct QualifiedPathType diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index bbd8818..ec89f6c 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -117,8 +117,9 @@ public: void visit (AST::IdentifierExpr &expr) override { - if (resolver->get_name_scope ().lookup (CanonicalPath (expr.as_string ()), - &resolved_node)) + if (resolver->get_name_scope ().lookup ( + CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()), + &resolved_node)) { resolver->insert_resolved_name (expr.get_node_id (), resolved_node); resolver->insert_new_definition (expr.get_node_id (), @@ -126,7 +127,8 @@ public: parent}); } else if (resolver->get_type_scope ().lookup ( - CanonicalPath (expr.as_string ()), &resolved_node)) + CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()), + &resolved_node)) { resolver->insert_resolved_type (expr.get_node_id (), resolved_node); resolver->insert_new_definition (expr.get_node_id (), @@ -272,8 +274,8 @@ public: auto label_name = label.get_lifetime ().get_lifetime_name (); auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); resolver->get_label_scope ().insert ( - CanonicalPath (label_name), label_lifetime_node_id, - label.get_locus (), false, + CanonicalPath::new_seg (expr.get_node_id (), label_name), + label_lifetime_node_id, label.get_locus (), false, [&] (const CanonicalPath &, NodeId, Location locus) -> void { rust_error_at (label.get_locus (), "label redefined multiple times"); @@ -300,7 +302,9 @@ public: NodeId resolved_node = UNKNOWN_NODEID; if (!resolver->get_label_scope ().lookup ( - CanonicalPath (label.get_lifetime_name ()), &resolved_node)) + CanonicalPath::new_seg (label.get_node_id (), + label.get_lifetime_name ()), + &resolved_node)) { rust_error_at (expr.get_label ().get_locus (), "failed to resolve label"); @@ -329,8 +333,8 @@ public: auto label_name = label.get_lifetime ().get_lifetime_name (); auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); resolver->get_label_scope ().insert ( - CanonicalPath (label_name), label_lifetime_node_id, - label.get_locus (), false, + CanonicalPath::new_seg (label.get_node_id (), label_name), + label_lifetime_node_id, label.get_locus (), false, [&] (const CanonicalPath &, NodeId, Location locus) -> void { rust_error_at (label.get_locus (), "label redefined multiple times"); @@ -358,7 +362,9 @@ public: NodeId resolved_node = UNKNOWN_NODEID; if (!resolver->get_label_scope ().lookup ( - CanonicalPath (label.get_lifetime_name ()), &resolved_node)) + CanonicalPath::new_seg (label.get_node_id (), + label.get_lifetime_name ()), + &resolved_node)) { rust_error_at (expr.get_label ().get_locus (), "failed to resolve label"); diff --git a/gcc/rust/resolve/rust-ast-resolve-implitem.h b/gcc/rust/resolve/rust-ast-resolve-implitem.h index 576cd3e..2b3a09a 100644 --- a/gcc/rust/resolve/rust-ast-resolve-implitem.h +++ b/gcc/rust/resolve/rust-ast-resolve-implitem.h @@ -43,6 +43,22 @@ public: item->accept_vis (resolver); } + void visit (AST::TypeAlias &type) override + { + auto path = prefix.append ( + CanonicalPath::new_seg (type.get_node_id (), type.get_new_type_name ())); + resolver->get_type_scope ().insert ( + path, type.get_node_id (), type.get_locus (), false, + [&] (const CanonicalPath &, NodeId, Location locus) -> void { + RichLocation r (type.get_locus ()); + r.add_range (locus); + rust_error_at (r, "redefined multiple times"); + }); + resolver->insert_new_definition (type.get_node_id (), + Definition{type.get_node_id (), + type.get_node_id ()}); + } + void visit (AST::ConstantItem &constant) override { auto path diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index fafd27e..1f1ff30 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -28,11 +28,168 @@ namespace Rust { namespace Resolver { -class ResolveItem : public ResolverBase +class ResolveTraitItems : public ResolverBase { using Rust::Resolver::ResolverBase::visit; public: + static void go (AST::TraitItem *item, const CanonicalPath &self) + { + ResolveTraitItems resolver (self); + item->accept_vis (resolver); + }; + + void visit (AST::TraitItemType &type) override + { + // insert Self::type_alias for TypePath lookup + auto path + = self.append (ResolveTraitItemTypeToCanonicalPath::resolve (type)); + resolver->get_type_scope ().insert ( + path, type.get_node_id (), type.get_locus (), false, + [&] (const CanonicalPath &, NodeId, Location locus) -> void { + RichLocation r (type.get_locus ()); + r.add_range (locus); + rust_error_at (r, "redefined multiple times"); + }); + + // FIXME this stops the erronious unused decls which will be fixed later on + resolver->get_type_scope ().append_reference_for_def (type.get_node_id (), + type.get_node_id ()); + + // TODO resolve the type-bounds + } + + void visit (AST::TraitItemFunc &func) override + { + NodeId scope_node_id = func.get_node_id (); + resolver->get_name_scope ().push (scope_node_id); + resolver->get_type_scope ().push (scope_node_id); + resolver->get_label_scope ().push (scope_node_id); + resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); + resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); + resolver->push_new_label_rib (resolver->get_type_scope ().peek ()); + + AST::TraitFunctionDecl &function = func.get_trait_function_decl (); + if (function.has_generics ()) + { + for (auto &generic : function.get_generic_params ()) + ResolveGenericParam::go (generic.get (), func.get_node_id ()); + } + + if (function.has_return_type ()) + ResolveType::go (function.get_return_type ().get (), func.get_node_id ()); + + // we make a new scope so the names of parameters are resolved and shadowed + // correctly + for (auto ¶m : function.get_function_params ()) + { + ResolveType::go (param.get_type ().get (), param.get_node_id ()); + PatternDeclaration::go (param.get_pattern ().get (), + param.get_node_id ()); + + // the mutability checker needs to verify for immutable decls the number + // of assignments are <1. This marks an implicit assignment + resolver->mark_assignment_to_decl (param.get_pattern ()->get_node_id (), + param.get_node_id ()); + } + + // trait items have an optional body + if (func.has_definition ()) + ResolveExpr::go (func.get_definition ().get (), func.get_node_id ()); + + resolver->get_name_scope ().pop (); + resolver->get_type_scope ().pop (); + resolver->get_label_scope ().pop (); + } + + void visit (AST::TraitItemMethod &func) override + { + NodeId scope_node_id = func.get_node_id (); + resolver->get_name_scope ().push (scope_node_id); + resolver->get_type_scope ().push (scope_node_id); + resolver->get_label_scope ().push (scope_node_id); + resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); + resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); + resolver->push_new_label_rib (resolver->get_type_scope ().peek ()); + + AST::TraitMethodDecl &function = func.get_trait_method_decl (); + if (function.has_generics ()) + { + for (auto &generic : function.get_generic_params ()) + ResolveGenericParam::go (generic.get (), func.get_node_id ()); + } + + if (function.has_return_type ()) + ResolveType::go (function.get_return_type ().get (), func.get_node_id ()); + + // self turns into (self: Self) as a function param + AST::SelfParam &self_param = function.get_self_param (); + AST::IdentifierPattern self_pattern ( + self_param.get_node_id (), "self", self_param.get_locus (), + self_param.get_has_ref (), self_param.get_is_mut (), + std::unique_ptr<AST::Pattern> (nullptr)); + + std::vector<std::unique_ptr<AST::TypePathSegment> > segments; + segments.push_back (std::unique_ptr<AST::TypePathSegment> ( + new AST::TypePathSegment ("Self", false, self_param.get_locus ()))); + + AST::TypePath self_type_path (std::move (segments), + self_param.get_locus ()); + + ResolveType::go (&self_type_path, self_param.get_node_id ()); + PatternDeclaration::go (&self_pattern, self_param.get_node_id ()); + + resolver->mark_assignment_to_decl (self_pattern.get_node_id (), + self_pattern.get_node_id ()); + + // we make a new scope so the names of parameters are resolved and shadowed + // correctly + for (auto ¶m : function.get_function_params ()) + { + ResolveType::go (param.get_type ().get (), param.get_node_id ()); + PatternDeclaration::go (param.get_pattern ().get (), + param.get_node_id ()); + + // the mutability checker needs to verify for immutable decls the number + // of assignments are <1. This marks an implicit assignment + resolver->mark_assignment_to_decl (param.get_pattern ()->get_node_id (), + param.get_node_id ()); + } + + // trait items have an optional body + if (func.has_definition ()) + ResolveExpr::go (func.get_definition ().get (), func.get_node_id ()); + + resolver->get_name_scope ().pop (); + resolver->get_type_scope ().pop (); + resolver->get_label_scope ().pop (); + } + + void visit (AST::TraitItemConst &constant) override + { + ResolveType::go (constant.get_type ().get (), constant.get_node_id ()); + ResolveExpr::go (constant.get_expr ().get (), constant.get_node_id ()); + + // the mutability checker needs to verify for immutable decls the number + // of assignments are <1. This marks an implicit assignment + resolver->mark_decl_mutability (constant.get_node_id (), false); + resolver->mark_assignment_to_decl (constant.get_node_id (), + constant.get_node_id ()); + } + +private: + ResolveTraitItems (const CanonicalPath &self) + : ResolverBase (UNKNOWN_NODEID), self (self) + {} + + const CanonicalPath &self; +}; + +class ResolveItem : public ResolverBase +{ +public: + using Rust::Resolver::ResolverBase::visit; + static void go (AST::Item *item) { ResolveItem resolver; @@ -169,7 +326,10 @@ public: void visit (AST::InherentImpl &impl_block) override { NodeId scope_node_id = impl_block.get_node_id (); + resolver->get_name_scope ().push (scope_node_id); resolver->get_type_scope ().push (scope_node_id); + resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); + resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); if (impl_block.has_generics ()) { @@ -184,18 +344,29 @@ public: impl_block.get_node_id (), canonicalize_type_with_generics); if (resolved_node == UNKNOWN_NODEID) - return; + { + resolver->get_type_scope ().pop (); + resolver->get_name_scope ().pop (); + return; + } + + auto Self + = CanonicalPath::get_big_self (impl_block.get_type ()->get_node_id ()); resolver->get_type_scope ().insert ( - CanonicalPath::get_big_self (), impl_block.get_type ()->get_node_id (), + Self, impl_block.get_type ()->get_node_id (), impl_block.get_type ()->get_locus_slow ()); for (auto &impl_item : impl_block.get_impl_items ()) - impl_item->accept_vis (*this); + { + resolve_impl_item (impl_item.get (), Self); + } resolver->get_type_scope ().peek ()->clear_name ( - CanonicalPath::get_big_self (), impl_block.get_type ()->get_node_id ()); + Self, impl_block.get_type ()->get_node_id ()); + resolver->get_type_scope ().pop (); + resolver->get_name_scope ().pop (); } void visit (AST::Method &method) override @@ -262,7 +433,10 @@ public: void visit (AST::TraitImpl &impl_block) override { NodeId scope_node_id = impl_block.get_node_id (); + resolver->get_name_scope ().push (scope_node_id); resolver->get_type_scope ().push (scope_node_id); + resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); + resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); if (impl_block.has_generics ()) { @@ -280,6 +454,7 @@ public: if (trait_resolved_node == UNKNOWN_NODEID) { resolver->get_type_scope ().pop (); + resolver->get_name_scope ().pop (); return; } @@ -290,156 +465,109 @@ public: if (type_resolved_node == UNKNOWN_NODEID) { resolver->get_type_scope ().pop (); + resolver->get_name_scope ().pop (); return; } + auto Self + = CanonicalPath::get_big_self (impl_block.get_type ()->get_node_id ()); + resolver->get_type_scope ().insert ( - CanonicalPath::get_big_self (), impl_block.get_type ()->get_node_id (), + Self, impl_block.get_type ()->get_node_id (), impl_block.get_type ()->get_locus_slow ()); for (auto &impl_item : impl_block.get_impl_items ()) - impl_item->accept_vis (*this); + { + resolve_impl_item (impl_item.get (), Self); + } resolver->get_type_scope ().peek ()->clear_name ( - CanonicalPath::get_big_self (), impl_block.get_type ()->get_node_id ()); + Self, impl_block.get_type ()->get_node_id ()); resolver->get_type_scope ().pop (); } void visit (AST::Trait &trait) override { NodeId scope_node_id = trait.get_node_id (); + resolver->get_name_scope ().push (scope_node_id); resolver->get_type_scope ().push (scope_node_id); + resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); + resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); // we need to inject an implicit self TypeParam here AST::TypeParam *implicit_self = new AST::TypeParam ("Self", trait.get_locus ()); trait.insert_implict_self ( std::unique_ptr<AST::GenericParam> (implicit_self)); + CanonicalPath Self = CanonicalPath::get_big_self (trait.get_node_id ()); for (auto &generic : trait.get_generic_params ()) { ResolveGenericParam::go (generic.get (), trait.get_node_id ()); } - for (auto &item : trait.get_trait_items ()) - item->accept_vis (*this); - - resolver->get_type_scope ().pop (); - } - - void visit (AST::TraitItemFunc &func) override - { - NodeId scope_node_id = func.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_type_scope ().peek ()); - - AST::TraitFunctionDecl &function = func.get_trait_function_decl (); - if (function.has_generics ()) - { - for (auto &generic : function.get_generic_params ()) - ResolveGenericParam::go (generic.get (), func.get_node_id ()); - } - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ().get (), func.get_node_id ()); + // Self is an implicit TypeParam so lets mark it as such + resolver->get_type_scope ().append_reference_for_def ( + Self.get_id (), implicit_self->get_node_id ()); - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto ¶m : function.get_function_params ()) + for (auto &item : trait.get_trait_items ()) { - ResolveType::go (param.get_type ().get (), param.get_node_id ()); - PatternDeclaration::go (param.get_pattern ().get (), - param.get_node_id ()); - - // the mutability checker needs to verify for immutable decls the number - // of assignments are <1. This marks an implicit assignment - resolver->mark_assignment_to_decl (param.get_pattern ()->get_node_id (), - param.get_node_id ()); + ResolveTraitItems::go (item.get (), Self); } - // trait items have an optional body - if (func.has_definition ()) - ResolveExpr::go (func.get_definition ().get (), func.get_node_id ()); - - resolver->get_name_scope ().pop (); resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); + resolver->get_name_scope ().pop (); } - void visit (AST::TraitItemMethod &func) override - { - NodeId scope_node_id = func.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_type_scope ().peek ()); - - AST::TraitMethodDecl &function = func.get_trait_method_decl (); - if (function.has_generics ()) - { - for (auto &generic : function.get_generic_params ()) - ResolveGenericParam::go (generic.get (), func.get_node_id ()); - } - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ().get (), func.get_node_id ()); - - // self turns into (self: Self) as a function param - AST::SelfParam &self_param = function.get_self_param (); - AST::IdentifierPattern self_pattern ( - self_param.get_node_id (), "self", self_param.get_locus (), - self_param.get_has_ref (), self_param.get_is_mut (), - std::unique_ptr<AST::Pattern> (nullptr)); +protected: + void resolve_impl_item (AST::TraitImplItem *item, const CanonicalPath &self); + void resolve_impl_item (AST::InherentImplItem *item, + const CanonicalPath &self); - std::vector<std::unique_ptr<AST::TypePathSegment> > segments; - segments.push_back (std::unique_ptr<AST::TypePathSegment> ( - new AST::TypePathSegment ("Self", false, self_param.get_locus ()))); - - AST::TypePath self_type_path (std::move (segments), - self_param.get_locus ()); - - ResolveType::go (&self_type_path, self_param.get_node_id ()); - PatternDeclaration::go (&self_pattern, self_param.get_node_id ()); + ResolveItem () : ResolverBase (UNKNOWN_NODEID) {} +}; - resolver->mark_assignment_to_decl (self_pattern.get_node_id (), - self_pattern.get_node_id ()); +class ResolveImplItems : public ResolveItem +{ + using Rust::Resolver::ResolveItem::visit; - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto ¶m : function.get_function_params ()) - { - ResolveType::go (param.get_type ().get (), param.get_node_id ()); - PatternDeclaration::go (param.get_pattern ().get (), - param.get_node_id ()); +public: + static void go (AST::InherentImplItem *item, const CanonicalPath &self) + { + ResolveImplItems resolver (self); + item->accept_vis (resolver); + }; - // the mutability checker needs to verify for immutable decls the number - // of assignments are <1. This marks an implicit assignment - resolver->mark_assignment_to_decl (param.get_pattern ()->get_node_id (), - param.get_node_id ()); - } + static void go (AST::TraitImplItem *item, const CanonicalPath &self) + { + ResolveImplItems resolver (self); + item->accept_vis (resolver); + }; - // trait items have an optional body - if (func.has_definition ()) - ResolveExpr::go (func.get_definition ().get (), func.get_node_id ()); + void visit (AST::TypeAlias &alias) override + { + ResolveItem::visit (alias); - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); + auto path + = self.append (CanonicalPath::new_seg (alias.get_node_id (), + alias.get_new_type_name ())); + resolver->get_type_scope ().insert ( + path, alias.get_node_id (), alias.get_locus (), false, + [&] (const CanonicalPath &, NodeId, Location locus) -> void { + RichLocation r (alias.get_locus ()); + r.add_range (locus); + rust_error_at (r, "redefined multiple times"); + }); + + // FIXME this stops the erronious unused decls which will be fixed later on + resolver->get_type_scope ().append_reference_for_def (alias.get_node_id (), + alias.get_node_id ()); } - // TODO - void visit (AST::TraitItemConst &) override { gcc_unreachable (); } - - void visit (AST::TraitItemType &) override { gcc_unreachable (); } - private: - ResolveItem () : ResolverBase (UNKNOWN_NODEID) {} + ResolveImplItems (const CanonicalPath &self) : ResolveItem (), self (self) {} + + const CanonicalPath &self; }; } // namespace Resolver diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h index 0734908..a41764a 100644 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.h +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h @@ -44,7 +44,8 @@ public: void visit (AST::IdentifierPattern &pattern) override { if (resolver->get_name_scope ().lookup ( - CanonicalPath (pattern.get_ident ()), &resolved_node)) + CanonicalPath::new_seg (pattern.get_node_id (), pattern.get_ident ()), + &resolved_node)) { resolver->insert_resolved_name (pattern.get_node_id (), resolved_node); resolver->insert_new_definition (pattern.get_node_id (), @@ -72,9 +73,9 @@ public: { // if we have a duplicate id this then allows for shadowing correctly // as new refs to this decl will match back here so it is ok to overwrite - resolver->get_name_scope ().insert (CanonicalPath (pattern.get_ident ()), - pattern.get_node_id (), - pattern.get_locus ()); + resolver->get_name_scope ().insert ( + CanonicalPath::new_seg (pattern.get_node_id (), pattern.get_ident ()), + pattern.get_node_id (), pattern.get_locus ()); resolver->insert_new_definition (pattern.get_node_id (), Definition{pattern.get_node_id (), parent}); diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h index e68e7b9..210a9fc 100644 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -67,7 +67,8 @@ public: void visit (AST::TupleStruct &struct_decl) override { - auto path = CanonicalPath (struct_decl.get_identifier ()); + auto path = CanonicalPath::new_seg (struct_decl.get_node_id (), + struct_decl.get_identifier ()); resolver->get_type_scope ().insert ( path, struct_decl.get_node_id (), struct_decl.get_locus (), false, [&] (const CanonicalPath &, NodeId, Location locus) -> void { @@ -99,7 +100,8 @@ public: void visit (AST::StructStruct &struct_decl) override { - auto path = CanonicalPath (struct_decl.get_identifier ()); + auto path = CanonicalPath::new_seg (struct_decl.get_node_id (), + struct_decl.get_identifier ()); resolver->get_type_scope ().insert ( path, struct_decl.get_node_id (), struct_decl.get_locus (), false, [&] (const CanonicalPath &, NodeId, Location locus) -> void { diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h index 3dd81d8..9abbb18 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -41,7 +41,9 @@ public: void visit (AST::TypeAlias &alias) override { - auto path = prefix.append (CanonicalPath (alias.get_new_type_name ())); + auto path + = prefix.append (CanonicalPath::new_seg (alias.get_node_id (), + alias.get_new_type_name ())); resolver->get_type_scope ().insert ( path, alias.get_node_id (), alias.get_locus (), false, [&] (const CanonicalPath &, NodeId, Location locus) -> void { @@ -53,7 +55,9 @@ public: void visit (AST::TupleStruct &struct_decl) override { - auto path = prefix.append (CanonicalPath (struct_decl.get_identifier ())); + auto path + = prefix.append (CanonicalPath::new_seg (struct_decl.get_node_id (), + struct_decl.get_identifier ())); resolver->get_type_scope ().insert ( path, struct_decl.get_node_id (), struct_decl.get_locus (), false, [&] (const CanonicalPath &, NodeId, Location locus) -> void { @@ -65,7 +69,9 @@ public: void visit (AST::StructStruct &struct_decl) override { - auto path = prefix.append (CanonicalPath (struct_decl.get_identifier ())); + auto path + = prefix.append (CanonicalPath::new_seg (struct_decl.get_node_id (), + struct_decl.get_identifier ())); resolver->get_type_scope ().insert ( path, struct_decl.get_node_id (), struct_decl.get_locus (), false, [&] (const CanonicalPath &, NodeId, Location locus) -> void { @@ -77,7 +83,8 @@ public: void visit (AST::StaticItem &var) override { - auto path = prefix.append (CanonicalPath (var.get_identifier ())); + auto path = prefix.append ( + CanonicalPath::new_seg (var.get_node_id (), var.get_identifier ())); resolver->get_name_scope ().insert ( path, var.get_node_id (), var.get_locus (), false, [&] (const CanonicalPath &, NodeId, Location locus) -> void { @@ -160,7 +167,8 @@ public: type_resolve_generic_args); CanonicalPath projection - = TraitImplProjection::resolve (trait_type_seg, impl_type_seg); + = TraitImplProjection::resolve (impl_block.get_node_id (), trait_type_seg, + impl_type_seg); CanonicalPath impl_prefix = prefix.append (projection); for (auto &impl_item : impl_block.get_impl_items ()) @@ -169,8 +177,8 @@ public: void visit (AST::Trait &trait) override { - CanonicalPath path - = prefix.append (CanonicalPath (trait.get_identifier ())); + CanonicalPath path = prefix.append ( + CanonicalPath::new_seg (trait.get_node_id (), trait.get_identifier ())); resolver->get_type_scope ().insert ( path, trait.get_node_id (), trait.get_locus (), false, [&] (const CanonicalPath &, NodeId, Location locus) -> void { @@ -180,7 +188,7 @@ public: }); for (auto &item : trait.get_trait_items ()) - ResolveTopLevelTraitItems::go (item.get ()); + ResolveTopLevelTraitItems::go (item.get (), path); } private: diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 19e7324..23419b0 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -30,7 +30,8 @@ class ResolveConstantItemToCanonicalPath public: static CanonicalPath resolve (AST::ConstantItem &constant) { - return CanonicalPath (constant.get_identifier ()); + return CanonicalPath::new_seg (constant.get_node_id (), + constant.get_identifier ()); } }; @@ -39,7 +40,8 @@ class ResolveFunctionItemToCanonicalPath public: static CanonicalPath resolve (AST::Function &function) { - return CanonicalPath (function.get_function_name ()); + return CanonicalPath::new_seg (function.get_node_id (), + function.get_function_name ()); } }; @@ -48,7 +50,8 @@ class ResolveMethodItemToCanonicalPath public: static CanonicalPath resolve (AST::Method &method) { - return CanonicalPath (method.get_method_name ()); + return CanonicalPath::new_seg (method.get_node_id (), + method.get_method_name ()); } }; @@ -57,7 +60,8 @@ class ResolveTraitItemFunctionToCanonicalPath public: static CanonicalPath resolve (AST::TraitItemFunc &function) { - return CanonicalPath ( + return CanonicalPath::new_seg ( + function.get_node_id (), function.get_trait_function_decl ().get_identifier ()); } }; @@ -67,7 +71,8 @@ class ResolveTraitItemMethodToCanonicalPath public: static CanonicalPath resolve (AST::TraitItemMethod &method) { - return CanonicalPath (method.get_trait_method_decl ().get_identifier ()); + return CanonicalPath::new_seg ( + method.get_node_id (), method.get_trait_method_decl ().get_identifier ()); } }; @@ -76,7 +81,8 @@ class ResolveTraitItemConstToCanonicalPath public: static CanonicalPath resolve (AST::TraitItemConst &constant) { - return CanonicalPath (constant.get_identifier ()); + return CanonicalPath::new_seg (constant.get_node_id (), + constant.get_identifier ()); } }; @@ -85,7 +91,7 @@ class ResolveTraitItemTypeToCanonicalPath public: static CanonicalPath resolve (AST::TraitItemType &type) { - return CanonicalPath (type.get_identifier ()); + return CanonicalPath::new_seg (type.get_node_id (), type.get_identifier ()); } }; @@ -118,7 +124,7 @@ public: void visit (AST::TypePathSegment &seg) override; - static CanonicalPath canonicalize_generic_args (AST::GenericArgs &args); + static std::string canonicalize_generic_args (AST::GenericArgs &args); static bool type_resolve_generic_args (AST::GenericArgs &args); @@ -142,40 +148,40 @@ class ResolvePathSegmentToCanonicalPath public: static CanonicalPath resolve (AST::PathExprSegment &seg) { - CanonicalPath path = CanonicalPath (seg.get_ident_segment ().as_string ()); - if (seg.has_generic_args ()) + if (!seg.has_generic_args ()) + return CanonicalPath::new_seg (seg.get_node_id (), + seg.get_ident_segment ().as_string ()); + + bool ok = ResolveTypeToCanonicalPath::type_resolve_generic_args ( + seg.get_generic_args ()); + if (!ok) { - bool ok = ResolveTypeToCanonicalPath::type_resolve_generic_args ( - seg.get_generic_args ()); - if (!ok) - { - rust_error_at (seg.get_locus (), - "failed to resolve all generic arguments"); - return CanonicalPath::create_empty (); - } - - path - = path.append (ResolveTypeToCanonicalPath::canonicalize_generic_args ( - seg.get_generic_args ())); + rust_error_at (seg.get_locus (), + "failed to resolve all generic arguments"); + return CanonicalPath::create_empty (); } - return path; + + std::string generics + = ResolveTypeToCanonicalPath::canonicalize_generic_args ( + seg.get_generic_args ()); + + return CanonicalPath::new_seg (seg.get_node_id (), + seg.get_ident_segment ().as_string () + + "::" + generics); } }; class TraitImplProjection { public: - static CanonicalPath resolve (const CanonicalPath &trait_seg, + static CanonicalPath resolve (NodeId id, const CanonicalPath &trait_seg, const CanonicalPath &impl_type_seg) { - return CanonicalPath ("<" + impl_type_seg.get () + " as " + trait_seg.get () - + ">"); + return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + " as " + + trait_seg.get () + ">"); } }; -// FIXME: as part of imports and visibility we need to be able to keep a context -// for handling PathInExpressions segments as they can be local to a particular -// lexical scope requiring a context to be maintained for resolution class ResolveRelativeTypePath { public: @@ -189,7 +195,8 @@ public: true); if (canonical_path.is_error ()) { - rust_error_at (path.get_locus (), "Failed to resolve canonical path"); + rust_error_at (path.get_locus (), + "Failed to resolve canonical path for TypePath"); return UNKNOWN_NODEID; } @@ -316,8 +323,9 @@ public: // for now lets focus on handling the basics: like struct<T> { a:T, ....} resolver->get_type_scope ().insert ( - CanonicalPath (param.get_type_representation ()), param.get_node_id (), - param.get_locus (), false, + CanonicalPath::new_seg (param.get_node_id (), + param.get_type_representation ()), + param.get_node_id (), param.get_locus (), false, [&] (const CanonicalPath &, NodeId, Location locus) -> void { rust_error_at (param.get_locus (), "generic param redefined multiple times"); diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index fae3f77..18047db 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -121,7 +121,9 @@ Resolver::insert_builtin_types (Rib *r) auto builtins = get_builtin_types (); for (auto &builtin : builtins) { - CanonicalPath builtin_path (builtin->as_string ()); + CanonicalPath builtin_path + = CanonicalPath::new_seg (builtin->get_node_id (), + builtin->as_string ()); r->insert_name (builtin_path, builtin->get_node_id (), Linemap::predeclared_location (), false, [] (const CanonicalPath &, NodeId, Location) -> void {}); @@ -384,7 +386,7 @@ ResolveStructExprField::visit (AST::StructExprFieldIdentifier &field) // rust-ast-resolve-type.h -CanonicalPath +std::string ResolveTypeToCanonicalPath::canonicalize_generic_args (AST::GenericArgs &args) { std::string buf; @@ -401,7 +403,7 @@ ResolveTypeToCanonicalPath::canonicalize_generic_args (AST::GenericArgs &args) i++; } - return CanonicalPath ("<" + buf + ">"); + return "<" + buf + ">"; } bool @@ -428,24 +430,31 @@ ResolveTypeToCanonicalPath::visit (AST::TypePathSegmentGeneric &seg) return; } - // ident seg - CanonicalPath ident_seg - = CanonicalPath (seg.get_ident_segment ().as_string ()); - result = result.append (ident_seg); + if (!seg.has_generic_args ()) + { + result = CanonicalPath::new_seg (seg.get_node_id (), + seg.get_ident_segment ().as_string ()); + return; + } - // generic args - if (seg.has_generic_args ()) + if (type_resolve_generic_args_flag) { - if (include_generic_args_flag) - result - = result.append (canonicalize_generic_args (seg.get_generic_args ())); + bool ok = type_resolve_generic_args (seg.get_generic_args ()); + failure_flag = !ok; + } - if (type_resolve_generic_args_flag) - { - bool ok = type_resolve_generic_args (seg.get_generic_args ()); - failure_flag = !ok; - } + if (include_generic_args_flag) + { + std::string generics + = canonicalize_generic_args (seg.get_generic_args ()); + result = CanonicalPath::new_seg (seg.get_node_id (), + seg.get_ident_segment ().as_string () + + "::" + generics); + return; } + + result = CanonicalPath::new_seg (seg.get_node_id (), + seg.get_ident_segment ().as_string ()); } void @@ -460,7 +469,8 @@ ResolveTypeToCanonicalPath::visit (AST::TypePathSegment &seg) } CanonicalPath ident_seg - = CanonicalPath (seg.get_ident_segment ().as_string ()); + = CanonicalPath::new_seg (seg.get_node_id (), + seg.get_ident_segment ().as_string ()); result = result.append (ident_seg); } @@ -474,7 +484,9 @@ ResolvePath::resolve_path (AST::PathInExpression *expr) AST::PathIdentSegment &root_ident_seg = root_segment.get_ident_segment (); bool segment_is_type = false; - CanonicalPath root_seg_path (root_ident_seg.as_string ()); + CanonicalPath root_seg_path + = CanonicalPath::new_seg (expr->get_node_id (), + root_ident_seg.as_string ()); // name scope first if (resolver->get_name_scope ().lookup (root_seg_path, &resolved_node)) @@ -607,5 +619,21 @@ ResolveType::visit (AST::ArrayType &type) ResolveExpr::go (type.get_size_expr ().get (), type.get_node_id ()); } +// rust-ast-resolve-item.h + +void +ResolveItem::resolve_impl_item (AST::TraitImplItem *item, + const CanonicalPath &self) +{ + ResolveImplItems::go (item, self); +} + +void +ResolveItem::resolve_impl_item (AST::InherentImplItem *item, + const CanonicalPath &self) +{ + ResolveImplItems::go (item, self); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-verify-assignee.h b/gcc/rust/resolve/rust-ast-verify-assignee.h index 13b6c91..aed0119 100644 --- a/gcc/rust/resolve/rust-ast-verify-assignee.h +++ b/gcc/rust/resolve/rust-ast-verify-assignee.h @@ -57,8 +57,9 @@ public: void visit (AST::IdentifierExpr &expr) override { - if (!resolver->get_name_scope ().lookup (CanonicalPath (expr.as_string ()), - &resolved_node)) + if (!resolver->get_name_scope ().lookup ( + CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()), + &resolved_node)) return; ok = true; diff --git a/gcc/rust/resolve/rust-name-resolver.h b/gcc/rust/resolve/rust-name-resolver.h index b1f745e..7938c7c 100644 --- a/gcc/rust/resolve/rust-name-resolver.h +++ b/gcc/rust/resolve/rust-name-resolver.h @@ -47,34 +47,74 @@ namespace Resolver { class CanonicalPath { public: - explicit CanonicalPath (std::string path) : path (path) {} - - CanonicalPath (const CanonicalPath &other) : path (other.path) {} + CanonicalPath (const CanonicalPath &other) : segs (other.segs) {} CanonicalPath &operator= (const CanonicalPath &other) { - path = other.path; + segs = other.segs; return *this; } - std::string get () const { return path; } - - static CanonicalPath get_big_self () { return CanonicalPath ("Self"); } + static CanonicalPath new_seg (NodeId id, const std::string &path) + { + rust_assert (!path.empty ()); + return CanonicalPath ({std::pair<NodeId, std::string> (id, path)}); + } - static CanonicalPath get_wee_self () { return CanonicalPath ("self"); } + std::string get () const + { + std::string buf; + for (size_t i = 0; i < segs.size (); i++) + { + bool have_more = (i + 1) < segs.size (); + const std::string &seg = segs.at (i).second; + buf += seg + (have_more ? "::" : ""); + } + return buf; + } - static CanonicalPath create_empty () + static CanonicalPath get_big_self (NodeId id) { - return CanonicalPath (std::string ()); + return CanonicalPath::new_seg (id, "Self"); } - bool is_error () const { return path.empty (); } + static CanonicalPath create_empty () { return CanonicalPath ({}); } + + bool is_error () const { return segs.size () == 0; } CanonicalPath append (const CanonicalPath &other) const { rust_assert (!other.is_error ()); - return is_error () ? CanonicalPath (other.get ()) - : CanonicalPath (append (other.get ())); + if (is_error ()) + return CanonicalPath (other.segs); + + std::vector<std::pair<NodeId, std::string>> copy (segs); + for (auto &s : other.segs) + copy.push_back (s); + + return CanonicalPath (copy); + } + + // if we have the path A::B::C this will give a callback for each segment + // example: + // A + // A::B + // A::B::C + void iterate (std::function<bool (const CanonicalPath &)> cb) const + { + std::vector<std::pair<NodeId, std::string>> buf; + for (auto &seg : segs) + { + buf.push_back (seg); + if (!cb (CanonicalPath (buf))) + return; + } + } + + NodeId get_id () const + { + rust_assert (!segs.empty ()); + return segs.back ().first; } bool operator== (const CanonicalPath &b) const @@ -85,9 +125,11 @@ public: bool operator< (const CanonicalPath &b) const { return get () < b.get (); } private: - std::string append (std::string elem) const { return path + "::" + elem; } + explicit CanonicalPath (std::vector<std::pair<NodeId, std::string>> path) + : segs (path) + {} - std::string path; + std::vector<std::pair<NodeId, std::string>> segs; }; class Rib @@ -216,8 +258,8 @@ private: NodeId node_id; std::map<CanonicalPath, NodeId> mappings; std::map<NodeId, CanonicalPath> reverse_mappings; - std::set<std::pair<NodeId, Location> > decls_within_rib; - std::map<NodeId, std::set<NodeId> > references; + std::set<std::pair<NodeId, Location>> decls_within_rib; + std::map<NodeId, std::set<NodeId>> references; }; class Scope @@ -284,7 +326,6 @@ public: { ok = true; r->append_reference_for_def (defId, refId); - return false; } return true; }); @@ -455,7 +496,7 @@ private: // map of resolved names mutability flag std::map<NodeId, bool> decl_mutability; // map of resolved names and set of assignments to the decl - std::map<NodeId, std::set<NodeId> > assignment_to_decl; + std::map<NodeId, std::set<NodeId>> assignment_to_decl; }; } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-const-fold.h b/gcc/rust/typecheck/rust-hir-const-fold.h index 90ea595..c71dd39 100644 --- a/gcc/rust/typecheck/rust-hir-const-fold.h +++ b/gcc/rust/typecheck/rust-hir-const-fold.h @@ -51,6 +51,8 @@ public: void visit (TyTy::FnType &) override { gcc_unreachable (); } + void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); } + void visit (TyTy::TupleType &type) override { if (type.num_fields () == 0) diff --git a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h index 47894b1..0879360 100644 --- a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h +++ b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h @@ -37,6 +37,12 @@ public: return resolver.ok; } + void visit (HIR::TypeAlias &alias) override + { + ok = true; + result.assign (alias.get_new_type_name ()); + } + void visit (HIR::Function &function) override { ok = true; @@ -145,7 +151,7 @@ public: if (query == candidate) continue; - if (query->can_eq (candidate)) + if (query->can_eq (candidate, 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 0e26778..a10a562 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.h +++ b/gcc/rust/typecheck/rust-hir-path-probe.h @@ -58,13 +58,28 @@ public: bool ok = context->lookup_type (impl_ty_id, &impl_block_ty); rust_assert (ok); - if (!receiver->can_eq (impl_block_ty)) + if (!receiver->can_eq (impl_block_ty, false)) return; // lets visit the impl_item item->accept_vis (*this); } + void visit (HIR::TypeAlias &alias) override + { + Identifier name = alias.get_new_type_name (); + if (search.as_string ().compare (name) == 0) + { + HirId tyid = alias.get_mappings ().get_hirid (); + TyTy::BaseType *ty = nullptr; + bool ok = context->lookup_type (tyid, &ty); + rust_assert (ok); + + PathProbeCandidate candidate{&alias, ty}; + candidates.push_back (std::move (candidate)); + } + } + void visit (HIR::ConstantItem &constant) override { Identifier name = constant.get_identifier (); @@ -122,6 +137,11 @@ public: query.as_string ().c_str ()); } + void visit (HIR::TypeAlias &alias) override + { + r.add_range (alias.get_locus ()); + } + void visit (HIR::ConstantItem &constant) override { r.add_range (constant.get_locus ()); diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h b/gcc/rust/typecheck/rust-hir-trait-resolve.h index 6d926f7..1b83be3 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.h +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h @@ -44,8 +44,9 @@ public: void visit (HIR::TraitItemType &type) override { - // associated types are not typed and only support bounds - TyTy::BaseType *ty = nullptr; + TyTy::BaseType *ty + = new TyTy::PlaceholderType (type.get_mappings ().get_hirid ()); + context->insert_type (type.get_mappings (), ty); // create trait-item-ref Location locus = type.get_locus (); diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 327a9a0..dd10d42 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -275,7 +275,7 @@ public: // always be at the end of the list auto s = fn->get_self_type (); - rust_assert (s->can_eq (adt)); + rust_assert (s->can_eq (adt, false)); rust_assert (s->get_kind () == TyTy::TypeKind::ADT); TyTy::ADTType *self_adt = static_cast<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 d161586..b0264e5 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -41,6 +41,14 @@ public: item->accept_vis (resolver); } + void visit (HIR::TypeAlias &alias) override + { + TyTy::BaseType *actual_type + = TypeCheckType::Resolve (alias.get_type_aliased ().get ()); + + context->insert_type (alias.get_mappings (), actual_type); + } + void visit (HIR::ConstantItem &constant) override { TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ()); @@ -204,9 +212,85 @@ public: return resolver.resolved_trait_item; } - void visit (HIR::ConstantItem &constant) override { gcc_unreachable (); } + void visit (HIR::ConstantItem &constant) override + { + TypeCheckImplItem::visit (constant); + + // we get the error checking from the base method here + TyTy::BaseType *lookup; + if (!context->lookup_type (constant.get_mappings ().get_hirid (), &lookup)) + return; + + const TraitItemReference &trait_item_ref + = trait_reference.lookup_trait_item ( + constant.get_identifier (), TraitItemReference::TraitItemType::CONST); - void visit (HIR::TypeAlias &type) override { gcc_unreachable (); } + // unknown trait item + if (trait_item_ref.is_error ()) + { + RichLocation r (constant.get_locus ()); + r.add_range (trait_reference.get_locus ()); + rust_error_at (r, "constant %<%s%> is not a member of trait %<%s%>", + constant.get_identifier ().c_str (), + trait_reference.get_name ().c_str ()); + return; + } + + // check the types are compatible + if (!trait_item_ref.get_tyty ()->can_eq (lookup, true)) + { + RichLocation r (constant.get_locus ()); + r.add_range (trait_item_ref.get_locus ()); + + rust_error_at ( + r, "constant %<%s%> has an incompatible type for trait %<%s%>", + constant.get_identifier ().c_str (), + trait_reference.get_name ().c_str ()); + return; + } + + resolved_trait_item = trait_item_ref; + } + + void visit (HIR::TypeAlias &type) override + { + TypeCheckImplItem::visit (type); + + // we get the error checking from the base method here + TyTy::BaseType *lookup; + if (!context->lookup_type (type.get_mappings ().get_hirid (), &lookup)) + return; + + const TraitItemReference &trait_item_ref + = trait_reference.lookup_trait_item ( + type.get_new_type_name (), TraitItemReference::TraitItemType::TYPE); + + // unknown trait item + if (trait_item_ref.is_error ()) + { + RichLocation r (type.get_locus ()); + r.add_range (trait_reference.get_locus ()); + rust_error_at (r, "type alias %<%s%> is not a member of trait %<%s%>", + type.get_new_type_name ().c_str (), + trait_reference.get_name ().c_str ()); + return; + } + + // check the types are compatible + if (!trait_item_ref.get_tyty ()->can_eq (lookup, true)) + { + RichLocation r (type.get_locus ()); + r.add_range (trait_item_ref.get_locus ()); + + rust_error_at ( + r, "type alias %<%s%> has an incompatible type for trait %<%s%>", + type.get_new_type_name ().c_str (), + trait_reference.get_name ().c_str ()); + return; + } + + resolved_trait_item = trait_item_ref; + } void visit (HIR::Function &function) override { @@ -263,7 +347,7 @@ public: = trait_item_fntype->handle_substitions (implicit_self_substs); // check the types are compatible - if (!trait_item_fntype->can_eq (fntype)) + if (!trait_item_fntype->can_eq (fntype, true)) { RichLocation r (function.get_locus ()); r.add_range (trait_item_ref.get_locus ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index 6081ec5..e9a3bde 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -1,3 +1,4 @@ + // Copyright (C) 2020 Free Software Foundation, Inc. // This file is part of GCC. @@ -22,6 +23,7 @@ #include "rust-hir-type-check-base.h" #include "rust-hir-full.h" #include "rust-substitution-mapper.h" +#include "rust-hir-path-probe.h" namespace Rust { namespace Resolver { @@ -145,7 +147,7 @@ public: TyTy::BaseType *path_type = lookup->clone (); path_type->set_ref (path.get_mappings ().get_hirid ()); - HIR::TypePathSegment *final_seg = path.get_final_segment (); + HIR::TypePathSegment *final_seg = path.get_final_segment ().get (); HIR::GenericArgs args = TypeCheckResolveGenericArguments::resolve (final_seg); diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h index 739f1b5..9741dfa 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.h +++ b/gcc/rust/typecheck/rust-substitution-mapper.h @@ -106,6 +106,7 @@ public: void visit (TyTy::ParamType &) override { gcc_unreachable (); } void visit (TyTy::StrType &) override { gcc_unreachable (); } void visit (TyTy::NeverType &) override { gcc_unreachable (); } + void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); } private: SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus) @@ -183,6 +184,7 @@ public: void visit (TyTy::CharType &) override { gcc_unreachable (); } void visit (TyTy::StrType &) override { gcc_unreachable (); } void visit (TyTy::NeverType &) override { gcc_unreachable (); } + void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); } private: SubstMapperInternal (HirId ref, TyTy::SubstitutionArgumentMappings &mappings) @@ -238,6 +240,7 @@ public: void visit (TyTy::ParamType &) override { gcc_unreachable (); } void visit (TyTy::StrType &) override { gcc_unreachable (); } void visit (TyTy::NeverType &) override { gcc_unreachable (); } + void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); } private: SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver) @@ -286,6 +289,7 @@ public: void visit (TyTy::ParamType &) override { gcc_unreachable (); } void visit (TyTy::StrType &) override { gcc_unreachable (); } void visit (TyTy::NeverType &) override { gcc_unreachable (); } + void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); } private: GetUsedSubstArgs () : args (TyTy::SubstitutionArgumentMappings::error ()) {} diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h index 2aba298..f6121ca 100644 --- a/gcc/rust/typecheck/rust-tyty-call.h +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -54,6 +54,7 @@ public: void visit (ParamType &) override { gcc_unreachable (); } void visit (StrType &) override { gcc_unreachable (); } void visit (NeverType &) override { gcc_unreachable (); } + void visit (PlaceholderType &) override { gcc_unreachable (); } // tuple-structs void visit (ADTType &type) override; @@ -102,6 +103,7 @@ public: void visit (ParamType &) override { gcc_unreachable (); } void visit (StrType &) override { gcc_unreachable (); } void visit (NeverType &) override { gcc_unreachable (); } + void visit (PlaceholderType &) override { gcc_unreachable (); } // FIXME void visit (FnPtr &type) override { gcc_unreachable (); } diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h index c3a9742..f01ef3b 100644 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ b/gcc/rust/typecheck/rust-tyty-cmp.h @@ -46,56 +46,303 @@ public: return ok; } - virtual void visit (TupleType &) override { ok = false; } + virtual void visit (TupleType &type) override + { + 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 (ADTType &) override { ok = false; } + virtual void visit (ADTType &type) override + { + 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 (InferType &) override { ok = false; } + virtual void visit (InferType &type) override + { + 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 (FnType &type) override + { + 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 (FnType &) override { ok = false; } + virtual void visit (FnPtr &type) override + { + 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 (FnPtr &) override { ok = false; } + virtual void visit (ArrayType &type) override + { + 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 (ArrayType &) override { ok = false; } + virtual void visit (BoolType &type) override + { + 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 (BoolType &) override { ok = false; } + virtual void visit (IntType &type) override + { + 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 (IntType &) override { ok = false; } + virtual void visit (UintType &type) override + { + 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 (UintType &) override { ok = false; } + virtual void visit (USizeType &type) override + { + 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 (USizeType &) override { ok = false; } + virtual void visit (ISizeType &type) override + { + 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 (ISizeType &) override { ok = false; } + virtual void visit (FloatType &type) override + { + 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 (FloatType &) override { ok = false; } + virtual void visit (ErrorType &type) override + { + 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 (ErrorType &) override { ok = false; } + virtual void visit (CharType &type) override + { + 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 (CharType &) override { ok = false; } + virtual void visit (ReferenceType &type) override + { + 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 (ReferenceType &) override { ok = false; } + virtual void visit (StrType &type) override + { + 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 (ParamType &) override + virtual void visit (NeverType &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 (StrType &) override { ok = false; } + virtual void visit (PlaceholderType &type) override + { + // it is ok for types to can eq to a placeholder + ok = true; + } - virtual void visit (NeverType &) override { ok = false; } + virtual void visit (ParamType &type) override + { + // it is ok for types to can eq to a ParamType + ok = true; + } protected: - BaseCmp (BaseType *base) + BaseCmp (BaseType *base, bool emit_errors) : mappings (Analysis::Mappings::get ()), - context (Resolver::TypeCheckContext::get ()), ok (false) + context (Resolver::TypeCheckContext::get ()), ok (false), + emit_error_flag (emit_errors) {} Analysis::Mappings *mappings; Resolver::TypeCheckContext *context; bool ok; + bool emit_error_flag; private: /* Returns a pointer to the ty that created this rule. */ @@ -107,7 +354,9 @@ class InferCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - InferCmp (InferType *base) : BaseCmp (base), base (base) {} + InferCmp (InferType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} void visit (BoolType &type) override { @@ -328,7 +577,9 @@ class FnCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - FnCmp (FnType *base) : BaseCmp (base), base (base) {} + FnCmp (FnType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} void visit (InferType &type) override { @@ -348,18 +599,18 @@ public: auto a = base->param_at (i).second; auto b = type.param_at (i).second; - auto unified_param = a->unify (b); - if (unified_param->get_kind () == TypeKind::ERROR) + if (!a->can_eq (b, emit_error_flag)) { + emit_error_flag = false; BaseCmp::visit (type); return; } } - auto unified_return - = base->get_return_type ()->unify (type.get_return_type ()); - if (unified_return->get_kind () == TypeKind::ERROR) + if (!base->get_return_type ()->can_eq (type.get_return_type (), + emit_error_flag)) { + emit_error_flag = false; BaseCmp::visit (type); return; } @@ -378,7 +629,9 @@ class FnptrCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - FnptrCmp (FnPtr *base) : BaseCmp (base), base (base) {} + FnptrCmp (FnPtr *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} void visit (InferType &type) override { @@ -393,17 +646,15 @@ public: void visit (FnPtr &type) override { - auto this_ret_type = base->get_return_type (); - auto other_ret_type = type.get_return_type (); - auto unified_result = this_ret_type->unify (other_ret_type); - if (unified_result == nullptr - || unified_result->get_kind () == TypeKind::ERROR) + if (base->num_params () != type.num_params ()) { BaseCmp::visit (type); return; } - if (base->num_params () != type.num_params ()) + 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)) { BaseCmp::visit (type); return; @@ -413,9 +664,7 @@ public: { auto this_param = base->param_at (i); auto other_param = type.param_at (i); - auto unified_param = this_param->unify (other_param); - if (unified_param == nullptr - || unified_param->get_kind () == TypeKind::ERROR) + if (!this_param->can_eq (other_param, emit_error_flag)) { BaseCmp::visit (type); return; @@ -427,17 +676,15 @@ public: void visit (FnType &type) override { - auto this_ret_type = base->get_return_type (); - auto other_ret_type = type.get_return_type (); - auto unified_result = this_ret_type->unify (other_ret_type); - if (unified_result == nullptr - || unified_result->get_kind () == TypeKind::ERROR) + if (base->num_params () != type.num_params ()) { BaseCmp::visit (type); return; } - if (base->num_params () != type.num_params ()) + 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)) { BaseCmp::visit (type); return; @@ -447,9 +694,7 @@ public: { auto this_param = base->param_at (i); auto other_param = type.param_at (i).second; - auto unified_param = this_param->unify (other_param); - if (unified_param == nullptr - || unified_param->get_kind () == TypeKind::ERROR) + if (!this_param->can_eq (other_param, emit_error_flag)) { BaseCmp::visit (type); return; @@ -470,7 +715,9 @@ class ArrayCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - ArrayCmp (ArrayType *base) : BaseCmp (base), base (base) {} + ArrayCmp (ArrayType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} void visit (ArrayType &type) override { @@ -506,7 +753,9 @@ class BoolCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - BoolCmp (BoolType *base) : BaseCmp (base), base (base) {} + BoolCmp (BoolType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} void visit (BoolType &type) override { ok = true; } @@ -526,7 +775,9 @@ class IntCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - IntCmp (IntType *base) : BaseCmp (base), base (base) {} + IntCmp (IntType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} void visit (InferType &type) override { @@ -549,7 +800,9 @@ class UintCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - UintCmp (UintType *base) : BaseCmp (base), base (base) {} + UintCmp (UintType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} void visit (InferType &type) override { @@ -572,7 +825,9 @@ class FloatCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - FloatCmp (FloatType *base) : BaseCmp (base), base (base) {} + FloatCmp (FloatType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} void visit (InferType &type) override { @@ -595,7 +850,9 @@ class ADTCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - ADTCmp (ADTType *base) : BaseCmp (base), base (base) {} + ADTCmp (ADTType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} void visit (ADTType &type) override { @@ -619,7 +876,7 @@ 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)) + if (!this_field_ty->can_eq (other_field_ty, emit_error_flag)) { BaseCmp::visit (type); return; @@ -640,7 +897,9 @@ class TupleCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - TupleCmp (TupleType *base) : BaseCmp (base), base (base) {} + TupleCmp (TupleType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} void visit (TupleType &type) override { @@ -655,7 +914,7 @@ public: BaseType *bo = base->get_field (i); BaseType *fo = type.get_field (i); - if (!bo->can_eq (fo)) + if (!bo->can_eq (fo, emit_error_flag)) { BaseCmp::visit (type); return; @@ -676,7 +935,9 @@ class USizeCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - USizeCmp (USizeType *base) : BaseCmp (base), base (base) {} + USizeCmp (USizeType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} void visit (InferType &type) override { @@ -696,7 +957,9 @@ class ISizeCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - ISizeCmp (ISizeType *base) : BaseCmp (base), base (base) {} + ISizeCmp (ISizeType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} void visit (InferType &type) override { @@ -716,7 +979,9 @@ class CharCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - CharCmp (CharType *base) : BaseCmp (base), base (base) {} + CharCmp (CharType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} void visit (InferType &type) override { @@ -736,14 +1001,16 @@ class ReferenceCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - ReferenceCmp (ReferenceType *base) : BaseCmp (base), base (base) {} + ReferenceCmp (ReferenceType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} void visit (ReferenceType &type) override { auto base_type = base->get_base (); auto other_base_type = type.get_base (); - ok = base_type->can_eq (other_base_type); + ok = base_type->can_eq (other_base_type, emit_error_flag); } private: @@ -757,7 +1024,9 @@ class ParamCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - ParamCmp (ParamType *base) : BaseCmp (base), base (base) {} + ParamCmp (ParamType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} // param types are a placeholder we shouldn't have cases where we unify // against it. eg: struct foo<T> { a: T }; When we invoke it we can do either: @@ -781,10 +1050,10 @@ public: if (lookup->get_kind () == TypeKind::PARAM) { InferType infer (UNKNOWN_HIRID, InferType::InferTypeKind::GENERAL); - return infer.can_eq (other); + return infer.can_eq (other, emit_error_flag); } - return lookup->can_eq (other); + return lookup->can_eq (other, emit_error_flag); } // imagine the case where we have: @@ -807,7 +1076,9 @@ class StrCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - StrCmp (StrType *base) : BaseCmp (base), base (base) {} + StrCmp (StrType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} void visit (StrType &type) override { ok = true; } @@ -822,7 +1093,9 @@ class NeverCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - NeverCmp (NeverType *base) : BaseCmp (base), base (base) {} + NeverCmp (NeverType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} void visit (NeverType &type) override { ok = true; } @@ -832,6 +1105,59 @@ private: NeverType *base; }; +class PlaceholderCmp : public BaseCmp +{ + using Rust::TyTy::BaseCmp::visit; + +public: + PlaceholderCmp (PlaceholderType *base, bool emit_errors) + : BaseCmp (base, emit_errors), base (base) + {} + + virtual void visit (TupleType &) override { ok = true; } + + virtual void visit (ADTType &) override { ok = true; } + + virtual void visit (InferType &) override { ok = true; } + + virtual void visit (FnType &) override { ok = true; } + + virtual void visit (FnPtr &) override { ok = true; } + + virtual void visit (ArrayType &) override { ok = true; } + + virtual void visit (BoolType &) override { ok = true; } + + virtual void visit (IntType &) override { ok = true; } + + virtual void visit (UintType &) override { ok = true; } + + virtual void visit (USizeType &) override { ok = true; } + + virtual void visit (ISizeType &) override { ok = true; } + + virtual void visit (FloatType &) override { ok = true; } + + virtual void visit (ErrorType &) override { ok = true; } + + virtual void visit (CharType &) override { ok = true; } + + virtual void visit (ReferenceType &) override { ok = true; } + + virtual void visit (ParamType &) override { ok = true; } + + virtual void visit (StrType &) override { ok = true; } + + virtual void visit (NeverType &) override { ok = true; } + + virtual void visit (PlaceholderType &) override { ok = true; } + +private: + BaseType *get_base () override { return base; } + + PlaceholderType *base; +}; + } // namespace TyTy } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 06bb33f..5db005b 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -299,7 +299,21 @@ public: virtual void visit (NeverType &type) override { Location ref_locus = mappings->lookup_location (type.get_ref ()); - rust_error_at (ref_locus, "expected [%s] got [%s]", + 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 (PlaceholderType &type) override + { + 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 ()); } @@ -1165,6 +1179,19 @@ private: NeverType *base; }; +class PlaceholderRules : public BaseRules +{ + using Rust::TyTy::BaseRules::visit; + +public: + PlaceholderRules (PlaceholderType *base) : BaseRules (base), base (base) {} + +private: + BaseType *get_base () override { return base; } + + PlaceholderType *base; +}; + } // namespace TyTy } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h index 0ed7eef..2bac5fe 100644 --- a/gcc/rust/typecheck/rust-tyty-visitor.h +++ b/gcc/rust/typecheck/rust-tyty-visitor.h @@ -45,6 +45,7 @@ public: virtual void visit (ParamType &type) = 0; virtual void visit (StrType &type) = 0; virtual void visit (NeverType &type) = 0; + virtual void visit (PlaceholderType &type) = 0; }; } // namespace TyTy diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index dd2472c..ba98212 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -98,9 +98,9 @@ InferType::unify (BaseType *other) } bool -InferType::can_eq (BaseType *other) +InferType::can_eq (BaseType *other, bool emit_errors) { - InferCmp r (this); + InferCmp r (this, emit_errors); return r.can_eq (other); } @@ -155,7 +155,7 @@ ErrorType::unify (BaseType *other) } bool -ErrorType::can_eq (BaseType *other) +ErrorType::can_eq (BaseType *other, bool emit_errors) { return get_kind () == other->get_kind (); } @@ -421,9 +421,9 @@ ADTType::unify (BaseType *other) } bool -ADTType::can_eq (BaseType *other) +ADTType::can_eq (BaseType *other, bool emit_errors) { - ADTCmp r (this); + ADTCmp r (this, emit_errors); return r.can_eq (other); } @@ -582,9 +582,9 @@ TupleType::unify (BaseType *other) } bool -TupleType::can_eq (BaseType *other) +TupleType::can_eq (BaseType *other, bool emit_errors) { - TupleCmp r (this); + TupleCmp r (this, emit_errors); return r.can_eq (other); } @@ -666,9 +666,9 @@ FnType::unify (BaseType *other) } bool -FnType::can_eq (BaseType *other) +FnType::can_eq (BaseType *other, bool emit_errors) { - FnCmp r (this); + FnCmp r (this, emit_errors); return r.can_eq (other); } @@ -861,9 +861,9 @@ FnPtr::unify (BaseType *other) } bool -FnPtr::can_eq (BaseType *other) +FnPtr::can_eq (BaseType *other, bool emit_errors) { - FnptrCmp r (this); + FnptrCmp r (this, emit_errors); return r.can_eq (other); } @@ -928,9 +928,9 @@ ArrayType::unify (BaseType *other) } bool -ArrayType::can_eq (BaseType *other) +ArrayType::can_eq (BaseType *other, bool emit_errors) { - ArrayCmp r (this); + ArrayCmp r (this, emit_errors); return r.can_eq (other); } @@ -983,9 +983,9 @@ BoolType::unify (BaseType *other) } bool -BoolType::can_eq (BaseType *other) +BoolType::can_eq (BaseType *other, bool emit_errors) { - BoolCmp r (this); + BoolCmp r (this, emit_errors); return r.can_eq (other); } @@ -1029,9 +1029,9 @@ IntType::unify (BaseType *other) } bool -IntType::can_eq (BaseType *other) +IntType::can_eq (BaseType *other, bool emit_errors) { - IntCmp r (this); + IntCmp r (this, emit_errors); return r.can_eq (other); } @@ -1086,9 +1086,9 @@ UintType::unify (BaseType *other) } bool -UintType::can_eq (BaseType *other) +UintType::can_eq (BaseType *other, bool emit_errors) { - UintCmp r (this); + UintCmp r (this, emit_errors); return r.can_eq (other); } @@ -1137,9 +1137,9 @@ FloatType::unify (BaseType *other) } bool -FloatType::can_eq (BaseType *other) +FloatType::can_eq (BaseType *other, bool emit_errors) { - FloatCmp r (this); + FloatCmp r (this, emit_errors); return r.can_eq (other); } @@ -1180,9 +1180,9 @@ USizeType::unify (BaseType *other) } bool -USizeType::can_eq (BaseType *other) +USizeType::can_eq (BaseType *other, bool emit_errors) { - USizeCmp r (this); + USizeCmp r (this, emit_errors); return r.can_eq (other); } @@ -1212,9 +1212,9 @@ ISizeType::unify (BaseType *other) } bool -ISizeType::can_eq (BaseType *other) +ISizeType::can_eq (BaseType *other, bool emit_errors) { - ISizeCmp r (this); + ISizeCmp r (this, emit_errors); return r.can_eq (other); } @@ -1244,9 +1244,9 @@ CharType::unify (BaseType *other) } bool -CharType::can_eq (BaseType *other) +CharType::can_eq (BaseType *other, bool emit_errors) { - CharCmp r (this); + CharCmp r (this, emit_errors); return r.can_eq (other); } @@ -1276,9 +1276,9 @@ ReferenceType::unify (BaseType *other) } bool -ReferenceType::can_eq (BaseType *other) +ReferenceType::can_eq (BaseType *other, bool emit_errors) { - ReferenceCmp r (this); + ReferenceCmp r (this, emit_errors); return r.can_eq (other); } @@ -1351,9 +1351,9 @@ ParamType::unify (BaseType *other) } bool -ParamType::can_eq (BaseType *other) +ParamType::can_eq (BaseType *other, bool emit_errors) { - ParamCmp r (this); + ParamCmp r (this, emit_errors); return r.can_eq (other); } @@ -1407,7 +1407,7 @@ ParamType::is_equal (const BaseType &other) const return false; if (can_resolve ()) - return resolve ()->can_eq (other2.resolve ()); + return resolve ()->can_eq (other2.resolve (), false); return get_symbol ().compare (other2.get_symbol ()) == 0; } @@ -1451,9 +1451,9 @@ StrType::unify (BaseType *other) } bool -StrType::can_eq (BaseType *other) +StrType::can_eq (BaseType *other, bool emit_errors) { - StrCmp r (this); + StrCmp r (this, emit_errors); return r.can_eq (other); } @@ -1483,9 +1483,9 @@ NeverType::unify (BaseType *other) } bool -NeverType::can_eq (BaseType *other) +NeverType::can_eq (BaseType *other, bool emit_errors) { - NeverCmp r (this); + NeverCmp r (this, emit_errors); return r.can_eq (other); } @@ -1495,6 +1495,38 @@ NeverType::clone () return new NeverType (get_ref (), get_ty_ref (), get_combined_refs ()); } +void +PlaceholderType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +PlaceholderType::as_string () const +{ + return "<placeholder>"; +} + +BaseType * +PlaceholderType::unify (BaseType *other) +{ + PlaceholderRules r (this); + return r.unify (other); +} + +bool +PlaceholderType::can_eq (BaseType *other, bool emit_errors) +{ + PlaceholderCmp r (this, emit_errors); + return r.can_eq (other); +} + +BaseType * +PlaceholderType::clone () +{ + return new PlaceholderType (get_ref (), get_ty_ref (), get_combined_refs ()); +} + // rust-tyty-call.h void diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 438c52b..d85b8a8 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -48,6 +48,7 @@ enum TypeKind USIZE, ISIZE, NEVER, + PLACEHOLDER, // there are more to add... ERROR }; @@ -110,6 +111,9 @@ public: case TypeKind::NEVER: return "Never"; + case TypeKind::PLACEHOLDER: + return "Placeholder"; + case TypeKind::ERROR: return "ERROR"; } @@ -151,7 +155,7 @@ public: // similar to unify but does not actually perform type unification but // determines whether they are compatible - virtual bool can_eq (BaseType *other) = 0; + virtual bool can_eq (BaseType *other, bool emit_errors) = 0; // Check value equality between two ty. Type inference rules are ignored. Two // ty are considered equal if they're of the same kind, and @@ -270,7 +274,7 @@ public: BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; BaseType *clone () final override; @@ -304,7 +308,7 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; BaseType *clone () final override; @@ -332,7 +336,7 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; BaseType *clone () final override; @@ -417,7 +421,7 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; bool is_equal (const BaseType &other) const override; @@ -849,7 +853,7 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; bool is_equal (const BaseType &other) const override; @@ -956,7 +960,7 @@ public: std::string get_identifier () const { return identifier; } BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; bool is_equal (const BaseType &other) const override; @@ -1052,7 +1056,7 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; bool is_equal (const BaseType &other) const override; @@ -1094,7 +1098,7 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; bool is_equal (const BaseType &other) const override; @@ -1133,7 +1137,7 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; BaseType *clone () final override; }; @@ -1166,7 +1170,7 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; IntKind get_int_kind () const { return int_kind; } @@ -1206,7 +1210,7 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; UintKind get_uint_kind () const { return uint_kind; } @@ -1244,7 +1248,7 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; FloatKind get_float_kind () const { return float_kind; } @@ -1284,7 +1288,7 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; BaseType *clone () final override; }; @@ -1317,7 +1321,7 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; BaseType *clone () final override; }; @@ -1350,7 +1354,7 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; BaseType *clone () final override; }; @@ -1387,7 +1391,7 @@ public: std::string get_name () const override final { return as_string (); } BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; bool is_equal (const BaseType &other) const override; @@ -1432,7 +1436,7 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; bool is_equal (const BaseType &other) const override; @@ -1465,7 +1469,35 @@ public: std::string as_string () const override; BaseType *unify (BaseType *other) override; - bool can_eq (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; + + BaseType *clone () final override; + + std::string get_name () const override final { return as_string (); } + + bool is_unit () const override { return true; } +}; + +// used at the type in associated types in traits +// see: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +class PlaceholderType : public BaseType +{ +public: + PlaceholderType (HirId ref, std::set<HirId> refs = std::set<HirId> ()) + : BaseType (ref, ref, TypeKind::PLACEHOLDER, refs) + {} + + PlaceholderType (HirId ref, HirId ty_ref, + std::set<HirId> refs = std::set<HirId> ()) + : BaseType (ref, ty_ref, TypeKind::PLACEHOLDER, refs) + {} + + void accept_vis (TyVisitor &vis) override; + + std::string as_string () const override; + + BaseType *unify (BaseType *other) override; + bool can_eq (BaseType *other, bool emit_errors) override; BaseType *clone () final override; diff --git a/gcc/testsuite/rust/compile/torture/traits3.rs b/gcc/testsuite/rust/compile/torture/traits3.rs index 621fcde..2ab74e1 100644 --- a/gcc/testsuite/rust/compile/torture/traits3.rs +++ b/gcc/testsuite/rust/compile/torture/traits3.rs @@ -1,7 +1,7 @@ pub trait Foo { fn Bar(self) -> i32; // { dg-warning "unused name .self." "" { target *-*-* } .-1 } - // { dg-warning "unused name .Bar." "" { target *-*-* } .-2 } + // { dg-warning "unused name .Foo::Bar." "" { target *-*-* } .-2 } } struct Baz; diff --git a/gcc/testsuite/rust/compile/torture/traits4.rs b/gcc/testsuite/rust/compile/torture/traits4.rs new file mode 100644 index 0000000..1db5f32 --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/traits4.rs @@ -0,0 +1,26 @@ +trait Foo { + type A; + // { dg-warning "unused name" "" { target *-*-* } .-1 } + type B; + // { dg-warning "unused name" "" { target *-*-* } .-1 } + + fn new(a: Self::A, b: Self::B) -> Self; + // { dg-warning "unused name .a." "" { target *-*-* } .-1 } + // { dg-warning "unused name .b." "" { target *-*-* } .-2 } + // { dg-warning "unused name .Foo::new." "" { target *-*-* } .-3 } +} + +struct Baz(i32, f32); + +impl Foo for Baz { + type A = i32; + type B = f32; + + fn new(a: Self::A, b: Self::B) -> Self { + Baz(a, b) + } +} + +fn main() { + Baz::new(123, 456f32); +} diff --git a/gcc/testsuite/rust/compile/torture/traits5.rs b/gcc/testsuite/rust/compile/torture/traits5.rs new file mode 100644 index 0000000..87c0283 --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/traits5.rs @@ -0,0 +1,26 @@ +trait Foo { + type A; + // { dg-warning "unused name" "" { target *-*-* } .-1 } + type B; + // { dg-warning "unused name" "" { target *-*-* } .-1 } + + fn new(a: Self::A, b: Self::B) -> Self; + // { dg-warning "unused name .a." "" { target *-*-* } .-1 } + // { dg-warning "unused name .b." "" { target *-*-* } .-2 } + // { dg-warning "unused name .Foo::new." "" { target *-*-* } .-3 } +} + +struct Baz(i32, f32); + +impl Foo for Baz { + type A = i32; + type B = f32; + + fn new(a: i32, b: f32) -> Self { + Baz(a, b) + } +} + +fn main() { + Baz::new(123, 456f32); +} |