aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-04-19 16:33:48 +0000
committerGitHub <noreply@github.com>2022-04-19 16:33:48 +0000
commit4152743451a73591fa60bc52f0b28447ef4a8878 (patch)
tree9f14d6ba86b46d6eb778df421be3927e99d9da0e
parent5b14291b54fe72407b840631511d1c3bb07df22e (diff)
parentad9e185e15fcfea8d23b03acccc26dab4e45bf45 (diff)
downloadgcc-4152743451a73591fa60bc52f0b28447ef4a8878.zip
gcc-4152743451a73591fa60bc52f0b28447ef4a8878.tar.gz
gcc-4152743451a73591fa60bc52f0b28447ef4a8878.tar.bz2
Merge #1121
1121: Fix bad projection substitution r=philberty a=philberty When we have a Trait such as: ``` pub unsafe trait SliceIndex<T> { type Output; fn index(self, slice: &T) -> &Self::Output; } unsafe impl<T> SliceIndex<[T]> for Range<usize> { type Output = [T]; fn index(self, slice: &[T]) -> &[T] { unsafe { &*self.get_unchecked(slice) } } } ``` When we need to verify that the impl index is compatible fir SliceIndex we get the Type info for the trait-item which is: fn<Self, T> index(self: Self, slice: &T) -> &<placeholder=projection<T>=[T]> This projection gets setup and the types are substituted with Self=Range<usize> and T=[T] which ended up substituting the projection twice resulting in a recursive slice [T=[T]]. In this case the associated type is already setup for the placeholder and does not require generic substitution. This means we added a flag to the substitution generic arguments mappings to handle this case. This patch also addressed memory corruption with the TypeBoundPredicate as part of the debugging of this issue which resulted in a segv when trying to debug the mappings. The issue was the copy constructors needed to update the used argument mappings each time since the substitution param mappings are copied and the addresses no longer exist, valgrind was great here to find this issue. Fixes #1120 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-ref.h22
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.cc4
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.h160
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h10
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h4
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.h9
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.cc86
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc18
-rw-r--r--gcc/rust/typecheck/rust-tyty.h28
-rw-r--r--gcc/testsuite/rust/compile/traits9.rs3
-rw-r--r--gcc/testsuite/rust/execute/torture/issue-1120.rs123
11 files changed, 332 insertions, 135 deletions
diff --git a/gcc/rust/typecheck/rust-hir-trait-ref.h b/gcc/rust/typecheck/rust-hir-trait-ref.h
index d8c8a19..a12736f 100644
--- a/gcc/rust/typecheck/rust-hir-trait-ref.h
+++ b/gcc/rust/typecheck/rust-hir-trait-ref.h
@@ -137,9 +137,9 @@ public:
// the trait will not be stored in its own map yet
void on_resolved ();
- void associated_type_set (TyTy::BaseType *ty);
+ void associated_type_set (TyTy::BaseType *ty) const;
- void associated_type_reset ();
+ void associated_type_reset () const;
bool is_object_safe () const;
@@ -301,6 +301,24 @@ public:
return false;
}
+ bool lookup_trait_item_by_type (const std::string &ident,
+ TraitItemReference::TraitItemType type,
+ const TraitItemReference **ref) const
+ {
+ for (auto &item : item_refs)
+ {
+ if (item.get_trait_item_type () != type)
+ continue;
+
+ if (ident.compare (item.get_identifier ()) == 0)
+ {
+ *ref = &item;
+ return true;
+ }
+ }
+ return false;
+ }
+
bool lookup_hir_trait_item (const HIR::TraitItem &item,
const TraitItemReference **ref) const
{
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index b4e0efe..5681ebd 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -128,7 +128,7 @@ TraitItemReference::resolve_item (HIR::TraitItemFunc &func)
}
void
-TraitItemReference::associated_type_set (TyTy::BaseType *ty)
+TraitItemReference::associated_type_set (TyTy::BaseType *ty) const
{
rust_assert (get_trait_item_type () == TraitItemType::TYPE);
@@ -141,7 +141,7 @@ TraitItemReference::associated_type_set (TyTy::BaseType *ty)
}
void
-TraitItemReference::associated_type_reset ()
+TraitItemReference::associated_type_reset () const
{
rust_assert (get_trait_item_type () == TraitItemType::TYPE);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
index f1b5e35..52c866c 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
@@ -385,9 +385,9 @@ class TypeCheckImplItemWithTrait : public TypeCheckImplItem
using Rust::Resolver::TypeCheckBase::visit;
public:
- static const TraitItemReference *
+ static TyTy::TypeBoundPredicateItem
Resolve (HIR::ImplBlock *parent, HIR::ImplItem *item, TyTy::BaseType *self,
- TraitReference &trait_reference,
+ TyTy::TypeBoundPredicate &trait_reference,
std::vector<TyTy::SubstitutionParamMapping> substitutions)
{
TypeCheckImplItemWithTrait resolver (parent, self, trait_reference,
@@ -398,38 +398,46 @@ public:
void visit (HIR::ConstantItem &constant) override
{
- trait_reference.lookup_trait_item_by_type (
+ // normal resolution of the item
+ TypeCheckImplItem::visit (constant);
+ TyTy::BaseType *lookup;
+ if (!context->lookup_type (constant.get_mappings ().get_hirid (), &lookup))
+ return;
+
+ // map the impl item to the associated trait item
+ const auto tref = trait_reference.get ();
+ const TraitItemReference *raw_trait_item = nullptr;
+ bool found = tref->lookup_trait_item_by_type (
constant.get_identifier (), TraitItemReference::TraitItemType::CONST,
- &resolved_trait_item);
+ &raw_trait_item);
// unknown trait item
- if (resolved_trait_item->is_error ())
+ if (!found || raw_trait_item->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;
}
- // normal resolution of the item
- TypeCheckImplItem::visit (constant);
- TyTy::BaseType *lookup;
- if (!context->lookup_type (constant.get_mappings ().get_hirid (), &lookup))
- return;
- if (resolved_trait_item->is_error ())
- return;
+ // get the item from the predicate
+ resolved_trait_item
+ = trait_reference.lookup_associated_item (raw_trait_item);
+ rust_assert (!resolved_trait_item.is_error ());
// merge the attributes
const HIR::TraitItem *hir_trait_item
- = resolved_trait_item->get_hir_trait_item ();
+ = resolved_trait_item.get_raw_item ()->get_hir_trait_item ();
merge_attributes (constant.get_outer_attrs (), *hir_trait_item);
// check the types are compatible
- if (!resolved_trait_item->get_tyty ()->can_eq (lookup, true))
+ auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self);
+ if (!trait_item_type->can_eq (lookup, true))
{
RichLocation r (constant.get_locus ());
- r.add_range (resolved_trait_item->get_locus ());
+ r.add_range (resolved_trait_item.get_locus ());
rust_error_at (
r, "constant %<%s%> has an incompatible type for trait %<%s%>",
@@ -440,38 +448,46 @@ public:
void visit (HIR::TypeAlias &type) override
{
- trait_reference.lookup_trait_item_by_type (
+ // normal resolution of the item
+ TypeCheckImplItem::visit (type);
+ TyTy::BaseType *lookup;
+ if (!context->lookup_type (type.get_mappings ().get_hirid (), &lookup))
+ return;
+
+ // map the impl item to the associated trait item
+ const auto tref = trait_reference.get ();
+ const TraitItemReference *raw_trait_item = nullptr;
+ bool found = tref->lookup_trait_item_by_type (
type.get_new_type_name (), TraitItemReference::TraitItemType::TYPE,
- &resolved_trait_item);
+ &raw_trait_item);
// unknown trait item
- if (resolved_trait_item->is_error ())
+ if (!found || raw_trait_item->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;
}
- // normal resolution of the item
- TypeCheckImplItem::visit (type);
- TyTy::BaseType *lookup;
- if (!context->lookup_type (type.get_mappings ().get_hirid (), &lookup))
- return;
- if (resolved_trait_item->is_error ())
- return;
+ // get the item from the predicate
+ resolved_trait_item
+ = trait_reference.lookup_associated_item (raw_trait_item);
+ rust_assert (!resolved_trait_item.is_error ());
// merge the attributes
const HIR::TraitItem *hir_trait_item
- = resolved_trait_item->get_hir_trait_item ();
+ = resolved_trait_item.get_raw_item ()->get_hir_trait_item ();
merge_attributes (type.get_outer_attrs (), *hir_trait_item);
// check the types are compatible
- if (!resolved_trait_item->get_tyty ()->can_eq (lookup, true))
+ auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self);
+ if (!trait_item_type->can_eq (lookup, true))
{
RichLocation r (type.get_locus ());
- r.add_range (resolved_trait_item->get_locus ());
+ r.add_range (resolved_trait_item.get_locus ());
rust_error_at (
r, "type alias %<%s%> has an incompatible type for trait %<%s%>",
@@ -481,83 +497,63 @@ public:
// its actually a projection, since we need a way to actually bind the
// generic substitutions to the type itself
- TyTy::ProjectionType *projection = new TyTy::ProjectionType (
- type.get_mappings ().get_hirid (), lookup, &trait_reference,
- resolved_trait_item->get_mappings ().get_defid (), substitutions);
+ TyTy::ProjectionType *projection
+ = new TyTy::ProjectionType (type.get_mappings ().get_hirid (), lookup,
+ tref,
+ raw_trait_item->get_mappings ().get_defid (),
+ substitutions);
context->insert_type (type.get_mappings (), projection);
- resolved_trait_item->associated_type_set (projection);
+ raw_trait_item->associated_type_set (projection);
}
void visit (HIR::Function &function) override
{
- // resolved_trait_item = trait_reference.lookup_trait_item (
- // function.get_function_name (), TraitItemReference::TraitItemType::FN);
- trait_reference.lookup_trait_item_by_type (
- function.get_function_name (), TraitItemReference::TraitItemType::FN,
- &resolved_trait_item);
+ // we get the error checking from the base method here
+ TypeCheckImplItem::visit (function);
+ TyTy::BaseType *lookup;
+ if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup))
+ return;
+
+ // map the impl item to the associated trait item
+ const auto tref = trait_reference.get ();
+ const TraitItemReference *raw_trait_item = nullptr;
+ bool found
+ = tref->lookup_trait_item_by_type (function.get_function_name (),
+ TraitItemReference::TraitItemType::FN,
+ &raw_trait_item);
// unknown trait item
- if (resolved_trait_item->is_error ())
+ if (!found || raw_trait_item->is_error ())
{
RichLocation r (function.get_locus ());
r.add_range (trait_reference.get_locus ());
rust_error_at (r, "method %<%s%> is not a member of trait %<%s%>",
function.get_function_name ().c_str (),
trait_reference.get_name ().c_str ());
+ return;
}
- // we get the error checking from the base method here
- TypeCheckImplItem::visit (function);
- TyTy::BaseType *lookup;
- if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup))
- return;
- if (resolved_trait_item->is_error ())
- return;
+ // get the item from the predicate
+ resolved_trait_item
+ = trait_reference.lookup_associated_item (raw_trait_item);
+ rust_assert (!resolved_trait_item.is_error ());
// merge the attributes
const HIR::TraitItem *hir_trait_item
- = resolved_trait_item->get_hir_trait_item ();
+ = resolved_trait_item.get_raw_item ()->get_hir_trait_item ();
merge_attributes (function.get_outer_attrs (), *hir_trait_item);
- rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
- rust_assert (resolved_trait_item->get_tyty ()->get_kind ()
- == TyTy::TypeKind::FNDEF);
-
- TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup);
- TyTy::FnType *trait_item_fntype
- = static_cast<TyTy::FnType *> (resolved_trait_item->get_tyty ());
-
- // sets substitute self into the trait_item_ref->tyty
- TyTy::SubstitutionParamMapping *self_mapping = nullptr;
- for (auto &param_mapping : trait_item_fntype->get_substs ())
- {
- const HIR::TypeParam &type_param = param_mapping.get_generic_param ();
- if (type_param.get_type_representation ().compare ("Self") == 0)
- {
- self_mapping = &param_mapping;
- break;
- }
- }
- rust_assert (self_mapping != nullptr);
-
- std::vector<TyTy::SubstitutionArg> mappings;
- mappings.push_back (TyTy::SubstitutionArg (self_mapping, self));
-
- TyTy::SubstitutionArgumentMappings implicit_self_substs (
- mappings, function.get_locus ());
- trait_item_fntype
- = trait_item_fntype->handle_substitions (implicit_self_substs);
-
// check the types are compatible
- if (!trait_item_fntype->can_eq (fntype, true))
+ auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self);
+ if (!trait_item_type->can_eq (lookup, true))
{
RichLocation r (function.get_locus ());
- r.add_range (resolved_trait_item->get_locus ());
+ r.add_range (resolved_trait_item.get_locus ());
rust_error_at (
r, "method %<%s%> has an incompatible type for trait %<%s%>",
- fntype->get_identifier ().c_str (),
+ function.get_function_name ().c_str (),
trait_reference.get_name ().c_str ());
}
}
@@ -577,10 +573,10 @@ protected:
private:
TypeCheckImplItemWithTrait (
HIR::ImplBlock *parent, TyTy::BaseType *self,
- TraitReference &trait_reference,
+ TyTy::TypeBoundPredicate &trait_reference,
std::vector<TyTy::SubstitutionParamMapping> substitutions)
: TypeCheckImplItem (parent, self), trait_reference (trait_reference),
- resolved_trait_item (&TraitItemReference::error_node ()),
+ resolved_trait_item (TyTy::TypeBoundPredicateItem::error ()),
substitutions (substitutions)
{
rust_assert (is_trait_impl_block ());
@@ -588,8 +584,8 @@ private:
bool is_trait_impl_block () const { return !trait_reference.is_error (); }
- TraitReference &trait_reference;
- TraitItemReference *resolved_trait_item;
+ TyTy::TypeBoundPredicate &trait_reference;
+ TyTy::TypeBoundPredicateItem resolved_trait_item;
std::vector<TyTy::SubstitutionParamMapping> substitutions;
};
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h
index 9846ed6..9d3beae 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.h
@@ -78,9 +78,9 @@ public:
trait_reference = TraitResolver::Resolve (*ref.get ());
rust_assert (!trait_reference->is_error ());
+ // we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
+ // for example
specified_bound = get_predicate_from_bound (*ref.get ());
- // FIXME error out maybe?
- // if specified_Bound == TyTy::TypeBoundPredicate::error() ?
}
TyTy::BaseType *self = nullptr;
@@ -120,9 +120,9 @@ public:
auto trait_item_ref
= TypeCheckImplItemWithTrait::Resolve (&impl_block,
impl_item.get (), self,
- *trait_reference,
+ specified_bound,
substitutions);
- trait_item_refs.push_back (trait_item_ref);
+ trait_item_refs.push_back (trait_item_ref.get_raw_item ());
}
}
@@ -134,7 +134,7 @@ public:
// filter the missing impl_items
std::vector<std::reference_wrapper<const TraitItemReference>>
missing_trait_items;
- for (auto &trait_item_ref : trait_reference->get_trait_items ())
+ for (const auto &trait_item_ref : trait_reference->get_trait_items ())
{
bool found = false;
for (auto implemented_trait_item : trait_item_refs)
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index e63f8ad..8e33783 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -211,8 +211,8 @@ public:
void clear_associated_type_mapping (HirId id)
{
auto it = associated_type_mappings.find (id);
- rust_assert (it != associated_type_mappings.end ());
- associated_type_mappings.erase (it);
+ if (it != associated_type_mappings.end ())
+ associated_type_mappings.erase (it);
}
// lookup any associated type mappings, the out parameter of mapping is
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h
index e12432e..028e10c 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -208,7 +208,14 @@ public:
void visit (TyTy::PlaceholderType &type) override
{
rust_assert (type.can_resolve ());
- resolved = SubstMapperInternal::Resolve (type.resolve (), mappings);
+ if (mappings.trait_item_mode ())
+ {
+ resolved = type.resolve ();
+ }
+ else
+ {
+ resolved = SubstMapperInternal::Resolve (type.resolve (), mappings);
+ }
}
void visit (TyTy::ProjectionType &type) override
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index e226400..bda7a7f 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -103,23 +103,28 @@ namespace TyTy {
TypeBoundPredicate::TypeBoundPredicate (
const Resolver::TraitReference &trait_reference, Location locus)
- : SubstitutionRef (trait_reference.get_trait_substs (),
- SubstitutionArgumentMappings::error ()),
+ : SubstitutionRef ({}, SubstitutionArgumentMappings::error ()),
reference (trait_reference.get_mappings ().get_defid ()), locus (locus),
error_flag (false)
{
+ substitutions.clear ();
+ for (const auto &p : trait_reference.get_trait_substs ())
+ substitutions.push_back (p.clone ());
+
// we setup a dummy implict self argument
SubstitutionArg placeholder_self (&get_substs ().front (), nullptr);
used_arguments.get_mappings ().push_back (placeholder_self);
}
TypeBoundPredicate::TypeBoundPredicate (
- DefId reference, std::vector<SubstitutionParamMapping> substitutions,
- Location locus)
- : SubstitutionRef (std::move (substitutions),
- SubstitutionArgumentMappings::error ()),
+ DefId reference, std::vector<SubstitutionParamMapping> subst, Location locus)
+ : SubstitutionRef ({}, SubstitutionArgumentMappings::error ()),
reference (reference), locus (locus), error_flag (false)
{
+ substitutions.clear ();
+ for (const auto &p : subst)
+ substitutions.push_back (p.clone ());
+
// we setup a dummy implict self argument
SubstitutionArg placeholder_self (&get_substs ().front (), nullptr);
used_arguments.get_mappings ().push_back (placeholder_self);
@@ -131,7 +136,6 @@ TypeBoundPredicate::TypeBoundPredicate (const TypeBoundPredicate &other)
error_flag (other.error_flag)
{
substitutions.clear ();
-
for (const auto &p : other.get_substs ())
substitutions.push_back (p.clone ());
@@ -143,8 +147,19 @@ TypeBoundPredicate::TypeBoundPredicate (const TypeBoundPredicate &other)
mappings.push_back (std::move (arg));
}
+ // we need to remap the argument mappings based on this copied constructor
+ std::vector<SubstitutionArg> copied_arg_mappings;
+ size_t i = 0;
+ for (const auto &m : other.used_arguments.get_mappings ())
+ {
+ TyTy::BaseType *argument
+ = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone ();
+ SubstitutionArg c (&substitutions.at (i++), argument);
+ copied_arg_mappings.push_back (std::move (c));
+ }
+
used_arguments
- = SubstitutionArgumentMappings (mappings,
+ = SubstitutionArgumentMappings (copied_arg_mappings,
other.used_arguments.get_locus ());
}
@@ -168,8 +183,19 @@ TypeBoundPredicate::operator= (const TypeBoundPredicate &other)
mappings.push_back (std::move (arg));
}
+ // we need to remap the argument mappings based on this copied constructor
+ std::vector<SubstitutionArg> copied_arg_mappings;
+ size_t i = 0;
+ for (const auto &m : other.used_arguments.get_mappings ())
+ {
+ TyTy::BaseType *argument
+ = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone ();
+ SubstitutionArg c (&substitutions.at (i++), argument);
+ copied_arg_mappings.push_back (std::move (c));
+ }
+
used_arguments
- = SubstitutionArgumentMappings (mappings,
+ = SubstitutionArgumentMappings (copied_arg_mappings,
other.used_arguments.get_locus ());
return *this;
@@ -204,16 +230,7 @@ TypeBoundPredicate::get () const
std::string
TypeBoundPredicate::get_name () const
{
- auto mappings = Analysis::Mappings::get ();
- auto trait = get ();
- auto nodeid = trait->get_mappings ().get_nodeid ();
-
- const Resolver::CanonicalPath *p = nullptr;
- if (mappings->lookup_canonical_path (mappings->get_current_crate (), nodeid,
- &p))
- return p->get ();
-
- return trait->get_name ();
+ return get ()->get_name ();
}
bool
@@ -285,15 +302,28 @@ TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver)
if (is_associated_type)
return trait_item_tyty;
- SubstitutionArgumentMappings gargs = parent->get_substitution_arguments ();
-
// set up the self mapping
+ SubstitutionArgumentMappings gargs = parent->get_substitution_arguments ();
rust_assert (!gargs.is_empty ());
- auto &sarg = gargs.get_mappings ().at (0);
- SubstitutionArg self (sarg.get_param_mapping (), receiver->clone ());
- gargs.get_mappings ()[0] = self;
- return Resolver::SubstMapperInternal::Resolve (trait_item_tyty, gargs);
+ // setup the adjusted mappings
+ std::vector<SubstitutionArg> adjusted_mappings;
+ for (size_t i = 0; i < gargs.get_mappings ().size (); i++)
+ {
+ auto &mapping = gargs.get_mappings ().at (i);
+
+ bool is_implicit_self = i == 0;
+ TyTy::BaseType *argument
+ = is_implicit_self ? receiver->clone () : mapping.get_tyty ();
+
+ SubstitutionArg arg (mapping.get_param_mapping (), argument);
+ adjusted_mappings.push_back (std::move (arg));
+ }
+
+ SubstitutionArgumentMappings adjusted (adjusted_mappings, gargs.get_locus (),
+ gargs.get_subst_cb (),
+ true /* trait-mode-flag */);
+ return Resolver::SubstMapperInternal::Resolve (trait_item_tyty, adjusted);
}
bool
TypeBoundPredicate::is_error () const
@@ -352,6 +382,12 @@ TypeBoundPredicateItem::needs_implementation () const
return !get_raw_item ()->is_optional ();
}
+Location
+TypeBoundPredicateItem::get_locus () const
+{
+ return get_raw_item ()->get_locus ();
+}
+
// TypeBoundsMappings
TypeBoundsMappings::TypeBoundsMappings (
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 156cc10..d9a4243 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -480,7 +480,7 @@ SubstitutionParamMapping::fill_param_ty (
if (type.get_kind () == TypeKind::PARAM)
{
- delete param;
+ // delete param;
param = static_cast<ParamType *> (type.clone ());
}
else
@@ -643,8 +643,9 @@ SubstitutionRef::adjust_mappings_for_this (
if (resolved_mappings.empty ())
return SubstitutionArgumentMappings::error ();
- return SubstitutionArgumentMappings (resolved_mappings,
- mappings.get_locus ());
+ return SubstitutionArgumentMappings (resolved_mappings, mappings.get_locus (),
+ mappings.get_subst_cb (),
+ mappings.trait_item_mode ());
}
bool
@@ -2699,6 +2700,13 @@ ProjectionType::clone () const
ProjectionType *
ProjectionType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
{
+ // // do we really need to substitute this?
+ // if (base->needs_generic_substitutions () || base->contains_type_parameters
+ // ())
+ // {
+ // return this;
+ // }
+
ProjectionType *projection = static_cast<ProjectionType *> (clone ());
projection->set_ty_ref (mappings->get_next_hir_id ());
projection->used_arguments = subst_mappings;
@@ -2755,9 +2763,7 @@ ProjectionType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
return nullptr;
}
- auto new_field = concrete->clone ();
- new_field->set_ref (fty->get_ref ());
- projection->base = new_field;
+ projection->base = concrete;
}
return projection;
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 17ba655..1f157c8 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -101,6 +101,8 @@ public:
const TypeBoundPredicate *get_parent () const { return parent; }
+ Location get_locus () const;
+
private:
const TypeBoundPredicate *parent;
const Resolver::TraitItemReference *trait_item_ref;
@@ -661,13 +663,16 @@ class SubstitutionArgumentMappings
public:
SubstitutionArgumentMappings (std::vector<SubstitutionArg> mappings,
Location locus,
- ParamSubstCb param_subst_cb = nullptr)
- : mappings (mappings), locus (locus), param_subst_cb (param_subst_cb)
+ ParamSubstCb param_subst_cb = nullptr,
+ bool trait_item_flag = false)
+ : mappings (mappings), locus (locus), param_subst_cb (param_subst_cb),
+ trait_item_flag (trait_item_flag)
{}
SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other)
: mappings (other.mappings), locus (other.locus),
- param_subst_cb (other.param_subst_cb)
+ param_subst_cb (other.param_subst_cb),
+ trait_item_flag (other.trait_item_flag)
{}
SubstitutionArgumentMappings &
@@ -676,13 +681,14 @@ public:
mappings = other.mappings;
locus = other.locus;
param_subst_cb = other.param_subst_cb;
+ trait_item_flag = other.trait_item_flag;
return *this;
}
static SubstitutionArgumentMappings error ()
{
- return SubstitutionArgumentMappings ({}, Location (), nullptr);
+ return SubstitutionArgumentMappings ({}, Location (), nullptr, false);
}
bool is_error () const { return mappings.size () == 0; }
@@ -754,10 +760,15 @@ public:
param_subst_cb (p, a);
}
+ ParamSubstCb get_subst_cb () const { return param_subst_cb; }
+
+ bool trait_item_mode () const { return trait_item_flag; }
+
private:
std::vector<SubstitutionArg> mappings;
Location locus;
ParamSubstCb param_subst_cb;
+ bool trait_item_flag;
};
class SubstitutionRef
@@ -2296,8 +2307,9 @@ private:
class ProjectionType : public BaseType, public SubstitutionRef
{
public:
- ProjectionType (HirId ref, BaseType *base, Resolver::TraitReference *trait,
- DefId item, std::vector<SubstitutionParamMapping> subst_refs,
+ ProjectionType (HirId ref, BaseType *base,
+ const Resolver::TraitReference *trait, DefId item,
+ std::vector<SubstitutionParamMapping> subst_refs,
SubstitutionArgumentMappings generic_arguments
= SubstitutionArgumentMappings::error (),
std::set<HirId> refs = std::set<HirId> ())
@@ -2310,7 +2322,7 @@ public:
{}
ProjectionType (HirId ref, HirId ty_ref, BaseType *base,
- Resolver::TraitReference *trait, DefId item,
+ const Resolver::TraitReference *trait, DefId item,
std::vector<SubstitutionParamMapping> subst_refs,
SubstitutionArgumentMappings generic_arguments
= SubstitutionArgumentMappings::error (),
@@ -2361,7 +2373,7 @@ public:
private:
BaseType *base;
- Resolver::TraitReference *trait;
+ const Resolver::TraitReference *trait;
DefId item;
};
diff --git a/gcc/testsuite/rust/compile/traits9.rs b/gcc/testsuite/rust/compile/traits9.rs
index 8d81bae..e1aef539 100644
--- a/gcc/testsuite/rust/compile/traits9.rs
+++ b/gcc/testsuite/rust/compile/traits9.rs
@@ -1,4 +1,3 @@
-// { dg-additional-options -frust-crate=example }
struct Foo(i32);
trait Bar {
fn baz(&self);
@@ -9,6 +8,6 @@ fn main() {
a = Foo(123);
let b: &dyn Bar = &a;
- // { dg-error "bounds not satisfied for Foo .example::Bar. is not satisfied" "" { target *-*-* } .-1 }
+ // { dg-error "bounds not satisfied for Foo .Bar. is not satisfied" "" { target *-*-* } .-1 }
// { dg-error "expected" "" { target *-*-* } .-2 }
}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1120.rs b/gcc/testsuite/rust/execute/torture/issue-1120.rs
new file mode 100644
index 0000000..ecbc6b2
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1120.rs
@@ -0,0 +1,123 @@
+// { dg-additional-options "-w" }
+extern "rust-intrinsic" {
+ pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+struct FatPtr<T> {
+ data: *const T,
+ len: usize,
+}
+
+pub union Repr<T> {
+ rust: *const [T],
+ rust_mut: *mut [T],
+ raw: FatPtr<T>,
+}
+
+pub enum Option<T> {
+ None,
+ Some(T),
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+ pub start: Idx,
+ pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+ pub const fn len(self) -> usize {
+ let a = unsafe { Repr { rust: self }.raw };
+ a.len
+ }
+
+ pub const fn as_ptr(self) -> *const T {
+ self as *const T
+ }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+ pub const unsafe fn offset(self, count: isize) -> *const T {
+ unsafe { offset(self, count) }
+ }
+
+ pub const unsafe fn add(self, count: usize) -> Self {
+ unsafe { self.offset(count as isize) }
+ }
+
+ pub const fn as_ptr(self) -> *const T {
+ self as *const T
+ }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+ unsafe {
+ Repr {
+ raw: FatPtr { data, len },
+ }
+ .rust
+ }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+ type Output;
+
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<T> {
+ type Output;
+
+ fn get(self, slice: &T) -> Option<&Self::Output>;
+
+ unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+ fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+ type Output = [T];
+
+ fn get(self, slice: &[T]) -> Option<&[T]> {
+ if self.start > self.end
+ /* || self.end > slice.len() */
+ {
+ Option::None
+ } else {
+ unsafe { Option::Some(&*self.get_unchecked(slice)) }
+ }
+ }
+
+ unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+ unsafe {
+ let a: *const T = slice.as_ptr();
+ let b: *const T = a.add(self.start);
+ slice_from_raw_parts(b, self.end - self.start)
+ }
+ }
+
+ fn index(self, slice: &[T]) -> &[T] {
+ unsafe { &*self.get_unchecked(slice) }
+ }
+}
+
+impl<T, I> Index<I> for [T]
+where
+ I: SliceIndex<[T]>,
+{
+ type Output = I::Output;
+
+ fn index(&self, index: I) -> &I::Output {
+ index.index(self)
+ }
+}
+
+fn main() -> i32 {
+ let a = [1, 2, 3, 4, 5];
+ let b = &a[1..3];
+
+ 0
+}