const TyTy::TypeBoundPredicate p (*trait_ref, BoundPolarity::RegularBound,
UNDEF_LOCATION);
- TyTy::TypeBoundPredicateItem item (&p, trait_item_ref);
+ TyTy::TypeBoundPredicateItem item (p, trait_item_ref);
TyTy::BaseType *trait_item_tyty = item.get_raw_item ()->get_tyty ();
if (receiver->get_kind () != TyTy::DYNAMIC)
TraitReference::TraitReference (
const HIR::Trait *hir_trait_ref, std::vector<TraitItemReference> item_refs,
- std::vector<const TraitReference *> super_traits,
+ std::vector<TyTy::TypeBoundPredicate> super_traits,
std::vector<TyTy::SubstitutionParamMapping> substs)
: hir_trait_ref (hir_trait_ref), item_refs (item_refs),
super_traits (super_traits)
bool
TraitReference::lookup_trait_item (const std::string &ident,
- const TraitItemReference **ref) const
+ const TraitItemReference **ref,
+ bool lookup_supers) const
{
for (auto &item : item_refs)
{
}
}
+ if (!lookup_supers)
+ return false;
+
// lookup super traits
for (const auto &super_trait : super_traits)
{
- bool found = super_trait->lookup_trait_item (ident, ref);
+ bool found = super_trait.get ()->lookup_trait_item (ident, ref);
if (found)
return true;
}
for (const auto &super_trait : super_traits)
{
const TraitItemReference *res
- = super_trait->lookup_trait_item (ident, type);
+ = super_trait.get ()->lookup_trait_item (ident, type);
if (!res->is_error ())
return res;
}
result.push_back (&item);
for (const auto &super_trait : super_traits)
- super_trait->get_trait_items_and_supers (result);
+ super_trait.get ()->get_trait_items_and_supers (result);
}
void
return this_id == other_id;
}
-const std::vector<const TraitReference *>
+std::vector<TyTy::TypeBoundPredicate>
TraitReference::get_super_traits () const
{
return super_traits;
{
// https: // doc.rust-lang.org/reference/items/traits.html#object-safety
std::vector<const TraitReference *> non_object_super_traits;
- for (auto &item : super_traits)
+ for (auto &super_trait : super_traits)
{
- if (!item->is_object_safe (false, UNDEF_LOCATION))
- non_object_super_traits.push_back (item);
+ if (!super_trait.get ()->is_object_safe (false, UNDEF_LOCATION))
+ non_object_super_traits.push_back (super_trait.get ());
}
std::vector<const Resolver::TraitItemReference *> non_object_safe_items;
for (const auto &super_trait : super_traits)
{
- if (super_trait->satisfies_bound (reference))
+ if (super_trait.get ()->satisfies_bound (reference))
return true;
}
public:
TraitReference (const HIR::Trait *hir_trait_ref,
std::vector<TraitItemReference> item_refs,
- std::vector<const TraitReference *> super_traits,
+ std::vector<TyTy::TypeBoundPredicate> super_traits,
std::vector<TyTy::SubstitutionParamMapping> substs);
TraitReference (TraitReference const &other);
const TraitItemReference **ref) const;
bool lookup_trait_item (const std::string &ident,
- const TraitItemReference **ref) const;
+ const TraitItemReference **ref,
+ bool lookup_supers = true) const;
const TraitItemReference *
lookup_trait_item (const std::string &ident,
bool is_equal (const TraitReference &other) const;
- const std::vector<const TraitReference *> get_super_traits () const;
+ std::vector<TyTy::TypeBoundPredicate> get_super_traits () const;
bool is_object_safe (bool emit_error, location_t locus) const;
private:
const HIR::Trait *hir_trait_ref;
std::vector<TraitItemReference> item_refs;
- std::vector<const TraitReference *> super_traits;
+ std::vector<TyTy::TypeBoundPredicate> super_traits;
std::vector<TyTy::SubstitutionParamMapping> trait_substs;
};
specified_bounds.push_back (self_hrtb);
// look for any
- std::vector<const TraitReference *> super_traits;
+ std::vector<TyTy::TypeBoundPredicate> super_traits;
if (trait_reference->has_type_param_bounds ())
{
for (auto &bound : trait_reference->get_type_param_bounds ())
return &TraitReference::error_node ();
specified_bounds.push_back (predicate);
- super_traits.push_back (predicate.get ());
+ super_traits.push_back (predicate);
}
}
}
item_refs.push_back (std::move (trait_item_ref));
}
- TraitReference trait_object (trait_reference, item_refs,
- std::move (super_traits),
+ TraitReference trait_object (trait_reference, item_refs, super_traits,
std::move (substitutions));
context->insert_trait_reference (
trait_reference->get_mappings ().get_defid (), std::move (trait_object));
location_t locus)
: SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
reference (trait_reference.get_mappings ().get_defid ()), locus (locus),
- error_flag (false), polarity (polarity)
+ error_flag (false), polarity (polarity),
+ super_traits (trait_reference.get_super_traits ())
{
rust_assert (!trait_reference.get_trait_substs ().empty ());
TypeBoundPredicate::TypeBoundPredicate (const TypeBoundPredicate &other)
: SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
reference (other.reference), locus (other.locus),
- error_flag (other.error_flag), polarity (other.polarity)
+ error_flag (other.error_flag), polarity (other.polarity),
+ super_traits (other.super_traits)
{
substitutions.clear ();
for (const auto &p : other.get_substs ())
= SubstitutionArgumentMappings (copied_arg_mappings, {},
other.used_arguments.get_regions (),
other.used_arguments.get_locus ());
+ super_traits = other.super_traits;
return *this;
}
}
// now actually perform a substitution
- used_arguments = get_mappings_from_generic_args (
+ auto args = get_mappings_from_generic_args (
*generic_args,
Resolver::TypeCheckContext::get ()->regions_from_generic_args (
*generic_args));
+ apply_argument_mappings (args);
+}
+
+void
+TypeBoundPredicate::apply_argument_mappings (
+ SubstitutionArgumentMappings &arguments)
+{
+ used_arguments = arguments;
error_flag |= used_arguments.is_error ();
auto &subst_mappings = used_arguments;
for (auto &sub : get_substs ())
const auto item_ref = item.get_raw_item ();
item_ref->associated_type_set (type);
}
+
+ for (auto &super_trait : super_traits)
+ {
+ auto adjusted
+ = super_trait.adjust_mappings_for_this (used_arguments,
+ true /*trait mode*/);
+ super_trait.apply_argument_mappings (adjusted);
+ }
}
bool
{
auto trait_ref = get ();
const Resolver::TraitItemReference *trait_item_ref = nullptr;
- if (!trait_ref->lookup_trait_item (search, &trait_item_ref))
- return TypeBoundPredicateItem::error ();
+ if (trait_ref->lookup_trait_item (search, &trait_item_ref,
+ false /*lookup supers*/))
+ return TypeBoundPredicateItem (*this, trait_item_ref);
+
+ for (auto &super_trait : super_traits)
+ {
+ auto lookup = super_trait.lookup_associated_item (search);
+ if (!lookup.is_error ())
+ return lookup;
+ }
- return TypeBoundPredicateItem (this, trait_item_ref);
+ return TypeBoundPredicateItem::error ();
}
TypeBoundPredicateItem::TypeBoundPredicateItem (
- const TypeBoundPredicate *parent,
+ const TypeBoundPredicate parent,
const Resolver::TraitItemReference *trait_item_ref)
: parent (parent), trait_item_ref (trait_item_ref)
{}
+TypeBoundPredicateItem::TypeBoundPredicateItem (
+ const TypeBoundPredicateItem &other)
+ : parent (other.parent), trait_item_ref (other.trait_item_ref)
+{}
+
+TypeBoundPredicateItem &
+TypeBoundPredicateItem::operator= (const TypeBoundPredicateItem &other)
+{
+ parent = other.parent;
+ trait_item_ref = other.trait_item_ref;
+
+ return *this;
+}
+
TypeBoundPredicateItem
TypeBoundPredicateItem::error ()
{
- return TypeBoundPredicateItem (nullptr, nullptr);
+ return TypeBoundPredicateItem (TypeBoundPredicate::error (), nullptr);
}
bool
TypeBoundPredicateItem::is_error () const
{
- return parent == nullptr || trait_item_ref == nullptr;
+ return parent.is_error () || trait_item_ref == nullptr;
}
const TypeBoundPredicate *
TypeBoundPredicateItem::get_parent () const
{
- return parent;
+ return &parent;
}
TypeBoundPredicateItem
TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver)
{
TyTy::BaseType *trait_item_tyty = get_raw_item ()->get_tyty ();
- if (parent->get_substitution_arguments ().is_empty ())
+ if (parent.get_substitution_arguments ().is_empty ())
return trait_item_tyty;
const Resolver::TraitItemReference *tref = get_raw_item ();
return trait_item_tyty;
// set up the self mapping
- SubstitutionArgumentMappings gargs = parent->get_substitution_arguments ();
+ SubstitutionArgumentMappings gargs = parent.get_substitution_arguments ();
rust_assert (!gargs.is_empty ());
// setup the adjusted mappings
== Resolver::TraitItemReference::TraitItemType::TYPE;
if (is_associated_type)
{
- TypeBoundPredicateItem item (this, &trait_item);
+ TypeBoundPredicateItem item (*this, &trait_item);
items.push_back (std::move (item));
}
}
class BaseType;
class TypeBoundPredicate;
-class TypeBoundPredicateItem
-{
-public:
- TypeBoundPredicateItem (const TypeBoundPredicate *parent,
- const Resolver::TraitItemReference *trait_item_ref);
-
- static TypeBoundPredicateItem error ();
-
- bool is_error () const;
-
- BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver);
-
- const Resolver::TraitItemReference *get_raw_item () const;
-
- bool needs_implementation () const;
-
- const TypeBoundPredicate *get_parent () const;
-
- location_t get_locus () const;
-
-private:
- const TypeBoundPredicate *parent;
- const Resolver::TraitItemReference *trait_item_ref;
-};
-
class TypeBoundsMappings
{
protected:
SubstitutionArgumentMappings
SubstitutionRef::adjust_mappings_for_this (
- SubstitutionArgumentMappings &mappings)
+ SubstitutionArgumentMappings &mappings, bool trait_mode)
{
std::vector<SubstitutionArg> resolved_mappings;
for (size_t i = 0; i < substitutions.size (); i++)
}
bool ok = !arg.is_error ();
- if (ok)
+ if (ok || (trait_mode && i == 0))
{
SubstitutionArg adjusted (&subst, arg.get_tyty ());
resolved_mappings.push_back (std::move (adjusted));
bool error_flag;
};
+class TypeBoundPredicateItem;
class SubstitutionRef
{
public:
// we have bindings for X Y Z and need to propagate the binding Y,Z into Foo
// Which binds to A,B
SubstitutionArgumentMappings
- adjust_mappings_for_this (SubstitutionArgumentMappings &mappings);
+ adjust_mappings_for_this (SubstitutionArgumentMappings &mappings,
+ bool trait_mode = false);
// Are the mappings here actually bound to this type. For example imagine the
// case:
void apply_generic_arguments (HIR::GenericArgs *generic_args,
bool has_associated_self);
+ void apply_argument_mappings (SubstitutionArgumentMappings &arguments);
+
bool contains_item (const std::string &search) const;
TypeBoundPredicateItem
location_t locus;
bool error_flag;
BoundPolarity polarity;
+ std::vector<TyTy::TypeBoundPredicate> super_traits;
+};
+
+class TypeBoundPredicateItem
+{
+public:
+ TypeBoundPredicateItem (const TypeBoundPredicate parent,
+ const Resolver::TraitItemReference *trait_item_ref);
+
+ TypeBoundPredicateItem (const TypeBoundPredicateItem &other);
+
+ TypeBoundPredicateItem &operator= (const TypeBoundPredicateItem &other);
+
+ static TypeBoundPredicateItem error ();
+
+ bool is_error () const;
+
+ BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver);
+
+ const Resolver::TraitItemReference *get_raw_item () const;
+
+ bool needs_implementation () const;
+
+ const TypeBoundPredicate *get_parent () const;
+
+ location_t get_locus () const;
+
+private:
+ TypeBoundPredicate parent;
+ const Resolver::TraitItemReference *trait_item_ref;
};
// https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.VariantDef.html
--- /dev/null
+/* { dg-output "parent 123\r*\nchild\r*\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "sized"]
+pub trait Sized {}
+
+struct Foo {
+ my_int: u32,
+ // { dg-warning "field is never read: .my_int." "" { target *-*-* } .-1 }
+}
+
+trait Parent<T> {
+ fn parent(&self) -> T;
+}
+
+trait Child: Parent<u32> {
+ fn child(&self);
+}
+
+impl Parent<u32> for Foo {
+ fn parent(&self) -> u32 {
+ unsafe {
+ let parent = "parent %u\n\0";
+ let msg = parent as *const str;
+ printf(msg as *const i8, self.my_int);
+ return self.my_int;
+ }
+ }
+}
+
+impl Child for Foo {
+ fn child(&self) {
+ let _ = self;
+ unsafe {
+ let child = "child\n\0";
+ let msg = child as *const str;
+ printf(msg as *const i8);
+ }
+ }
+}
+
+pub fn main() -> i32 {
+ let a = Foo { my_int: 123 };
+ let b: &dyn Child = &a;
+
+ b.parent();
+ b.child();
+
+ 0
+}