From 30ca36242090e5b1dcb8094a7a11574949f36d1a Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 5 Jul 2021 16:35:50 +0100 Subject: Assert that impl items are non null when translated to hir When we translate AST::InherentImplItems or AST::TraitImplItem's these get lowered into a generic ImplBlock with ImplItems these must be non null. TraitImpl blocks can contains associated types but normal InherentImpl's do not this unifies the path to turn both into an HIR::ImplBlock --- gcc/rust/hir/rust-ast-lower-item.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'gcc') 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 (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 (lowered)); impl_item_ids.push_back (lowered->get_impl_mappings ().get_hirid ()); } -- cgit v1.1 From c5ce98cbb8db8d33774c50e229daedf99a71bb5a Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 5 Jul 2021 16:36:08 +0100 Subject: ImplBlocks can contain TypeAlias's This lowers TypeAliases into ImplItem for HIR::ImplBlocks. --- gcc/rust/hir/rust-ast-lower-implitem.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'gcc') 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 > where_clause_items; + HIR::WhereClause where_clause (std::move (where_clause_items)); + HIR::Visibility vis = HIR::Visibility::create_public (); + + std::vector > 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 (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 (); -- cgit v1.1 From bb51a9de35e35ac4e411a323c1fde806fb54d142 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 5 Jul 2021 16:36:54 +0100 Subject: Add toplevel resolution for type alias TypeAliases can be contained within ImplBlocks and need their full canonical path to be resolved. --- gcc/rust/resolve/rust-ast-resolve-implitem.h | 15 +++++++++++++++ gcc/rust/resolve/rust-ast-resolve-item.h | 18 +++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/resolve/rust-ast-resolve-implitem.h b/gcc/rust/resolve/rust-ast-resolve-implitem.h index 576cd3e..9b71dad 100644 --- a/gcc/rust/resolve/rust-ast-resolve-implitem.h +++ b/gcc/rust/resolve/rust-ast-resolve-implitem.h @@ -43,6 +43,21 @@ public: item->accept_vis (resolver); } + void visit (AST::TypeAlias &type) override + { + auto path = prefix.append (CanonicalPath (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..09d6430 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -433,10 +433,22 @@ public: resolver->get_label_scope ().pop (); } - // TODO - void visit (AST::TraitItemConst &) override { gcc_unreachable (); } + 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 ()); + } - void visit (AST::TraitItemType &) override { gcc_unreachable (); } + void visit (AST::TraitItemType &alias) override + { + // nothing to do here until we start supporting Type Bounds + } private: ResolveItem () : ResolverBase (UNKNOWN_NODEID) {} -- cgit v1.1 From 91aa2cba1ca4b481a9b3fed77054258a3fdc442d Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 5 Jul 2021 17:25:24 +0100 Subject: Refactor CanonicalPath so we can iterate the segments This adds the associated NodeId into each CanonicalPath segment which references their respective TypePathSegment or PathExprSegment. --- gcc/rust/resolve/rust-ast-resolve-expr.h | 20 +++++---- gcc/rust/resolve/rust-ast-resolve-implitem.h | 3 +- gcc/rust/resolve/rust-ast-resolve-pattern.h | 5 ++- gcc/rust/resolve/rust-ast-resolve-stmt.h | 4 +- gcc/rust/resolve/rust-ast-resolve-toplevel.h | 13 +++--- gcc/rust/resolve/rust-ast-resolve-type.h | 26 ++++++----- gcc/rust/resolve/rust-ast-resolve.cc | 12 ++--- gcc/rust/resolve/rust-ast-verify-assignee.h | 4 +- gcc/rust/resolve/rust-name-resolver.h | 67 ++++++++++++++++++++++------ 9 files changed, 102 insertions(+), 52 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index bbd8818..d6f5fcd 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -117,8 +117,8 @@ 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.as_string ()), &resolved_node)) { resolver->insert_resolved_name (expr.get_node_id (), resolved_node); resolver->insert_new_definition (expr.get_node_id (), @@ -126,7 +126,7 @@ public: parent}); } else if (resolver->get_type_scope ().lookup ( - CanonicalPath (expr.as_string ()), &resolved_node)) + CanonicalPath::new_seg (expr.as_string ()), &resolved_node)) { resolver->insert_resolved_type (expr.get_node_id (), resolved_node); resolver->insert_new_definition (expr.get_node_id (), @@ -272,7 +272,7 @@ 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, + CanonicalPath::new_seg (label_name), label_lifetime_node_id, label.get_locus (), false, [&] (const CanonicalPath &, NodeId, Location locus) -> void { rust_error_at (label.get_locus (), @@ -299,8 +299,9 @@ public: } NodeId resolved_node = UNKNOWN_NODEID; - if (!resolver->get_label_scope ().lookup ( - CanonicalPath (label.get_lifetime_name ()), &resolved_node)) + if (!resolver->get_label_scope ().lookup (CanonicalPath::new_seg ( + label.get_lifetime_name ()), + &resolved_node)) { rust_error_at (expr.get_label ().get_locus (), "failed to resolve label"); @@ -329,7 +330,7 @@ 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, + CanonicalPath::new_seg (label_name), label_lifetime_node_id, label.get_locus (), false, [&] (const CanonicalPath &, NodeId, Location locus) -> void { rust_error_at (label.get_locus (), @@ -357,8 +358,9 @@ public: } NodeId resolved_node = UNKNOWN_NODEID; - if (!resolver->get_label_scope ().lookup ( - CanonicalPath (label.get_lifetime_name ()), &resolved_node)) + if (!resolver->get_label_scope ().lookup (CanonicalPath::new_seg ( + 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 9b71dad..b622dcb 100644 --- a/gcc/rust/resolve/rust-ast-resolve-implitem.h +++ b/gcc/rust/resolve/rust-ast-resolve-implitem.h @@ -45,7 +45,8 @@ public: void visit (AST::TypeAlias &type) override { - auto path = prefix.append (CanonicalPath (type.get_new_type_name ())); + auto path + = prefix.append (CanonicalPath::new_seg (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 { diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h index 0734908..b2d059e 100644 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.h +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h @@ -44,7 +44,7 @@ public: void visit (AST::IdentifierPattern &pattern) override { if (resolver->get_name_scope ().lookup ( - CanonicalPath (pattern.get_ident ()), &resolved_node)) + CanonicalPath::new_seg (pattern.get_ident ()), &resolved_node)) { resolver->insert_resolved_name (pattern.get_node_id (), resolved_node); resolver->insert_new_definition (pattern.get_node_id (), @@ -72,7 +72,8 @@ 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 ()), + resolver->get_name_scope ().insert (CanonicalPath::new_seg ( + pattern.get_ident ()), pattern.get_node_id (), pattern.get_locus ()); resolver->insert_new_definition (pattern.get_node_id (), diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h index e68e7b9..b0cdeb2 100644 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -67,7 +67,7 @@ public: void visit (AST::TupleStruct &struct_decl) override { - auto path = CanonicalPath (struct_decl.get_identifier ()); + auto path = CanonicalPath::new_seg (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 +99,7 @@ public: void visit (AST::StructStruct &struct_decl) override { - auto path = CanonicalPath (struct_decl.get_identifier ()); + auto path = CanonicalPath::new_seg (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..44f5b22 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -41,7 +41,8 @@ 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_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 +54,8 @@ 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_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 +67,8 @@ 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_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 +80,7 @@ public: void visit (AST::StaticItem &var) override { - auto path = prefix.append (CanonicalPath (var.get_identifier ())); + auto path = prefix.append (CanonicalPath::new_seg (var.get_identifier ())); resolver->get_name_scope ().insert ( path, var.get_node_id (), var.get_locus (), false, [&] (const CanonicalPath &, NodeId, Location locus) -> void { @@ -170,7 +173,7 @@ public: void visit (AST::Trait &trait) override { CanonicalPath path - = prefix.append (CanonicalPath (trait.get_identifier ())); + = prefix.append (CanonicalPath::new_seg (trait.get_identifier ())); resolver->get_type_scope ().insert ( path, trait.get_node_id (), trait.get_locus (), false, [&] (const CanonicalPath &, NodeId, Location locus) -> void { diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 19e7324..cf6962b 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -30,7 +30,7 @@ class ResolveConstantItemToCanonicalPath public: static CanonicalPath resolve (AST::ConstantItem &constant) { - return CanonicalPath (constant.get_identifier ()); + return CanonicalPath::new_seg (constant.get_identifier ()); } }; @@ -39,7 +39,7 @@ class ResolveFunctionItemToCanonicalPath public: static CanonicalPath resolve (AST::Function &function) { - return CanonicalPath (function.get_function_name ()); + return CanonicalPath::new_seg (function.get_function_name ()); } }; @@ -48,7 +48,7 @@ class ResolveMethodItemToCanonicalPath public: static CanonicalPath resolve (AST::Method &method) { - return CanonicalPath (method.get_method_name ()); + return CanonicalPath::new_seg (method.get_method_name ()); } }; @@ -57,7 +57,7 @@ class ResolveTraitItemFunctionToCanonicalPath public: static CanonicalPath resolve (AST::TraitItemFunc &function) { - return CanonicalPath ( + return CanonicalPath::new_seg ( function.get_trait_function_decl ().get_identifier ()); } }; @@ -67,7 +67,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_trait_method_decl ().get_identifier ()); } }; @@ -76,7 +77,7 @@ class ResolveTraitItemConstToCanonicalPath public: static CanonicalPath resolve (AST::TraitItemConst &constant) { - return CanonicalPath (constant.get_identifier ()); + return CanonicalPath::new_seg (constant.get_identifier ()); } }; @@ -85,7 +86,7 @@ class ResolveTraitItemTypeToCanonicalPath public: static CanonicalPath resolve (AST::TraitItemType &type) { - return CanonicalPath (type.get_identifier ()); + return CanonicalPath::new_seg (type.get_identifier ()); } }; @@ -142,7 +143,8 @@ class ResolvePathSegmentToCanonicalPath public: static CanonicalPath resolve (AST::PathExprSegment &seg) { - CanonicalPath path = CanonicalPath (seg.get_ident_segment ().as_string ()); + CanonicalPath path + = CanonicalPath::new_seg (seg.get_ident_segment ().as_string ()); if (seg.has_generic_args ()) { bool ok = ResolveTypeToCanonicalPath::type_resolve_generic_args ( @@ -168,8 +170,8 @@ public: static CanonicalPath resolve (const CanonicalPath &trait_seg, const CanonicalPath &impl_type_seg) { - return CanonicalPath ("<" + impl_type_seg.get () + " as " + trait_seg.get () - + ">"); + return CanonicalPath::new_seg ("<" + impl_type_seg.get () + " as " + + trait_seg.get () + ">"); } }; @@ -316,8 +318,8 @@ public: // for now lets focus on handling the basics: like struct { 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_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..d47371c 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -121,7 +121,8 @@ 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->as_string ()); r->insert_name (builtin_path, builtin->get_node_id (), Linemap::predeclared_location (), false, [] (const CanonicalPath &, NodeId, Location) -> void {}); @@ -401,7 +402,7 @@ ResolveTypeToCanonicalPath::canonicalize_generic_args (AST::GenericArgs &args) i++; } - return CanonicalPath ("<" + buf + ">"); + return CanonicalPath::new_seg ("<" + buf + ">"); } bool @@ -430,7 +431,7 @@ ResolveTypeToCanonicalPath::visit (AST::TypePathSegmentGeneric &seg) // ident seg CanonicalPath ident_seg - = CanonicalPath (seg.get_ident_segment ().as_string ()); + = CanonicalPath::new_seg (seg.get_ident_segment ().as_string ()); result = result.append (ident_seg); // generic args @@ -460,7 +461,7 @@ ResolveTypeToCanonicalPath::visit (AST::TypePathSegment &seg) } CanonicalPath ident_seg - = CanonicalPath (seg.get_ident_segment ().as_string ()); + = CanonicalPath::new_seg (seg.get_ident_segment ().as_string ()); result = result.append (ident_seg); } @@ -474,7 +475,8 @@ 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 (root_ident_seg.as_string ()); // name scope first if (resolver->get_name_scope ().lookup (root_seg_path, &resolved_node)) diff --git a/gcc/rust/resolve/rust-ast-verify-assignee.h b/gcc/rust/resolve/rust-ast-verify-assignee.h index 13b6c91..11a5414 100644 --- a/gcc/rust/resolve/rust-ast-verify-assignee.h +++ b/gcc/rust/resolve/rust-ast-verify-assignee.h @@ -57,8 +57,8 @@ 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.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..d3b22a0 100644 --- a/gcc/rust/resolve/rust-name-resolver.h +++ b/gcc/rust/resolve/rust-name-resolver.h @@ -47,34 +47,73 @@ 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 new_seg (const std::string &path) + { + rust_assert (!path.empty ()); + return CanonicalPath ({path}); + } - static CanonicalPath get_big_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); + buf += seg + (have_more ? "::" : ""); + } + return buf; + } - static CanonicalPath get_wee_self () { return CanonicalPath ("self"); } + static CanonicalPath get_big_self () + { + return CanonicalPath::new_seg ("Self"); + } - static CanonicalPath create_empty () + static CanonicalPath get_wee_self () { - return CanonicalPath (std::string ()); + return CanonicalPath::new_seg ("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 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_path (std::function cb) const + { + std::vector buf; + for (auto &seg : segs) + { + buf.push_back (seg); + if (!cb (CanonicalPath (buf))) + return; + } } bool operator== (const CanonicalPath &b) const @@ -85,9 +124,9 @@ 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 path) : segs (path) {} - std::string path; + std::vector segs; }; class Rib -- cgit v1.1 From e3390f5602149c9f918efdd9fdc63448920da916 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 7 Jul 2021 16:53:57 +0100 Subject: Introduce placeholder type This is used in Traits with associated types that can contain TypeBounds but provides an ability to reuse out type system to check that trait items are compatible with their respective ImplBlock Items --- gcc/rust/backend/rust-compile-context.h | 2 ++ gcc/rust/backend/rust-compile-tyty.h | 2 ++ gcc/rust/typecheck/rust-hir-const-fold.h | 2 ++ gcc/rust/typecheck/rust-hir-trait-resolve.h | 5 +++-- gcc/rust/typecheck/rust-substitution-mapper.h | 4 ++++ gcc/rust/typecheck/rust-tyty-call.h | 2 ++ gcc/rust/typecheck/rust-tyty-cmp.h | 18 +++++++++++++++ gcc/rust/typecheck/rust-tyty-rules.h | 29 +++++++++++++++++++++++- gcc/rust/typecheck/rust-tyty-visitor.h | 1 + gcc/rust/typecheck/rust-tyty.cc | 32 +++++++++++++++++++++++++++ gcc/rust/typecheck/rust-tyty.h | 32 +++++++++++++++++++++++++++ 11 files changed, 126 insertions(+), 3 deletions(-) (limited to 'gcc') 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/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-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-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..7595e2f 100644 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ b/gcc/rust/typecheck/rust-tyty-cmp.h @@ -86,6 +86,11 @@ public: virtual void visit (NeverType &) override { ok = false; } + virtual void visit (PlaceholderType &) override + { // it is ok for types to can eq to a placeholder + ok = true; + } + protected: BaseCmp (BaseType *base) : mappings (Analysis::Mappings::get ()), @@ -832,6 +837,19 @@ private: NeverType *base; }; +class PlaceholderCmp : public BaseCmp +{ + using Rust::TyTy::BaseCmp::visit; + +public: + PlaceholderCmp (PlaceholderType *base) : BaseCmp (base), base (base) {} + +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..503d380 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -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 ""; +} + +BaseType * +PlaceholderType::unify (BaseType *other) +{ + PlaceholderRules r (this); + return r.unify (other); +} + +bool +PlaceholderType::can_eq (BaseType *other) +{ + PlaceholderCmp r (this); + 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..c04c249 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"; } @@ -1474,6 +1478,34 @@ public: 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 refs = std::set ()) + : BaseType (ref, ref, TypeKind::PLACEHOLDER, refs) + {} + + PlaceholderType (HirId ref, HirId ty_ref, + std::set refs = std::set ()) + : 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) override; + + BaseType *clone () final override; + + std::string get_name () const override final { return as_string (); } + + bool is_unit () const override { return true; } +}; + } // namespace TyTy } // namespace Rust -- cgit v1.1 From 99355534ef44f316ec2b72f4776e08cf01169715 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 8 Jul 2021 13:41:30 +0100 Subject: The type system has a function can_eq this adds a with_errors flag With the type system we can check for equality explicitly which is useful. When it comes to TypeParameters or Placeholders can_eq allows for: fn bla() -> fn bla() -> i32 The type parameter can be subsituted which means the generic function can equal the subsituted one if it was given the right substituion arguments. This can emit errors such as expected [X] got [Y] or we might want to have silent errors so we can filter impl items such as the impl item overlapping pass --- .../typecheck/rust-hir-inherent-impl-overlap.h | 2 +- gcc/rust/typecheck/rust-hir-path-probe.h | 2 +- gcc/rust/typecheck/rust-hir-type-check-expr.h | 2 +- gcc/rust/typecheck/rust-hir-type-check-implitem.h | 2 +- gcc/rust/typecheck/rust-tyty-cmp.h | 448 +++++++++++++++++---- gcc/rust/typecheck/rust-tyty.cc | 76 ++-- gcc/rust/typecheck/rust-tyty.h | 40 +- 7 files changed, 440 insertions(+), 132 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h index 47894b1..cbfe1df 100644 --- a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h +++ b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h @@ -145,7 +145,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..e21bfc9 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.h +++ b/gcc/rust/typecheck/rust-hir-path-probe.h @@ -58,7 +58,7 @@ 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 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 (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..d617882 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -263,7 +263,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-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h index 7595e2f..f01ef3b 100644 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ b/gcc/rust/typecheck/rust-tyty-cmp.h @@ -46,61 +46,303 @@ public: return ok; } - virtual void visit (TupleType &) override { ok = false; } + virtual void visit (TupleType &type) override + { + ok = false; - virtual void visit (ADTType &) 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 (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 (FnType &) 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 (FnPtr &) override { ok = false; } + 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 (ArrayType &) 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 (BoolType &) 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 (IntType &) 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 (UintType &) 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 (USizeType &) 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 (ISizeType &) 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 (FloatType &) 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 (ErrorType &) 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 (CharType &) 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 (ReferenceType &) 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 (ParamType &) override + virtual void visit (ReferenceType &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 (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 (NeverType &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 (NeverType &) 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 (PlaceholderType &) override - { // it is ok for types to can eq to a placeholder + 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. */ @@ -112,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 { @@ -333,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 { @@ -353,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; } @@ -383,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 { @@ -398,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; @@ -418,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; @@ -432,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; @@ -452,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; @@ -475,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 { @@ -511,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; } @@ -531,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 { @@ -554,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 { @@ -577,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 { @@ -600,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 { @@ -624,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; @@ -645,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 { @@ -660,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; @@ -681,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 { @@ -701,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 { @@ -721,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 { @@ -741,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: @@ -762,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 { a: T }; When we invoke it we can do either: @@ -786,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: @@ -812,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; } @@ -827,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; } @@ -842,7 +1110,47 @@ class PlaceholderCmp : public BaseCmp using Rust::TyTy::BaseCmp::visit; public: - PlaceholderCmp (PlaceholderType *base) : BaseCmp (base), base (base) {} + 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; } diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 503d380..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); } @@ -1515,9 +1515,9 @@ PlaceholderType::unify (BaseType *other) } bool -PlaceholderType::can_eq (BaseType *other) +PlaceholderType::can_eq (BaseType *other, bool emit_errors) { - PlaceholderCmp r (this); + PlaceholderCmp r (this, emit_errors); return r.can_eq (other); } diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index c04c249..d85b8a8 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -155,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 @@ -274,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; @@ -308,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; @@ -336,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; @@ -421,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; @@ -853,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; @@ -960,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; @@ -1056,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; @@ -1098,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; @@ -1137,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; }; @@ -1170,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; } @@ -1210,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; } @@ -1248,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; } @@ -1288,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; }; @@ -1321,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; }; @@ -1354,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; }; @@ -1391,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; @@ -1436,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; @@ -1469,7 +1469,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; @@ -1497,7 +1497,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; -- cgit v1.1 From 97b917f8d287b362fabf7b8da0796237bb8e16d1 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 8 Jul 2021 14:45:56 +0100 Subject: Traits must inherit the prefix trait path TraitItems must inherent the Trait name such that the items are prefixed accordingly: trait foo { // Path foo fn bar().. // Path foo::bar } --- gcc/rust/resolve/rust-ast-resolve-toplevel.h | 2 +- gcc/testsuite/rust/compile/torture/traits3.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h index 44f5b22..9f0d816 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -183,7 +183,7 @@ public: }); for (auto &item : trait.get_trait_items ()) - ResolveTopLevelTraitItems::go (item.get ()); + ResolveTopLevelTraitItems::go (item.get (), path); } private: 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; -- cgit v1.1 From 8bfeef998ff340fef37f07e1a7a0366e73296380 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 8 Jul 2021 15:32:14 +0100 Subject: Add node-ids to type-path-segments in AST We must track the type path segments ids within the Canonical path. --- gcc/rust/ast/rust-path.h | 16 ++--- gcc/rust/hir/rust-ast-lower-type.h | 11 +++- gcc/rust/hir/rust-ast-lower.cc | 10 ++- gcc/rust/hir/tree/rust-hir-path.h | 87 ++++++++++++++++++--------- gcc/rust/typecheck/rust-hir-type-check-type.h | 4 +- 5 files changed, 84 insertions(+), 44 deletions(-) (limited to 'gcc') 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/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 (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 clone_type_path_segment () const { return std::unique_ptr (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_args, std::vector > type_args, std::vector 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 cb) + std::vector > &get_segments () { - for (auto &seg : segments) - { - if (!cb (seg.get ())) - return; - } + return segments; } - TypePathSegment *get_final_segment () { return segments.back ().get (); } + std::unique_ptr &get_final_segment () + { + return segments.back (); + } }; struct QualifiedPathType 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); -- cgit v1.1 From 213bc11225fcbb57e2fa6d949917bd2cf44e2477 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 8 Jul 2021 15:44:59 +0100 Subject: canonical path enhancements This refactors the canonical path to enforce the segment ids. --- gcc/rust/resolve/rust-ast-resolve-expr.h | 28 +++++++----- gcc/rust/resolve/rust-ast-resolve-implitem.h | 4 +- gcc/rust/resolve/rust-ast-resolve-item.h | 19 ++++++-- gcc/rust/resolve/rust-ast-resolve-pattern.h | 10 ++-- gcc/rust/resolve/rust-ast-resolve-stmt.h | 6 ++- gcc/rust/resolve/rust-ast-resolve-toplevel.h | 19 +++++--- gcc/rust/resolve/rust-ast-resolve-type.h | 68 +++++++++++++++------------- gcc/rust/resolve/rust-ast-resolve.cc | 48 ++++++++++++-------- gcc/rust/resolve/rust-ast-verify-assignee.h | 3 +- gcc/rust/resolve/rust-name-resolver.h | 39 ++++++++-------- 10 files changed, 142 insertions(+), 102 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index d6f5fcd..ec89f6c 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -118,7 +118,8 @@ public: void visit (AST::IdentifierExpr &expr) override { if (resolver->get_name_scope ().lookup ( - CanonicalPath::new_seg (expr.as_string ()), &resolved_node)) + 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::new_seg (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::new_seg (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"); @@ -299,9 +301,10 @@ public: } NodeId resolved_node = UNKNOWN_NODEID; - if (!resolver->get_label_scope ().lookup (CanonicalPath::new_seg ( - label.get_lifetime_name ()), - &resolved_node)) + if (!resolver->get_label_scope ().lookup ( + 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"); @@ -330,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::new_seg (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,9 +361,10 @@ public: } NodeId resolved_node = UNKNOWN_NODEID; - if (!resolver->get_label_scope ().lookup (CanonicalPath::new_seg ( - label.get_lifetime_name ()), - &resolved_node)) + if (!resolver->get_label_scope ().lookup ( + 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 b622dcb..2b3a09a 100644 --- a/gcc/rust/resolve/rust-ast-resolve-implitem.h +++ b/gcc/rust/resolve/rust-ast-resolve-implitem.h @@ -45,8 +45,8 @@ public: void visit (AST::TypeAlias &type) override { - auto path - = prefix.append (CanonicalPath::new_seg (type.get_new_type_name ())); + 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 { diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index 09d6430..ad817dc 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -184,17 +184,23 @@ public: impl_block.get_node_id (), canonicalize_type_with_generics); if (resolved_node == UNKNOWN_NODEID) - return; + { + resolver->get_type_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); 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 (); } @@ -293,15 +299,18 @@ public: 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); 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 (); } diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h index b2d059e..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::new_seg (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,10 +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::new_seg ( - 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 b0cdeb2..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::new_seg (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::new_seg (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 9f0d816..9abbb18 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -42,7 +42,8 @@ public: void visit (AST::TypeAlias &alias) override { auto path - = prefix.append (CanonicalPath::new_seg (alias.get_new_type_name ())); + = 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 { @@ -55,7 +56,8 @@ public: void visit (AST::TupleStruct &struct_decl) override { auto path - = prefix.append (CanonicalPath::new_seg (struct_decl.get_identifier ())); + = 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 { @@ -68,7 +70,8 @@ public: void visit (AST::StructStruct &struct_decl) override { auto path - = prefix.append (CanonicalPath::new_seg (struct_decl.get_identifier ())); + = 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 { @@ -80,7 +83,8 @@ public: void visit (AST::StaticItem &var) override { - auto path = prefix.append (CanonicalPath::new_seg (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 { @@ -163,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 ()) @@ -172,8 +177,8 @@ public: void visit (AST::Trait &trait) override { - CanonicalPath path - = prefix.append (CanonicalPath::new_seg (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 { diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index cf6962b..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::new_seg (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::new_seg (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::new_seg (method.get_method_name ()); + return CanonicalPath::new_seg (method.get_node_id (), + method.get_method_name ()); } }; @@ -58,6 +61,7 @@ public: static CanonicalPath resolve (AST::TraitItemFunc &function) { return CanonicalPath::new_seg ( + function.get_node_id (), function.get_trait_function_decl ().get_identifier ()); } }; @@ -68,7 +72,7 @@ public: static CanonicalPath resolve (AST::TraitItemMethod &method) { return CanonicalPath::new_seg ( - method.get_trait_method_decl ().get_identifier ()); + method.get_node_id (), method.get_trait_method_decl ().get_identifier ()); } }; @@ -77,7 +81,8 @@ class ResolveTraitItemConstToCanonicalPath public: static CanonicalPath resolve (AST::TraitItemConst &constant) { - return CanonicalPath::new_seg (constant.get_identifier ()); + return CanonicalPath::new_seg (constant.get_node_id (), + constant.get_identifier ()); } }; @@ -86,7 +91,7 @@ class ResolveTraitItemTypeToCanonicalPath public: static CanonicalPath resolve (AST::TraitItemType &type) { - return CanonicalPath::new_seg (type.get_identifier ()); + return CanonicalPath::new_seg (type.get_node_id (), type.get_identifier ()); } }; @@ -119,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); @@ -143,41 +148,40 @@ class ResolvePathSegmentToCanonicalPath public: static CanonicalPath resolve (AST::PathExprSegment &seg) { - CanonicalPath path - = CanonicalPath::new_seg (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::new_seg ("<" + 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: @@ -191,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; } @@ -318,7 +323,8 @@ public: // for now lets focus on handling the basics: like struct { a:T, ....} resolver->get_type_scope ().insert ( - CanonicalPath::new_seg (param.get_type_representation ()), + 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 (), diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index d47371c..b568e1c 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -122,7 +122,8 @@ Resolver::insert_builtin_types (Rib *r) for (auto &builtin : builtins) { CanonicalPath builtin_path - = CanonicalPath::new_seg (builtin->as_string ()); + = 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 {}); @@ -385,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; @@ -402,7 +403,7 @@ ResolveTypeToCanonicalPath::canonicalize_generic_args (AST::GenericArgs &args) i++; } - return CanonicalPath::new_seg ("<" + buf + ">"); + return "<" + buf + ">"; } bool @@ -429,24 +430,31 @@ ResolveTypeToCanonicalPath::visit (AST::TypePathSegmentGeneric &seg) return; } - // ident seg - CanonicalPath ident_seg - = CanonicalPath::new_seg (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 @@ -461,7 +469,8 @@ ResolveTypeToCanonicalPath::visit (AST::TypePathSegment &seg) } CanonicalPath ident_seg - = CanonicalPath::new_seg (seg.get_ident_segment ().as_string ()); + = CanonicalPath::new_seg (seg.get_node_id (), + seg.get_ident_segment ().as_string ()); result = result.append (ident_seg); } @@ -476,7 +485,8 @@ ResolvePath::resolve_path (AST::PathInExpression *expr) bool segment_is_type = false; CanonicalPath root_seg_path - = CanonicalPath::new_seg (root_ident_seg.as_string ()); + = 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)) diff --git a/gcc/rust/resolve/rust-ast-verify-assignee.h b/gcc/rust/resolve/rust-ast-verify-assignee.h index 11a5414..aed0119 100644 --- a/gcc/rust/resolve/rust-ast-verify-assignee.h +++ b/gcc/rust/resolve/rust-ast-verify-assignee.h @@ -58,7 +58,8 @@ public: void visit (AST::IdentifierExpr &expr) override { if (!resolver->get_name_scope ().lookup ( - CanonicalPath::new_seg (expr.as_string ()), &resolved_node)) + 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 d3b22a0..033b891 100644 --- a/gcc/rust/resolve/rust-name-resolver.h +++ b/gcc/rust/resolve/rust-name-resolver.h @@ -55,10 +55,10 @@ public: return *this; } - static CanonicalPath new_seg (const std::string &path) + static CanonicalPath new_seg (NodeId id, const std::string &path) { rust_assert (!path.empty ()); - return CanonicalPath ({path}); + return CanonicalPath ({std::pair (id, path)}); } std::string get () const @@ -67,20 +67,15 @@ public: for (size_t i = 0; i < segs.size (); i++) { bool have_more = (i + 1) < segs.size (); - const std::string &seg = segs.at (i); + const std::string &seg = segs.at (i).second; buf += seg + (have_more ? "::" : ""); } return buf; } - static CanonicalPath get_big_self () + static CanonicalPath get_big_self (NodeId id) { - return CanonicalPath::new_seg ("Self"); - } - - static CanonicalPath get_wee_self () - { - return CanonicalPath::new_seg ("self"); + return CanonicalPath::new_seg (id, "Self"); } static CanonicalPath create_empty () { return CanonicalPath ({}); } @@ -93,7 +88,7 @@ public: if (is_error ()) return CanonicalPath (other.segs); - std::vector copy (segs); + std::vector> copy (segs); for (auto &s : other.segs) copy.push_back (s); @@ -105,9 +100,9 @@ public: // A // A::B // A::B::C - void iterate_path (std::function cb) const + void iterate (std::function cb) const { - std::vector buf; + std::vector> buf; for (auto &seg : segs) { buf.push_back (seg); @@ -116,6 +111,12 @@ public: } } + NodeId get_id () const + { + rust_assert (!segs.empty ()); + return segs.back ().first; + } + bool operator== (const CanonicalPath &b) const { return get ().compare (b.get ()) == 0; @@ -124,9 +125,11 @@ public: bool operator< (const CanonicalPath &b) const { return get () < b.get (); } private: - explicit CanonicalPath (std::vector path) : segs (path) {} + explicit CanonicalPath (std::vector> path) + : segs (path) + {} - std::vector segs; + std::vector> segs; }; class Rib @@ -255,8 +258,8 @@ private: NodeId node_id; std::map mappings; std::map reverse_mappings; - std::set > decls_within_rib; - std::map > references; + std::set> decls_within_rib; + std::map> references; }; class Scope @@ -494,7 +497,7 @@ private: // map of resolved names mutability flag std::map decl_mutability; // map of resolved names and set of assignments to the decl - std::map > assignment_to_decl; + std::map> assignment_to_decl; }; } // namespace Resolver -- cgit v1.1 From 0352605f4ae03639dfdeb0c3b5e02c344807075c Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 9 Jul 2021 13:40:36 +0100 Subject: Add path probe and impl overlapping updates for TypeAliases With the desuagaring of AST::TraitImpl and AST::InherentImpl into a generic HIR::ImplBlock we must ensure the existing passes can support TypeAliases accordingly. --- gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h | 6 ++++++ gcc/rust/typecheck/rust-hir-path-probe.h | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h index cbfe1df..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; diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h index e21bfc9..a10a562 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.h +++ b/gcc/rust/typecheck/rust-hir-path-probe.h @@ -65,6 +65,21 @@ public: 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 ()); -- cgit v1.1 From 7ebf5d62d208f52d8b63824165ae830c190d91b5 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 10 Jul 2021 21:04:06 +0100 Subject: Ensure adding references adds it for all declarations with that ID In the case for implicit declarations we must ensure all declarations have the reference appended. --- gcc/rust/resolve/rust-name-resolver.h | 1 - 1 file changed, 1 deletion(-) (limited to 'gcc') diff --git a/gcc/rust/resolve/rust-name-resolver.h b/gcc/rust/resolve/rust-name-resolver.h index 033b891..7938c7c 100644 --- a/gcc/rust/resolve/rust-name-resolver.h +++ b/gcc/rust/resolve/rust-name-resolver.h @@ -326,7 +326,6 @@ public: { ok = true; r->append_reference_for_def (defId, refId); - return false; } return true; }); -- cgit v1.1 From defb583203923bf4edeb0531e85fa28de5015ecb Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 5 Jul 2021 17:49:04 +0100 Subject: Add support for TypeAliases on Traits This is the initial support for associated types, by creating placeholder types for each trait type alias. When it comes to checking for compatibility we are missing the piece to ensure that the type is defintly the same as the associated type. Addresses #471 #456 --- gcc/rust/resolve/rust-ast-resolve-item.h | 341 ++++++++++++++-------- gcc/rust/resolve/rust-ast-resolve.cc | 16 + gcc/rust/typecheck/rust-hir-type-check-implitem.h | 88 +++++- gcc/testsuite/rust/compile/torture/traits4.rs | 26 ++ gcc/testsuite/rust/compile/torture/traits5.rs | 26 ++ 5 files changed, 378 insertions(+), 119 deletions(-) create mode 100644 gcc/testsuite/rust/compile/torture/traits4.rs create mode 100644 gcc/testsuite/rust/compile/torture/traits5.rs (limited to 'gcc') diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index ad817dc..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 (nullptr)); + + std::vector > segments; + segments.push_back (std::unique_ptr ( + 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 ()) { @@ -186,6 +346,7 @@ public: if (resolved_node == UNKNOWN_NODEID) { resolver->get_type_scope ().pop (); + resolver->get_name_scope ().pop (); return; } @@ -197,11 +358,15 @@ public: 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 ( Self, impl_block.get_type ()->get_node_id ()); + resolver->get_type_scope ().pop (); + resolver->get_name_scope ().pop (); } void visit (AST::Method &method) override @@ -268,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 ()) { @@ -286,6 +454,7 @@ public: if (trait_resolved_node == UNKNOWN_NODEID) { resolver->get_type_scope ().pop (); + resolver->get_name_scope ().pop (); return; } @@ -296,6 +465,7 @@ public: if (type_resolved_node == UNKNOWN_NODEID) { resolver->get_type_scope ().pop (); + resolver->get_name_scope ().pop (); return; } @@ -307,7 +477,9 @@ public: 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 ( Self, impl_block.get_type ()->get_node_id ()); @@ -317,150 +489,85 @@ public: 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 (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); + // 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 ()); - 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 ()); - - // 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 (nullptr)); - - std::vector > segments; - segments.push_back (std::unique_ptr ( - new AST::TypePathSegment ("Self", false, self_param.get_locus ()))); +protected: + void resolve_impl_item (AST::TraitImplItem *item, const CanonicalPath &self); + void resolve_impl_item (AST::InherentImplItem *item, + const CanonicalPath &self); - 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 ()); + ResolveItem () : ResolverBase (UNKNOWN_NODEID) {} +}; - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - } +class ResolveImplItems : public ResolveItem +{ + using Rust::Resolver::ResolveItem::visit; - void visit (AST::TraitItemConst &constant) override +public: + static void go (AST::InherentImplItem *item, const CanonicalPath &self) { - ResolveType::go (constant.get_type ().get (), constant.get_node_id ()); - ResolveExpr::go (constant.get_expr ().get (), constant.get_node_id ()); + 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_decl_mutability (constant.get_node_id (), false); - resolver->mark_assignment_to_decl (constant.get_node_id (), - constant.get_node_id ()); - } + static void go (AST::TraitImplItem *item, const CanonicalPath &self) + { + ResolveImplItems resolver (self); + item->accept_vis (resolver); + }; - void visit (AST::TraitItemType &alias) override + void visit (AST::TypeAlias &alias) override { - // nothing to do here until we start supporting Type Bounds + ResolveItem::visit (alias); + + 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 ()); } 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.cc b/gcc/rust/resolve/rust-ast-resolve.cc index b568e1c..18047db 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -619,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/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index d617882..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 { 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); +} -- cgit v1.1