From 2547e60d2fca2a323a1b16e04c595aeeec598bc1 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 16 Nov 2021 17:05:40 +0000 Subject: Fix ICE assertion on bad duplicate name This fixes the ice for TypeNoBounds canonical paths for reference types which was not implemented resulting in empty paths for the canonical path of impl_blocks for example. A Fixme has been added to point out that we should update this interface to only take AST::TypeNoBounds. Fixes #808 --- gcc/rust/resolve/rust-ast-resolve-type.h | 3 +++ gcc/rust/resolve/rust-ast-resolve.cc | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) (limited to 'gcc') diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 838d173..2bcf79d 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -101,6 +101,7 @@ protected: using Rust::Resolver::ResolverBase::visit; public: + // FIXME this should really only take AST::TypeNoBounds& static CanonicalPath resolve (AST::Type &type, bool include_generic_args = true, bool type_resolve_generic_args = true) @@ -121,6 +122,8 @@ public: } } + void visit (AST::ReferenceType &ref) override; + void visit (AST::TypePathSegmentGeneric &seg) override; void visit (AST::TypePathSegment &seg) override; diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 921b77c..45daa02 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -481,6 +481,24 @@ ResolveTypeToCanonicalPath::visit (AST::TypePathSegment &seg) result = result.append (ident_seg); } +void +ResolveTypeToCanonicalPath::visit (AST::ReferenceType &ref) +{ + auto inner_type + = ResolveTypeToCanonicalPath::resolve (*ref.get_type_referenced ().get (), + include_generic_args_flag, + type_resolve_generic_args_flag); + + std::string segment_string ("&"); + if (ref.get_has_mut ()) + segment_string += "mut "; + + segment_string += inner_type.get (); + + auto ident_seg = CanonicalPath::new_seg (ref.get_node_id (), segment_string); + result = result.append (ident_seg); +} + // rust-ast-resolve-expr.h void -- cgit v1.1 From e584c6f8a7805b1ddc9fe97065cd8f1bac734fc2 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 16 Nov 2021 17:46:08 +0000 Subject: Generic segments must be appended to the prefix and not override --- gcc/rust/resolve/rust-ast-resolve.cc | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 45daa02..9a0d349 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -439,8 +439,10 @@ ResolveTypeToCanonicalPath::visit (AST::TypePathSegmentGeneric &seg) if (!seg.has_generic_args ()) { - result = CanonicalPath::new_seg (seg.get_node_id (), - seg.get_ident_segment ().as_string ()); + auto ident_segment + = CanonicalPath::new_seg (seg.get_node_id (), + seg.get_ident_segment ().as_string ()); + result = result.append (ident_segment); return; } @@ -454,14 +456,18 @@ ResolveTypeToCanonicalPath::visit (AST::TypePathSegmentGeneric &seg) { 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); + auto generic_segment + = CanonicalPath::new_seg (seg.get_node_id (), + seg.get_ident_segment ().as_string () + + "::" + generics); + result = result.append (generic_segment); return; } - result = CanonicalPath::new_seg (seg.get_node_id (), - seg.get_ident_segment ().as_string ()); + auto ident_segment + = CanonicalPath::new_seg (seg.get_node_id (), + seg.get_ident_segment ().as_string ()); + result = result.append (ident_segment); } void -- cgit v1.1 From 649e2ec5682ed8007987f2acb4899892a81cc18f Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 17 Nov 2021 16:45:50 +0000 Subject: Unify the adjusted self argument to the self parameter on MethodCalls When we must infer the substitutions on method calls we must make sure to unify the self arguments from the receiver, taking into account the autoderef mechanism. This enforces the type checks and fixes up any inference variables along the way. Addresses #808 --- gcc/rust/typecheck/rust-hir-type-check-expr.h | 7 ++++++- gcc/rust/typecheck/rust-tyty-call.h | 9 ++++++--- gcc/rust/typecheck/rust-tyty.cc | 2 ++ 3 files changed, 14 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 99696ae..d5d12b4 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -295,6 +295,10 @@ public: return; } + // Get the adjusted self + Adjuster adj (receiver_tyty); + TyTy::BaseType *adjusted_self = adj.adjust_type (adjustments); + // store the adjustments for code-generation to know what to do context->insert_autoderef_mappings (expr.get_mappings ().get_hirid (), std::move (adjustments)); @@ -401,7 +405,8 @@ public: } TyTy::BaseType *function_ret_tyty - = TyTy::TypeCheckMethodCallExpr::go (lookup, expr, context); + = TyTy::TypeCheckMethodCallExpr::go (lookup, expr, adjusted_self, + context); if (function_ret_tyty == nullptr || function_ret_tyty->get_kind () == TyTy::TypeKind::ERROR) { diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h index c11fd4d..3080427 100644 --- a/gcc/rust/typecheck/rust-tyty-call.h +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -88,9 +88,10 @@ class TypeCheckMethodCallExpr : private TyVisitor public: // Resolve the Method parameters and return back the return type static BaseType *go (BaseType *ref, HIR::MethodCallExpr &call, + TyTy::BaseType *adjusted_self, Resolver::TypeCheckContext *context) { - TypeCheckMethodCallExpr checker (call, context); + TypeCheckMethodCallExpr checker (call, adjusted_self, context); ref->accept_vis (checker); return checker.resolved; } @@ -125,13 +126,15 @@ public: private: TypeCheckMethodCallExpr (HIR::MethodCallExpr &c, + TyTy::BaseType *adjusted_self, Resolver::TypeCheckContext *context) - : resolved (nullptr), call (c), context (context), - mappings (Analysis::Mappings::get ()) + : resolved (nullptr), call (c), adjusted_self (adjusted_self), + context (context), mappings (Analysis::Mappings::get ()) {} BaseType *resolved; HIR::MethodCallExpr &call; + TyTy::BaseType *adjusted_self; Resolver::TypeCheckContext *context; Analysis::Mappings *mappings; }; diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 378416f..add4dbe 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -2786,6 +2786,8 @@ TypeCheckCallExpr::visit (FnPtr &type) void TypeCheckMethodCallExpr::visit (FnType &type) { + adjusted_self->unify (type.get_self_type ()); + // +1 for the receiver self size_t num_args_to_call = call.num_params () + 1; if (num_args_to_call != type.num_params ()) -- cgit v1.1 From e8695eee4f1b9121d0caa7a93ff51f69707c607f Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 17 Nov 2021 17:25:01 +0000 Subject: Add missing implict monomorphized types into the context --- gcc/rust/Make-lang.in | 1 + gcc/rust/typecheck/rust-substitution-mapper.cc | 49 ++++++++++++++++++++++++++ gcc/rust/typecheck/rust-substitution-mapper.h | 8 +---- 3 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 gcc/rust/typecheck/rust-substitution-mapper.cc (limited to 'gcc') diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index f3302c2e..f0e9bc3 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -86,6 +86,7 @@ GRS_OBJS = \ rust/rust-hir-const-fold.o \ rust/rust-hir-type-check-type.o \ rust/rust-hir-type-check-struct.o \ + rust/rust-substitution-mapper.o \ rust/rust-lint-marklive.o \ rust/rust-hir-type-check-path.o \ rust/rust-compile-intrinsic.o \ diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc new file mode 100644 index 0000000..a439416 --- /dev/null +++ b/gcc/rust/typecheck/rust-substitution-mapper.cc @@ -0,0 +1,49 @@ +// Copyright (C) 2020-2021 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#include "rust-substitution-mapper.h" +#include "rust-hir-type-check.h" + +namespace Rust { +namespace Resolver { + +TyTy::BaseType * +SubstMapperInternal::Resolve (TyTy::BaseType *base, + TyTy::SubstitutionArgumentMappings &mappings) +{ + SubstMapperInternal mapper (base->get_ref (), mappings); + base->accept_vis (mapper); + rust_assert (mapper.resolved != nullptr); + + // insert these new implict types into the context + bool is_fn = mapper.resolved->get_kind () == TyTy::TypeKind::FNDEF; + bool is_adt = mapper.resolved->get_kind () == TyTy::TypeKind::ADT; + bool is_param = mapper.resolved->get_kind () == TyTy::TypeKind::PARAM; + if (!is_fn && !is_adt && !is_param) + { + auto context = TypeCheckContext::get (); + context->insert_type ( + Analysis::NodeMapping (0, 0, mapper.resolved->get_ty_ref (), 0), + mapper.resolved); + } + + return mapper.resolved; +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h index 0b3ec3b..0932038 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.h +++ b/gcc/rust/typecheck/rust-substitution-mapper.h @@ -154,13 +154,7 @@ class SubstMapperInternal : public TyTy::TyVisitor { public: static TyTy::BaseType *Resolve (TyTy::BaseType *base, - TyTy::SubstitutionArgumentMappings &mappings) - { - SubstMapperInternal mapper (base->get_ref (), mappings); - base->accept_vis (mapper); - rust_assert (mapper.resolved != nullptr); - return mapper.resolved; - } + TyTy::SubstitutionArgumentMappings &mappings); void visit (TyTy::FnType &type) override { -- cgit v1.1 From db832831ed15ad25aec99a7d4a87b7019e5f1aa4 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 17 Nov 2021 17:38:41 +0000 Subject: Probe for candidates on based on the actual receiver type Impl blocks Self type is a TypeNoBouns which means it can be for types such as: impl &T {}. I think we might need to change the probe algorithm for method calls to be fully based on the autoderef rather than trying to filter based on the Self type. More investigation is needed for the probe phase here. Fixes #808 --- gcc/rust/typecheck/rust-hir-type-check-expr.h | 22 ++++++++++++++++++---- gcc/testsuite/rust/compile/torture/issue-808.rs | 23 +++++++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/rust/compile/torture/issue-808.rs (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index d5d12b4..c206592 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -265,15 +265,29 @@ public: bool probe_impls = !receiver_is_generic; bool ignore_mandatory_trait_items = !receiver_is_generic; + auto probe_type = probe_impls ? receiver_tyty : root; auto candidates - = PathProbeType::Probe (root, expr.get_method_name ().get_segment (), + = PathProbeType::Probe (probe_type, + expr.get_method_name ().get_segment (), probe_impls, probe_bounds, ignore_mandatory_trait_items); if (candidates.empty ()) { - rust_error_at (expr.get_locus (), - "failed to resolve the PathExprSegment to any item"); - return; + if (probe_impls) + { + candidates + = PathProbeType::Probe (root, + expr.get_method_name ().get_segment (), + probe_impls, probe_bounds, + ignore_mandatory_trait_items); + } + + if (candidates.empty ()) + { + rust_error_at (expr.get_locus (), + "failed to resolve the PathExprSegment to any item"); + return; + } } std::vector adjustments; diff --git a/gcc/testsuite/rust/compile/torture/issue-808.rs b/gcc/testsuite/rust/compile/torture/issue-808.rs new file mode 100644 index 0000000..bfbf774 --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/issue-808.rs @@ -0,0 +1,23 @@ +pub trait Foo { + type Target; + // { dg-warning "unused name" "" { target *-*-* } .-1 } + + fn bar(&self) -> &Self::Target; + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .Foo::bar." "" { target *-*-* } .-2 } +} + +impl Foo for &T { + type Target = T; + + fn bar(&self) -> &T { + *self + } +} + +pub fn main() { + let a: i32 = 123; + let b: &i32 = &a; + + b.bar(); +} -- cgit v1.1