diff options
-rw-r--r-- | gcc/rust/Make-lang.in | 1 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-type.h | 3 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve.cc | 38 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 29 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-substitution-mapper.cc | 49 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-substitution-mapper.h | 8 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty-call.h | 9 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 2 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/torture/issue-808.rs | 23 |
9 files changed, 140 insertions, 22 deletions
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/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..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 @@ -481,6 +487,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 diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index daef15b..9eef755 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<Adjustment> adjustments; @@ -295,6 +309,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 +419,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-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 +// <http://www.gnu.org/licenses/>. + +#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 { 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 ()) 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<T> Foo for &T { + type Target = T; + + fn bar(&self) -> &T { + *self + } +} + +pub fn main() { + let a: i32 = 123; + let b: &i32 = &a; + + b.bar(); +} |