diff options
author | Philip Herron <philip.herron@embecosm.com> | 2022-03-16 16:19:31 +0000 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2022-03-16 22:12:35 +0000 |
commit | 8086790254d0adaad48405ee838b8ca699e9d9a8 (patch) | |
tree | 12f83b7535a7c2c881f1e5a2b56df0d669c88cb0 | |
parent | 21cf0e67a6f748525ca79e8d9aa59c94bef13519 (diff) | |
download | gcc-8086790254d0adaad48405ee838b8ca699e9d9a8.zip gcc-8086790254d0adaad48405ee838b8ca699e9d9a8.tar.gz gcc-8086790254d0adaad48405ee838b8ca699e9d9a8.tar.bz2 |
Fix unconstrained type parameter checks
This patch removes our old method of checking for unconstrained type
parameters which only worked for the basic cases such as:
impl<T> Foo { }
But checking for unconstrained types is more complex, we need to handle
covariant types such as:
impl<T> *T { }
Or
struct foo<X,Y>(X,Y);
impl<T> foo<&T,*T> {}
This rewrites the algorithm to take advantage of our substition
abstractions and HirIds so we can map the ids of the type-params to be
constrained and look at the trait-references used-arguments when the
generics are applied (or they may be empty) and then do the same for any
used arguments on an algebraic data type.
Fixes #1019
-rw-r--r-- | gcc/rust/Make-lang.in | 1 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-base.cc | 84 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-base.h | 8 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-item.h | 43 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-toplevel.h | 5 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-type.cc | 28 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-type.h | 97 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty-bounds.cc | 87 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 17 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 39 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/issue-1019.rs | 19 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/traits12.rs | 20 |
12 files changed, 289 insertions, 159 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 76a45e7..cd40efb 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -99,6 +99,7 @@ GRS_OBJS = \ rust/rust-hir-type-check-pattern.o \ rust/rust-hir-type-check-expr.o \ rust/rust-hir-dot-operator.o \ + rust/rust-hir-type-check-base.o \ rust/rust-autoderef.o \ rust/rust-substitution-mapper.o \ rust/rust-lint-marklive.o \ diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc new file mode 100644 index 0000000..32c5881 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -0,0 +1,84 @@ +// Copyright (C) 2020-2022 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-hir-type-check-base.h" + +namespace Rust { +namespace Resolver { + +bool +TypeCheckBase::check_for_unconstrained ( + const std::vector<TyTy::SubstitutionParamMapping> ¶ms_to_constrain, + const TyTy::SubstitutionArgumentMappings &constraint_a, + const TyTy::SubstitutionArgumentMappings &constraint_b, + const TyTy::BaseType *reference) +{ + std::set<HirId> symbols_to_constrain; + std::map<HirId, Location> symbol_to_location; + for (const auto &p : params_to_constrain) + { + HirId ref = p.get_param_ty ()->get_ref (); + symbols_to_constrain.insert (ref); + symbol_to_location.insert ({ref, p.get_param_locus ()}); + } + + // set up the set of constrained symbols + std::set<HirId> constrained_symbols; + for (const auto &c : constraint_a.get_mappings ()) + { + const TyTy::BaseType *arg = c.get_tyty (); + if (arg != nullptr) + { + const TyTy::BaseType *p = arg->get_root (); + constrained_symbols.insert (p->get_ty_ref ()); + } + } + for (const auto &c : constraint_b.get_mappings ()) + { + const TyTy::BaseType *arg = c.get_tyty (); + if (arg != nullptr) + { + const TyTy::BaseType *p = arg->get_root (); + constrained_symbols.insert (p->get_ty_ref ()); + } + } + + const auto root = reference->get_root (); + if (root->get_kind () == TyTy::TypeKind::PARAM) + { + const TyTy::ParamType *p = static_cast<const TyTy::ParamType *> (root); + constrained_symbols.insert (p->get_ty_ref ()); + } + + // check for unconstrained + bool unconstrained = false; + for (auto &sym : symbols_to_constrain) + { + bool used = constrained_symbols.find (sym) != constrained_symbols.end (); + if (!used) + { + Location locus = symbol_to_location.at (sym); + rust_error_at (locus, "unconstrained type parameter"); + unconstrained = true; + } + } + return unconstrained; +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h index 830b95ca..5a3f553 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.h +++ b/gcc/rust/typecheck/rust-hir-type-check-base.h @@ -47,6 +47,14 @@ protected: TraitReference *resolve_trait_path (HIR::TypePath &); + TyTy::TypeBoundPredicate get_predicate_from_bound (HIR::TypePath &path); + + bool check_for_unconstrained ( + const std::vector<TyTy::SubstitutionParamMapping> ¶ms_to_constrain, + const TyTy::SubstitutionArgumentMappings &constraint_a, + const TyTy::SubstitutionArgumentMappings &constraint_b, + const TyTy::BaseType *reference); + Analysis::Mappings *mappings; Resolver *resolver; TypeCheckContext *context; diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index 8a41548..4c6c4a6 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -70,7 +70,7 @@ public: } } - std::vector<TyTy::TypeBoundPredicate> specified_bounds; + auto specified_bound = TyTy::TypeBoundPredicate::error (); TraitReference *trait_reference = &TraitReference::error_node (); if (impl_block.has_trait_ref ()) { @@ -78,26 +78,7 @@ public: trait_reference = TraitResolver::Resolve (*ref.get ()); rust_assert (!trait_reference->is_error ()); - // setup the bound - TyTy::TypeBoundPredicate predicate (*trait_reference, - ref->get_locus ()); - auto &final_seg = ref->get_final_segment (); - if (final_seg->is_generic_segment ()) - { - auto final_generic_seg - = static_cast<HIR::TypePathSegmentGeneric *> (final_seg.get ()); - if (final_generic_seg->has_generic_args ()) - { - HIR::GenericArgs &generic_args - = final_generic_seg->get_generic_args (); - - // this is applying generic arguments to a trait - // reference - predicate.apply_generic_arguments (&generic_args); - } - } - - specified_bounds.push_back (std::move (predicate)); + specified_bound = get_predicate_from_bound (*ref.get ()); } TyTy::BaseType *self = nullptr; @@ -108,11 +89,25 @@ public: "failed to resolve Self for ImplBlock"); return; } - // inherit the bounds - self->inherit_bounds (specified_bounds); + // inherit the bounds + if (!specified_bound.is_error ()) + self->inherit_bounds ({specified_bound}); + + // check for any unconstrained type-params + const TyTy::SubstitutionArgumentMappings trait_constraints + = specified_bound.get_substitution_arguments (); + const TyTy::SubstitutionArgumentMappings impl_constraints + = GetUsedSubstArgs::From (self); + + bool impl_block_has_unconstrained_typarams + = check_for_unconstrained (substitutions, trait_constraints, + impl_constraints, self); + if (impl_block_has_unconstrained_typarams) + return; + + // validate the impl items bool is_trait_impl_block = !trait_reference->is_error (); - std::vector<const TraitItemReference *> trait_item_refs; for (auto &impl_item : impl_block.get_impl_items ()) { diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index 2271dace..5e12466 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -468,9 +468,8 @@ public: ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); } - auto self - = TypeCheckType::Resolve (impl_block.get_type ().get (), &substitutions); - if (self == nullptr || self->get_kind () == TyTy::TypeKind::ERROR) + auto self = TypeCheckType::Resolve (impl_block.get_type ().get ()); + if (self->get_kind () == TyTy::TypeKind::ERROR) return; for (auto &impl_item : impl_block.get_impl_items ()) diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index ee77128..914bebb 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -84,11 +84,6 @@ TypeCheckType::visit (HIR::TypePath &path) } translated = SubstMapper::Resolve (path_type, path.get_locus (), &args); - if (translated->get_kind () != TyTy::TypeKind::ERROR - && mappings != nullptr) - { - check_for_unconstrained (args.get_type_args ()); - } } else if (!args.is_empty ()) { @@ -548,26 +543,11 @@ TypeCheckType::visit (HIR::TraitObjectType &type) HIR::TypeParamBound &b = *bound.get (); HIR::TraitBound &trait_bound = static_cast<HIR::TraitBound &> (b); - auto &type_path = trait_bound.get_path (); - TraitReference *trait = resolve_trait_path (type_path); - TyTy::TypeBoundPredicate predicate (*trait, trait_bound.get_locus ()); - auto &final_seg = type_path.get_final_segment (); - if (final_seg->is_generic_segment ()) - { - auto final_generic_seg - = static_cast<HIR::TypePathSegmentGeneric *> (final_seg.get ()); - if (final_generic_seg->has_generic_args ()) - { - HIR::GenericArgs &generic_args - = final_generic_seg->get_generic_args (); - - // this is applying generic arguments to a trait - // reference - predicate.apply_generic_arguments (&generic_args); - } - } + TyTy::TypeBoundPredicate predicate + = get_predicate_from_bound (trait_bound.get_path ()); - if (predicate.is_object_safe (true, type.get_locus ())) + if (!predicate.is_error () + && predicate.is_object_safe (true, type.get_locus ())) specified_bounds.push_back (std::move (predicate)); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index 373287e..127502f 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -57,12 +57,9 @@ class TypeCheckType : public TypeCheckBase using Rust::Resolver::TypeCheckBase::visit; public: - static TyTy::BaseType * - Resolve (HIR::Type *type, - std::vector<TyTy::SubstitutionParamMapping> *subst_mappings - = nullptr) + static TyTy::BaseType *Resolve (HIR::Type *type) { - TypeCheckType resolver (type->get_mappings ().get_hirid (), subst_mappings); + TypeCheckType resolver (type->get_mappings ().get_hirid ()); type->accept_vis (resolver); rust_assert (resolver.translated != nullptr); resolver.context->insert_type (type->get_mappings (), resolver.translated); @@ -159,43 +156,10 @@ public: void visit (HIR::TraitObjectType &type) override; private: - TypeCheckType (HirId id, - std::vector<TyTy::SubstitutionParamMapping> *subst_mappings) - : TypeCheckBase (), subst_mappings (subst_mappings), - translated (new TyTy::ErrorType (id)) + TypeCheckType (HirId id) + : TypeCheckBase (), translated (new TyTy::ErrorType (id)) {} - void - check_for_unconstrained (std::vector<std::unique_ptr<HIR::Type>> &type_args) - { - std::map<std::string, Location> param_location_map; - std::set<std::string> param_tys; - - if (subst_mappings != nullptr) - { - for (auto &mapping : *subst_mappings) - { - std::string sym = mapping.get_param_ty ()->get_symbol (); - param_tys.insert (sym); - param_location_map[sym] = mapping.get_generic_param ().get_locus (); - } - } - - std::set<std::string> args; - for (auto &arg : type_args) - args.insert (arg->as_string ()); - - for (auto &exp : param_tys) - { - bool used = args.find (exp) != args.end (); - if (!used) - { - Location locus = param_location_map.at (exp); - rust_error_at (locus, "unconstrained type parameter"); - } - } - } - TyTy::BaseType *resolve_root_path (HIR::TypePath &path, size_t *offset, NodeId *root_resolved_node_id); @@ -205,7 +169,6 @@ private: TyTy::BaseType *tyseg, const Analysis::NodeMapping &expr_mappings, Location expr_locus); - std::vector<TyTy::SubstitutionParamMapping> *subst_mappings; TyTy::BaseType *translated; }; @@ -245,28 +208,10 @@ public: HIR::TraitBound *b = static_cast<HIR::TraitBound *> (bound.get ()); - auto &type_path = b->get_path (); - TraitReference *trait = resolve_trait_path (type_path); - TyTy::TypeBoundPredicate predicate (*trait, b->get_locus ()); - - auto &final_seg = type_path.get_final_segment (); - if (final_seg->is_generic_segment ()) - { - auto final_generic_seg - = static_cast<HIR::TypePathSegmentGeneric *> ( - final_seg.get ()); - if (final_generic_seg->has_generic_args ()) - { - HIR::GenericArgs &generic_args - = final_generic_seg->get_generic_args (); - - // this is applying generic arguments to a trait - // reference - predicate.apply_generic_arguments (&generic_args); - } - } - - specified_bounds.push_back (std::move (predicate)); + TyTy::TypeBoundPredicate predicate + = get_predicate_from_bound (b->get_path ()); + if (!predicate.is_error ()) + specified_bounds.push_back (std::move (predicate)); } break; @@ -315,28 +260,10 @@ public: HIR::TraitBound *b = static_cast<HIR::TraitBound *> (bound.get ()); - auto &type_path = b->get_path (); - TraitReference *trait = resolve_trait_path (type_path); - TyTy::TypeBoundPredicate predicate (*trait, b->get_locus ()); - - auto &final_seg = type_path.get_final_segment (); - if (final_seg->is_generic_segment ()) - { - auto final_generic_seg - = static_cast<HIR::TypePathSegmentGeneric *> ( - final_seg.get ()); - if (final_generic_seg->has_generic_args ()) - { - HIR::GenericArgs &generic_args - = final_generic_seg->get_generic_args (); - - // this is applying generic arguments to a trait - // reference - predicate.apply_generic_arguments (&generic_args); - } - } - - specified_bounds.push_back (std::move (predicate)); + TyTy::TypeBoundPredicate predicate + = get_predicate_from_bound (b->get_path ()); + if (!predicate.is_error ()) + specified_bounds.push_back (std::move (predicate)); } break; diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index 25d4966..a7ec42c 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -63,6 +63,37 @@ TypeCheckBase::resolve_trait_path (HIR::TypePath &path) return TraitResolver::Resolve (path); } +TyTy::TypeBoundPredicate +TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path) +{ + TraitReference *trait = resolve_trait_path (type_path); + if (trait->is_error ()) + return TyTy::TypeBoundPredicate::error (); + + TyTy::TypeBoundPredicate predicate (*trait, type_path.get_locus ()); + HIR::GenericArgs args + = HIR::GenericArgs::create_empty (type_path.get_locus ()); + + auto &final_seg = type_path.get_final_segment (); + if (final_seg->is_generic_segment ()) + { + auto final_generic_seg + = static_cast<HIR::TypePathSegmentGeneric *> (final_seg.get ()); + if (final_generic_seg->has_generic_args ()) + { + args = final_generic_seg->get_generic_args (); + } + } + + if (predicate.requires_generic_args ()) + { + // this is applying generic arguments to a trait reference + predicate.apply_generic_arguments (&args); + } + + return predicate; +} + } // namespace Resolver namespace TyTy { @@ -72,7 +103,7 @@ TypeBoundPredicate::TypeBoundPredicate ( : SubstitutionRef (trait_reference.get_trait_substs (), SubstitutionArgumentMappings::error ()), reference (trait_reference.get_mappings ().get_defid ()), locus (locus), - args (nullptr), error_flag (false) + args (HIR::GenericArgs::create_empty ()), error_flag (false) {} TypeBoundPredicate::TypeBoundPredicate ( @@ -80,7 +111,8 @@ TypeBoundPredicate::TypeBoundPredicate ( Location locus) : SubstitutionRef (std::move (substitutions), SubstitutionArgumentMappings::error ()), - reference (reference), locus (locus), args (nullptr), error_flag (false) + reference (reference), locus (locus), + args (HIR::GenericArgs::create_empty ()), error_flag (false) {} TypeBoundPredicate::TypeBoundPredicate (const TypeBoundPredicate &other) @@ -95,6 +127,33 @@ TypeBoundPredicate::TypeBoundPredicate (const TypeBoundPredicate &other) } } +TypeBoundPredicate & +TypeBoundPredicate::operator= (const TypeBoundPredicate &other) +{ + reference = other.reference; + locus = other.locus; + args = other.args; + error_flag = other.error_flag; + used_arguments = other.used_arguments; + + substitutions.clear (); + if (!other.is_error ()) + { + for (const auto &p : other.get_substs ()) + substitutions.push_back (p.clone ()); + } + + return *this; +} + +TypeBoundPredicate +TypeBoundPredicate::error () +{ + auto p = TypeBoundPredicate (UNKNOWN_DEFID, {}, Location ()); + p.error_flag = true; + return p; +} + std::string TypeBoundPredicate::as_string () const { @@ -139,8 +198,19 @@ TypeBoundPredicate::is_object_safe (bool emit_error, Location locus) const void TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args) { - args = generic_args; - // TODO verify these arguments are valid and not too many were added + // we need to get the substitutions argument mappings but also remember that + // we have an implicit Self argument which we must be careful to respect + rust_assert (used_arguments.is_empty ()); + rust_assert (!substitutions.empty ()); + + // we setup a dummy implict self argument + SubstitutionArg placeholder_self (&substitutions.front (), nullptr); + used_arguments.get_mappings ().push_back (std::move (placeholder_self)); + + // now actually perform a substitution + used_arguments = get_mappings_from_generic_args (*generic_args); + error_flag |= used_arguments.is_error (); + args = *generic_args; } bool @@ -222,6 +292,15 @@ TypeBoundPredicate::handle_substitions (SubstitutionArgumentMappings mappings) return nullptr; } +bool +TypeBoundPredicate::requires_generic_args () const +{ + if (is_error ()) + return false; + + return substitutions.size () > 1 && args.is_empty (); +} + // trait item reference const Resolver::TraitItemReference * diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 8d5cc5e..c12095f 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -201,11 +201,16 @@ BaseType::inherit_bounds ( const BaseType * BaseType::get_root () const { - const BaseType *root = this; - while (root->get_kind () == TyTy::REF) + const TyTy::BaseType *root = this; + if (get_kind () == TyTy::REF) { const ReferenceType *r = static_cast<const ReferenceType *> (root); - root = r->get_base (); + root = r->get_base ()->get_root (); + } + else if (get_kind () == TyTy::POINTER) + { + const PointerType *r = static_cast<const PointerType *> (root); + root = r->get_base ()->get_root (); } return root; } @@ -543,11 +548,11 @@ SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args) rust_error_at ( r, "generic item takes at least %lu type arguments but %lu were supplied", - substitutions.size (), args.get_type_args ().size ()); + (min_required_substitutions () - offs), args.get_type_args ().size ()); return SubstitutionArgumentMappings::error (); } - std::vector<SubstitutionArg> mappings; + std::vector<SubstitutionArg> mappings = used_arguments.get_mappings (); for (auto &arg : args.get_type_args ()) { BaseType *resolved = Resolver::TypeCheckType::Resolve (arg.get ()); @@ -2351,7 +2356,7 @@ ParamType::handle_substitions (SubstitutionArgumentMappings mappings) SubstitutionArg arg = SubstitutionArg::error (); bool ok = mappings.get_argument_for_symbol (this, &arg); - if (ok) + if (ok && !arg.is_error ()) p->set_ty_ref (arg.get_tyty ()->get_ref ()); return p; diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 44eb81f..58b5042 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -551,7 +551,13 @@ public: : generic (other.generic), param (other.param) {} - std::string as_string () const { return param->get_name (); } + std::string as_string () const + { + if (param == nullptr) + return "nullptr"; + + return param->get_name (); + } bool fill_param_ty (BaseType &type, Location locus); @@ -615,7 +621,9 @@ public: BaseType *get_tyty () { return argument; } - const SubstitutionParamMapping *get_param_mapping () { return param; } + const BaseType *get_tyty () const { return argument; } + + const SubstitutionParamMapping *get_param_mapping () const { return param; } static SubstitutionArg error () { return SubstitutionArg (nullptr, nullptr); } @@ -634,7 +642,8 @@ public: std::string as_string () const { - return param->as_string () + ":" + argument->as_string (); + return param->as_string () + + (argument != nullptr ? ":" + argument->as_string () : ""); } private: @@ -712,8 +721,12 @@ public: size_t size () const { return mappings.size (); } + bool is_empty () const { return size () == 0; } + std::vector<SubstitutionArg> &get_mappings () { return mappings; } + const std::vector<SubstitutionArg> &get_mappings () const { return mappings; } + std::string as_string () const { std::string buffer; @@ -951,6 +964,10 @@ public: TypeBoundPredicate (const TypeBoundPredicate &other); + TypeBoundPredicate &operator= (const TypeBoundPredicate &other); + + static TypeBoundPredicate error (); + std::string as_string () const; const Resolver::TraitReference *get () const; @@ -970,17 +987,11 @@ public: TypeBoundPredicateItem lookup_associated_item (const std::string &search) const; - HIR::GenericArgs *get_generic_args () { return args; } + HIR::GenericArgs *get_generic_args () { return &args; } - const HIR::GenericArgs *get_generic_args () const { return args; } + const HIR::GenericArgs *get_generic_args () const { return &args; } - bool has_generic_args () const - { - if (args == nullptr) - return false; - - return args->has_generic_args (); - } + bool has_generic_args () const { return args.has_generic_args (); } // WARNING THIS WILL ALWAYS RETURN NULLPTR BaseType * @@ -988,10 +999,12 @@ public: bool is_error () const; + bool requires_generic_args () const; + private: DefId reference; Location locus; - HIR::GenericArgs *args; + HIR::GenericArgs args; bool error_flag; }; diff --git a/gcc/testsuite/rust/compile/issue-1019.rs b/gcc/testsuite/rust/compile/issue-1019.rs new file mode 100644 index 0000000..aea86a8 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-1019.rs @@ -0,0 +1,19 @@ +trait A<T> { + type Output; + + fn test(self, a: &T) -> &Self::Output; +} + +struct Foo<T> { + // { dg-warning "struct is never constructed" "" { target *-*-* } .-1 } + start: T, + end: T, +} + +impl<X> A<X> for Foo<usize> { + type Output = X; + + fn test(self, a: &X) -> &Self::Output { + a + } +} diff --git a/gcc/testsuite/rust/compile/traits12.rs b/gcc/testsuite/rust/compile/traits12.rs new file mode 100644 index 0000000..25e0eb7 --- /dev/null +++ b/gcc/testsuite/rust/compile/traits12.rs @@ -0,0 +1,20 @@ +trait A<T> { + type Output; + + fn test(self, a: &T) -> &Self::Output; +} + +struct Foo<T> { + start: T, + end: T, +} + +impl<T> A for Foo<usize> { + // { dg-error "generic item takes at least 1 type arguments but 0 were supplied" "" { target *-*-* } .-1 } + // { dg-error "unconstrained type parameter" "" { target *-*-* } .-2 } + type Output = T; + + fn test(self, a: &T) -> &Self::Output { + a + } +} |