aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2022-03-16 16:19:31 +0000
committerPhilip Herron <philip.herron@embecosm.com>2022-03-16 22:12:35 +0000
commit8086790254d0adaad48405ee838b8ca699e9d9a8 (patch)
tree12f83b7535a7c2c881f1e5a2b56df0d669c88cb0
parent21cf0e67a6f748525ca79e8d9aa59c94bef13519 (diff)
downloadgcc-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.in1
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.cc84
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.h8
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h43
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.h5
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.cc28
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h97
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.cc87
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc17
-rw-r--r--gcc/rust/typecheck/rust-tyty.h39
-rw-r--r--gcc/testsuite/rust/compile/issue-1019.rs19
-rw-r--r--gcc/testsuite/rust/compile/traits12.rs20
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> &params_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> &params_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
+ }
+}