@@ -343,14 +343,26 @@ TraitReference::on_resolved ()
}
void
-TraitReference::clear_associated_types ()
+TraitReference::clear_associated_types () const
{
- for (auto &item : item_refs)
+ for (const auto &item : item_refs)
+ {
+ bool is_assoc_type = item.get_trait_item_type ()
+ == TraitItemReference::TraitItemType::TYPE;
+ if (is_assoc_type)
+ item.associated_type_reset (false);
+ }
+}
+
+void
+TraitReference::clear_associated_type_projections () const
+{
+ for (const auto &item : item_refs)
{
bool is_assoc_type = item.get_trait_item_type ()
== TraitItemReference::TraitItemType::TYPE;
if (is_assoc_type)
- item.associated_type_reset ();
+ item.associated_type_reset (true);
}
}
@@ -106,7 +106,7 @@ public:
void associated_type_set (TyTy::BaseType *ty) const;
- void associated_type_reset () const;
+ void associated_type_reset (bool only_projections) const;
bool is_object_safe () const;
@@ -212,7 +212,9 @@ public:
void on_resolved ();
- void clear_associated_types ();
+ void clear_associated_types () const;
+
+ void clear_associated_type_projections () const;
bool is_equal (const TraitReference &other) const;
@@ -161,6 +161,9 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
TraitQueryGuard guard (trait_id);
TyTy::BaseType *self = nullptr;
std::vector<TyTy::SubstitutionParamMapping> substitutions;
+
+ // FIXME
+ // this should use the resolve_generic_params like everywhere else
for (auto &generic_param : trait_reference->get_generic_params ())
{
switch (generic_param.get ()->get_kind ())
@@ -182,7 +185,11 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
if (typaram.get_type_representation ().compare ("Self") == 0)
{
- self = param_type;
+ rust_assert (param_type->get_kind () == TyTy::TypeKind::PARAM);
+ TyTy::ParamType *p
+ = static_cast<TyTy::ParamType *> (param_type);
+ p->set_implicit_self_trait ();
+ self = p;
}
}
break;
@@ -365,7 +372,7 @@ TraitItemReference::associated_type_set (TyTy::BaseType *ty) const
}
void
-TraitItemReference::associated_type_reset () const
+TraitItemReference::associated_type_reset (bool only_projections) const
{
rust_assert (get_trait_item_type () == TraitItemType::TYPE);
@@ -374,7 +381,21 @@ TraitItemReference::associated_type_reset () const
TyTy::PlaceholderType *placeholder
= static_cast<TyTy::PlaceholderType *> (item_ty);
- placeholder->clear_associated_type ();
+ if (!only_projections)
+ {
+ placeholder->clear_associated_type ();
+ }
+ else
+ {
+ if (!placeholder->can_resolve ())
+ return;
+
+ const TyTy::BaseType *r = placeholder->resolve ();
+ if (r->get_kind () == TyTy::TypeKind::PROJECTION)
+ {
+ placeholder->clear_associated_type ();
+ }
+ }
}
TyTy::BaseType *
@@ -30,42 +30,18 @@ class TypeBoundsProbe : public TypeCheckBase
{
public:
static std::vector<std::pair<TraitReference *, HIR::ImplBlock *>>
- Probe (const TyTy::BaseType *receiver)
- {
- TypeBoundsProbe probe (receiver);
- probe.scan ();
- return probe.trait_references;
- }
+ Probe (const TyTy::BaseType *receiver);
static bool is_bound_satisfied_for_type (TyTy::BaseType *receiver,
- TraitReference *ref)
- {
- for (auto &bound : receiver->get_specified_bounds ())
- {
- const TraitReference *b = bound.get ();
- if (b->is_equal (*ref))
- return true;
- }
-
- std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> bounds
- = Probe (receiver);
- for (auto &bound : bounds)
- {
- const TraitReference *b = bound.first;
- if (b->is_equal (*ref))
- return true;
- }
-
- return false;
- }
+ TraitReference *ref);
private:
void scan ();
+ void assemble_sized_builtin ();
+ void assemble_builtin_candidate (Analysis::RustLangItem::ItemType item);
private:
- TypeBoundsProbe (const TyTy::BaseType *receiver)
- : TypeCheckBase (), receiver (receiver)
- {}
+ TypeBoundsProbe (const TyTy::BaseType *receiver);
const TyTy::BaseType *receiver;
std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> trait_references;
@@ -1095,6 +1095,7 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
return;
}
+ fn->prepare_higher_ranked_bounds ();
auto root = receiver_tyty->get_root ();
if (root->get_kind () == TyTy::TypeKind::ADT)
{
@@ -1659,6 +1660,11 @@ TypeCheckExpr::resolve_operator_overload (
TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
rust_assert (fn->is_method ());
+ fn->prepare_higher_ranked_bounds ();
+ rust_debug_loc (expr.get_locus (), "resolved operator overload to: {%u} {%s}",
+ candidate.candidate.ty->get_ref (),
+ candidate.candidate.ty->debug_str ().c_str ());
+
auto root = lhs->get_root ();
if (root->get_kind () == TyTy::TypeKind::ADT)
{
@@ -23,6 +23,41 @@
namespace Rust {
namespace Resolver {
+TypeBoundsProbe::TypeBoundsProbe (const TyTy::BaseType *receiver)
+ : TypeCheckBase (), receiver (receiver)
+{}
+
+std::vector<std::pair<TraitReference *, HIR::ImplBlock *>>
+TypeBoundsProbe::Probe (const TyTy::BaseType *receiver)
+{
+ TypeBoundsProbe probe (receiver);
+ probe.scan ();
+ return probe.trait_references;
+}
+
+bool
+TypeBoundsProbe::is_bound_satisfied_for_type (TyTy::BaseType *receiver,
+ TraitReference *ref)
+{
+ for (auto &bound : receiver->get_specified_bounds ())
+ {
+ const TraitReference *b = bound.get ();
+ if (b->is_equal (*ref))
+ return true;
+ }
+
+ std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> bounds
+ = Probe (receiver);
+ for (auto &bound : bounds)
+ {
+ const TraitReference *b = bound.first;
+ if (b->is_equal (*ref))
+ return true;
+ }
+
+ return false;
+}
+
void
TypeBoundsProbe::scan ()
{
@@ -57,6 +92,75 @@ TypeBoundsProbe::scan ()
if (!trait_ref->is_error ())
trait_references.push_back ({trait_ref, path.second});
}
+
+ // marker traits...
+ assemble_sized_builtin ();
+}
+
+void
+TypeBoundsProbe::assemble_sized_builtin ()
+{
+ const TyTy::BaseType *raw = receiver->destructure ();
+
+ // does this thing actually implement sized?
+ switch (raw->get_kind ())
+ {
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::FLOAT:
+ case TyTy::USIZE:
+ case TyTy::ISIZE:
+ assemble_builtin_candidate (Analysis::RustLangItem::SIZED);
+ break;
+
+ // not-sure about this.... FIXME
+ case TyTy::INFER:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ break;
+ }
+}
+
+void
+TypeBoundsProbe::assemble_builtin_candidate (
+ Analysis::RustLangItem::ItemType lang_item)
+{
+ DefId id;
+ bool found_lang_item = mappings->lookup_lang_item (lang_item, &id);
+ if (!found_lang_item)
+ return;
+
+ HIR::Item *item = mappings->lookup_defid (id);
+ if (item == nullptr)
+ return;
+
+ rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait);
+ HIR::Trait *trait = static_cast<HIR::Trait *> (item);
+ const TyTy::BaseType *raw = receiver->destructure ();
+
+ // assemble the reference
+ TraitReference *trait_ref = TraitResolver::Resolve (*trait);
+ trait_references.push_back ({trait_ref, mappings->lookup_builtin_marker ()});
+
+ rust_debug ("Added builtin lang_item: %s for %s",
+ Analysis::RustLangItem::ToString (lang_item).c_str (),
+ raw->get_name ().c_str ());
}
TraitReference *
@@ -101,7 +205,8 @@ TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path)
= static_cast<HIR::TypePathSegmentFunction *> (final_seg.get ());
auto &fn = final_function_seg->get_function_path ();
- // we need to make implicit generic args which must be an implicit Tuple
+ // we need to make implicit generic args which must be an implicit
+ // Tuple
auto crate_num = mappings->get_current_crate ();
HirId implicit_args_id = mappings->get_next_hir_id ();
Analysis::NodeMapping mapping (crate_num,
@@ -514,8 +619,8 @@ TypeBoundPredicate::lookup_associated_type (const std::string &search)
{
TypeBoundPredicateItem item = lookup_associated_item (search);
- // only need to check that it is infact an associated type because other wise
- // if it was not found it will just be an error node anyway
+ // only need to check that it is infact an associated type because other
+ // wise if it was not found it will just be an error node anyway
if (!item.is_error ())
{
const auto raw = item.get_raw_item ();
@@ -119,11 +119,6 @@ SubstitutionParamMapping::fill_param_ty (
{
type.inherit_bounds (*param);
}
- else
- {
- if (!param->bounds_compatible (type, locus, true))
- return false;
- }
if (type.get_kind () == TypeKind::PARAM)
{
@@ -133,8 +128,15 @@ SubstitutionParamMapping::fill_param_ty (
else
{
// check the substitution is compatible with bounds
- if (!param->bounds_compatible (type, locus, true))
- return false;
+ rust_debug_loc (locus,
+ "fill_param_ty bounds_compatible: param %s type %s",
+ param->get_name ().c_str (), type.get_name ().c_str ());
+
+ if (!param->is_implicit_self_trait ())
+ {
+ if (!param->bounds_compatible (type, locus, true))
+ return false;
+ }
// recursively pass this down to all HRTB's
for (auto &bound : param->get_specified_bounds ())
@@ -870,10 +872,149 @@ SubstitutionRef::solve_missing_mappings_from_this (SubstitutionRef &ref,
return SubstitutionArgumentMappings (resolved_mappings, {}, locus);
}
+Resolver::AssociatedImplTrait *
+SubstitutionRef::lookup_associated_impl (const SubstitutionParamMapping &subst,
+ const TypeBoundPredicate &bound,
+ const TyTy::BaseType *binding,
+ bool *error_flag) const
+{
+ auto context = Resolver::TypeCheckContext::get ();
+ const Resolver::TraitReference *specified_bound_ref = bound.get ();
+
+ // setup any associated type mappings for the specified bonds and this
+ // type
+ auto candidates = Resolver::TypeBoundsProbe::Probe (binding);
+ std::vector<Resolver::AssociatedImplTrait *> associated_impl_traits;
+ for (auto &probed_bound : candidates)
+ {
+ const Resolver::TraitReference *bound_trait_ref = probed_bound.first;
+ const HIR::ImplBlock *associated_impl = probed_bound.second;
+
+ HirId impl_block_id = associated_impl->get_mappings ().get_hirid ();
+ Resolver::AssociatedImplTrait *associated = nullptr;
+ bool found_impl_trait
+ = context->lookup_associated_trait_impl (impl_block_id, &associated);
+ if (found_impl_trait)
+ {
+ bool found_trait = specified_bound_ref->is_equal (*bound_trait_ref);
+ bool found_self = associated->get_self ()->can_eq (binding, false);
+ if (found_trait && found_self)
+ {
+ associated_impl_traits.push_back (associated);
+ }
+ }
+ }
+
+ if (associated_impl_traits.empty ())
+ return nullptr;
+
+ // This code is important when you look at slices for example when
+ // you have a slice such as:
+ //
+ // let slice = &array[1..3]
+ //
+ // the higher ranked bounds will end up having an Index trait
+ // implementation for Range<usize> so we need this code to resolve
+ // that we have an integer inference variable that needs to become
+ // a usize
+ //
+ // The other complicated issue is that we might have an intrinsic
+ // which requires the :Clone or Copy bound but the libcore adds
+ // implementations for all the integral types so when there are
+ // multiple candidates we need to resolve to the default
+ // implementation for that type otherwise its an error for
+ // ambiguous type bounds
+
+ // if we have a non-general inference variable we need to be
+ // careful about the selection here
+ bool is_infer_var = binding->get_kind () == TyTy::TypeKind::INFER;
+ bool is_integer_infervar
+ = is_infer_var
+ && static_cast<const TyTy::InferType *> (binding)->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::INTEGRAL;
+ bool is_float_infervar
+ = is_infer_var
+ && static_cast<const TyTy::InferType *> (binding)->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::FLOAT;
+
+ Resolver::AssociatedImplTrait *associate_impl_trait = nullptr;
+ if (associated_impl_traits.size () == 1)
+ {
+ // just go for it
+ associate_impl_trait = associated_impl_traits.at (0);
+ }
+ else if (is_integer_infervar)
+ {
+ TyTy::BaseType *type = nullptr;
+ bool ok = context->lookup_builtin ("i32", &type);
+ rust_assert (ok);
+
+ for (auto &impl : associated_impl_traits)
+ {
+ bool found = impl->get_self ()->is_equal (*type);
+ if (found)
+ {
+ associate_impl_trait = impl;
+ break;
+ }
+ }
+ }
+ else if (is_float_infervar)
+ {
+ TyTy::BaseType *type = nullptr;
+ bool ok = context->lookup_builtin ("f64", &type);
+ rust_assert (ok);
+
+ for (auto &impl : associated_impl_traits)
+ {
+ bool found = impl->get_self ()->is_equal (*type);
+ if (found)
+ {
+ associate_impl_trait = impl;
+ break;
+ }
+ }
+ }
+
+ if (associate_impl_trait == nullptr)
+ {
+ // go for the first one? or error out?
+ auto &mappings = *Analysis::Mappings::get ();
+ const auto &type_param = subst.get_generic_param ();
+ const auto *trait_ref = bound.get ();
+
+ RichLocation r (type_param.get_locus ());
+ r.add_range (bound.get_locus ());
+ r.add_range (mappings.lookup_location (binding->get_ref ()));
+
+ rust_error_at (r, "ambiguous type bound for trait %s and type %s",
+ trait_ref->get_name ().c_str (),
+ binding->get_name ().c_str ());
+
+ *error_flag = true;
+ return nullptr;
+ }
+
+ return associate_impl_trait;
+}
+
+void
+SubstitutionRef::prepare_higher_ranked_bounds ()
+{
+ for (const auto &subst : get_substs ())
+ {
+ const TyTy::ParamType *pty = subst.get_param_ty ();
+ for (const auto &bound : pty->get_specified_bounds ())
+ {
+ const auto ref = bound.get ();
+ ref->clear_associated_type_projections ();
+ }
+ }
+}
+
bool
SubstitutionRef::monomorphize ()
{
- auto context = Resolver::TypeCheckContext::get ();
for (const auto &subst : get_substs ())
{
const TyTy::ParamType *pty = subst.get_param_ty ();
@@ -887,136 +1028,16 @@ SubstitutionRef::monomorphize ()
for (const auto &bound : pty->get_specified_bounds ())
{
- const Resolver::TraitReference *specified_bound_ref = bound.get ();
-
- // setup any associated type mappings for the specified bonds and this
- // type
- auto candidates = Resolver::TypeBoundsProbe::Probe (binding);
- std::vector<Resolver::AssociatedImplTrait *> associated_impl_traits;
- for (auto &probed_bound : candidates)
+ bool error_flag = false;
+ auto associated
+ = lookup_associated_impl (subst, bound, binding, &error_flag);
+ if (associated != nullptr)
{
- const Resolver::TraitReference *bound_trait_ref
- = probed_bound.first;
- const HIR::ImplBlock *associated_impl = probed_bound.second;
-
- HirId impl_block_id
- = associated_impl->get_mappings ().get_hirid ();
- Resolver::AssociatedImplTrait *associated = nullptr;
- bool found_impl_trait
- = context->lookup_associated_trait_impl (impl_block_id,
- &associated);
- if (found_impl_trait)
- {
- bool found_trait
- = specified_bound_ref->is_equal (*bound_trait_ref);
- bool found_self
- = associated->get_self ()->can_eq (binding, false);
- if (found_trait && found_self)
- {
- associated_impl_traits.push_back (associated);
- }
- }
+ associated->setup_associated_types (binding, bound);
}
- if (!associated_impl_traits.empty ())
- {
- // This code is important when you look at slices for example when
- // you have a slice such as:
- //
- // let slice = &array[1..3]
- //
- // the higher ranked bounds will end up having an Index trait
- // implementation for Range<usize> so we need this code to resolve
- // that we have an integer inference variable that needs to become
- // a usize
- //
- // The other complicated issue is that we might have an intrinsic
- // which requires the :Clone or Copy bound but the libcore adds
- // implementations for all the integral types so when there are
- // multiple candidates we need to resolve to the default
- // implementation for that type otherwise its an error for
- // ambiguous type bounds
-
- if (associated_impl_traits.size () == 1)
- {
- Resolver::AssociatedImplTrait *associate_impl_trait
- = associated_impl_traits.at (0);
- associate_impl_trait->setup_associated_types (binding, bound);
- }
- else
- {
- // if we have a non-general inference variable we need to be
- // careful about the selection here
- bool is_infer_var
- = binding->get_kind () == TyTy::TypeKind::INFER;
- bool is_integer_infervar
- = is_infer_var
- && static_cast<const TyTy::InferType *> (binding)
- ->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::INTEGRAL;
- bool is_float_infervar
- = is_infer_var
- && static_cast<const TyTy::InferType *> (binding)
- ->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::FLOAT;
-
- Resolver::AssociatedImplTrait *associate_impl_trait = nullptr;
- if (is_integer_infervar)
- {
- TyTy::BaseType *type = nullptr;
- bool ok = context->lookup_builtin ("i32", &type);
- rust_assert (ok);
-
- for (auto &impl : associated_impl_traits)
- {
- bool found = impl->get_self ()->is_equal (*type);
- if (found)
- {
- associate_impl_trait = impl;
- break;
- }
- }
- }
- else if (is_float_infervar)
- {
- TyTy::BaseType *type = nullptr;
- bool ok = context->lookup_builtin ("f64", &type);
- rust_assert (ok);
-
- for (auto &impl : associated_impl_traits)
- {
- bool found = impl->get_self ()->is_equal (*type);
- if (found)
- {
- associate_impl_trait = impl;
- break;
- }
- }
- }
-
- if (associate_impl_trait == nullptr)
- {
- // go for the first one? or error out?
- auto &mappings = *Analysis::Mappings::get ();
- const auto &type_param = subst.get_generic_param ();
- const auto *trait_ref = bound.get ();
-
- RichLocation r (type_param.get_locus ());
- r.add_range (bound.get_locus ());
- r.add_range (
- mappings.lookup_location (binding->get_ref ()));
-
- rust_error_at (
- r, "ambiguous type bound for trait %s and type %s",
- trait_ref->get_name ().c_str (),
- binding->get_name ().c_str ());
-
- return false;
- }
-
- associate_impl_trait->setup_associated_types (binding, bound);
- }
- }
+ if (error_flag)
+ return false;
}
}
@@ -298,7 +298,13 @@ public:
// TODO comment
BaseType *infer_substitions (Location locus);
- // TODO comment
+ // this clears any possible projections from higher ranked trait bounds which
+ // could be hanging around from a previous resolution
+ void prepare_higher_ranked_bounds ();
+
+ // FIXME
+ // this is bad name for this, i think it should be something like
+ // compute-higher-ranked-bounds
bool monomorphize ();
// TODO comment
@@ -308,6 +314,10 @@ public:
SubstitutionArgumentMappings get_used_arguments () const;
protected:
+ Resolver::AssociatedImplTrait *lookup_associated_impl (
+ const SubstitutionParamMapping &subst, const TypeBoundPredicate &bound,
+ const TyTy::BaseType *binding, bool *error_flag) const;
+
std::vector<SubstitutionParamMapping> substitutions;
SubstitutionArgumentMappings used_arguments;
};
@@ -31,6 +31,7 @@
#include "rust-hir-type-bounds.h"
#include "rust-hir-trait-resolve.h"
#include "rust-tyty-cmp.h"
+#include "rust-type-util.h"
#include "options.h"
@@ -266,6 +267,7 @@ BaseType::get_locus () const
return ident.locus;
}
+// FIXME this is missing locus
bool
BaseType::satisfies_bound (const TypeBoundPredicate &predicate) const
{
@@ -277,12 +279,67 @@ BaseType::satisfies_bound (const TypeBoundPredicate &predicate) const
return true;
}
+ bool satisfied = false;
auto probed = Resolver::TypeBoundsProbe::Probe (this);
for (const auto &b : probed)
{
const Resolver::TraitReference *bound = b.first;
if (bound->satisfies_bound (*query))
+ {
+ satisfied = true;
+ break;
+ }
+ }
+
+ if (!satisfied)
+ return false;
+
+ for (const auto &b : probed)
+ {
+ const Resolver::TraitReference *bound = b.first;
+ if (!bound->is_equal (*query))
+ continue;
+
+ // builtin ones have no impl-block this needs fixed and use a builtin node
+ // of somekind
+ if (b.second == nullptr)
return true;
+
+ // need to check that associated types can match as well
+ const HIR::ImplBlock &impl = *(b.second);
+ for (const auto &item : impl.get_impl_items ())
+ {
+ TyTy::BaseType *impl_item_ty = nullptr;
+ Analysis::NodeMapping i = item->get_impl_mappings ();
+ bool query_ok = Resolver::query_type (i.get_hirid (), &impl_item_ty);
+ if (!query_ok)
+ return false;
+
+ std::string item_name = item->get_impl_item_name ();
+ TypeBoundPredicateItem lookup
+ = predicate.lookup_associated_item (item_name);
+ if (lookup.is_error ())
+ return false;
+
+ const auto *item_ref = lookup.get_raw_item ();
+ TyTy::BaseType *bound_ty = item_ref->get_tyty ();
+
+ // compare the types
+ if (!bound_ty->can_eq (impl_item_ty, false))
+ {
+ RichLocation r (mappings->lookup_location (get_ref ()));
+ r.add_range (predicate.get_locus ());
+ r.add_range (mappings->lookup_location (i.get_hirid ()));
+
+ rust_error_at (
+ r, "expected %<%s%> got %<%s%>",
+ bound_ty->destructure ()->get_name ().c_str (),
+ impl_item_ty->destructure ()->get_name ().c_str ());
+ return false;
+ }
+ }
+
+ return true;
}
return false;
@@ -2827,18 +2884,18 @@ ParamType::ParamType (std::string symbol, Location locus, HirId ref,
{Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
locus},
specified_bounds, refs),
- symbol (symbol), param (param)
+ is_trait_self (false), symbol (symbol), param (param)
{}
-ParamType::ParamType (std::string symbol, Location locus, HirId ref,
- HirId ty_ref, HIR::GenericParam ¶m,
+ParamType::ParamType (bool is_trait_self, std::string symbol, Location locus,
+ HirId ref, HirId ty_ref, HIR::GenericParam ¶m,
std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs)
: BaseType (ref, ty_ref, TypeKind::PARAM,
{Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
locus},
specified_bounds, refs),
- symbol (symbol), param (param)
+ is_trait_self (is_trait_self), symbol (symbol), param (param)
{}
HIR::GenericParam &
@@ -2906,8 +2963,9 @@ ParamType::can_eq (const BaseType *other, bool emit_errors) const
BaseType *
ParamType::clone () const
{
- return new ParamType (get_symbol (), ident.locus, get_ref (), get_ty_ref (),
- param, get_specified_bounds (), get_combined_refs ());
+ return new ParamType (is_trait_self, get_symbol (), ident.locus, get_ref (),
+ get_ty_ref (), param, get_specified_bounds (),
+ get_combined_refs ());
}
BaseType *
@@ -2997,6 +3055,18 @@ ParamType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
return p;
}
+void
+ParamType::set_implicit_self_trait ()
+{
+ is_trait_self = true;
+}
+
+bool
+ParamType::is_implicit_self_trait () const
+{
+ return is_trait_self;
+}
+
// StrType
StrType::StrType (HirId ref, std::set<HirId> refs)
@@ -267,8 +267,8 @@ public:
std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs = std::set<HirId> ());
- ParamType (std::string symbol, Location locus, HirId ref, HirId ty_ref,
- HIR::GenericParam ¶m,
+ ParamType (bool is_trait_self, std::string symbol, Location locus, HirId ref,
+ HirId ty_ref, HIR::GenericParam ¶m,
std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs = std::set<HirId> ());
@@ -298,7 +298,11 @@ public:
ParamType *handle_substitions (SubstitutionArgumentMappings &mappings);
+ void set_implicit_self_trait ();
+ bool is_implicit_self_trait () const;
+
private:
+ bool is_trait_self;
std::string symbol;
HIR::GenericParam ¶m;
};
@@ -96,9 +96,16 @@ static const HirId kDefaultCrateNumBegin = 0;
Mappings::Mappings ()
: crateNumItr (kDefaultCrateNumBegin), currentCrateNum (UNKNOWN_CREATENUM),
hirIdIter (kDefaultHirIdBegin), nodeIdIter (kDefaultNodeIdBegin)
-{}
+{
+ Analysis::NodeMapping node (0, 0, 0, 0);
+ builtinMarker
+ = new HIR::ImplBlock (node, {}, {}, nullptr, nullptr, HIR::WhereClause ({}),
+ Positive,
+ HIR::Visibility (HIR::Visibility::VisType::PUBLIC),
+ {}, {}, Location ());
+}
-Mappings::~Mappings () {}
+Mappings::~Mappings () { delete builtinMarker; }
Mappings *
Mappings::get ()
@@ -1035,5 +1042,11 @@ Mappings::lookup_ast_item (NodeId id, AST::Item **result)
return true;
}
+HIR::ImplBlock *
+Mappings::lookup_builtin_marker ()
+{
+ return builtinMarker;
+}
+
} // namespace Analysis
} // namespace Rust
@@ -296,6 +296,8 @@ public:
void insert_ast_item (AST::Item *item);
bool lookup_ast_item (NodeId id, AST::Item **result);
+ HIR::ImplBlock *lookup_builtin_marker ();
+
private:
Mappings ();
@@ -304,6 +306,7 @@ private:
HirId hirIdIter;
NodeId nodeIdIter;
std::map<CrateNum, LocalDefId> localIdIter;
+ HIR::ImplBlock *builtinMarker;
std::map<NodeId, CrateNum> crate_node_to_crate_num;
std::map<CrateNum, AST::Crate *> ast_crate_mappings;
new file mode 100644
@@ -0,0 +1,19 @@
+mod core {
+ mod ops {
+ #[lang = "add"]
+ pub trait Add<Rhs = Self> {
+ type Output;
+
+ fn add(self, rhs: Rhs) -> Self::Output;
+ }
+ }
+}
+
+pub fn foo<T: core::ops::Add<Output = i32>>(a: T) -> i32 {
+ a + a
+}
+
+pub fn main() {
+ foo(123f32);
+ // { dg-error "bounds not satisfied for f32 .Add. is not satisfied" "" { target *-*-* } .-1 }
+}
new file mode 100644
@@ -0,0 +1,28 @@
+mod core {
+ mod ops {
+ #[lang = "add"]
+ pub trait Add<Rhs = Self> {
+ type Output;
+
+ fn add(self, rhs: Rhs) -> Self::Output;
+ }
+ }
+}
+
+impl core::ops::Add for f32 {
+ type Output = f32;
+
+ fn add(self, rhs: Self) -> Self::Output {
+ self + rhs
+ }
+}
+
+pub fn foo<T: core::ops::Add<Output = i32>>(a: T) -> i32 {
+ a + a
+}
+
+pub fn main() {
+ foo(123f32);
+ // { dg-error "expected .i32. got .f32." "" { target *-*-* } .-1 }
+ // { dg-error "bounds not satisfied for f32 .Add. is not satisfied" "" { target *-*-* } .-2 }
+}