}
}
- bool have_implementation_for_lang_item = resolved_candidates.size () > 0;
+ auto selected_candidates
+ = MethodResolver::Select (resolved_candidates, lhs, {});
+ bool have_implementation_for_lang_item = selected_candidates.size () > 0;
if (!have_implementation_for_lang_item)
return false;
- if (resolved_candidates.size () > 1)
+ if (selected_candidates.size () > 1)
{
// no need to error out as we are just trying to see if there is a fit
return false;
}
// Get the adjusted self
- MethodCandidate candidate = *resolved_candidates.begin ();
+ MethodCandidate candidate = *selected_candidates.begin ();
Adjuster adj (lhs);
TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
return resolver.result;
}
+std::set<MethodCandidate>
+MethodResolver::Select (std::set<MethodCandidate> &candidates,
+ TyTy::BaseType *receiver,
+ std::vector<TyTy::BaseType *> arguments)
+{
+ std::set<MethodCandidate> selected;
+ for (auto &candidate : candidates)
+ {
+ TyTy::BaseType *candidate_type = candidate.candidate.ty;
+ rust_assert (candidate_type->get_kind () == TyTy::TypeKind::FNDEF);
+ TyTy::FnType &fn = *static_cast<TyTy::FnType *> (candidate_type);
+
+ // match the number of arguments
+ if (fn.num_params () != (arguments.size () + 1))
+ continue;
+
+ // match the arguments
+ bool failed = false;
+ for (size_t i = 0; i < arguments.size (); i++)
+ {
+ TyTy::BaseType *arg = arguments.at (i);
+ TyTy::BaseType *param = fn.get_params ().at (i + 1).second;
+ TyTy::BaseType *coerced
+ = try_coercion (0, TyTy::TyWithLocation (param),
+ TyTy::TyWithLocation (arg), Location ());
+ if (coerced->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ failed = true;
+ break;
+ }
+ }
+
+ if (!failed)
+ selected.insert (candidate);
+ }
+
+ return selected;
+}
+
void
MethodResolver::try_hook (const TyTy::BaseType &r)
{
Probe (TyTy::BaseType *receiver, const HIR::PathIdentSegment &segment_name,
bool autoderef_flag = false);
+ static std::set<MethodCandidate>
+ Select (std::set<MethodCandidate> &candidates, TyTy::BaseType *receiver,
+ std::vector<TyTy::BaseType *> arguments);
+
static std::vector<predicate_candidate> get_predicate_items (
const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver,
const std::vector<TyTy::TypeBoundPredicate> &specified_bounds);
}
}
- bool have_implementation_for_lang_item = resolved_candidates.size () > 0;
+ std::vector<TyTy::BaseType *> select_args = {};
+ if (rhs != nullptr)
+ select_args = {rhs};
+ auto selected_candidates
+ = MethodResolver::Select (resolved_candidates, lhs, select_args);
+
+ bool have_implementation_for_lang_item = selected_candidates.size () > 0;
if (!have_implementation_for_lang_item)
return false;
- if (resolved_candidates.size () > 1)
+ if (selected_candidates.size () > 1)
{
// mutliple candidates
RichLocation r (expr.get_locus ());
}
// Get the adjusted self
- MethodCandidate candidate = *resolved_candidates.begin ();
+ MethodCandidate candidate = *selected_candidates.begin ();
Adjuster adj (lhs);
TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
return coerced;
}
+TyTy::BaseType *
+try_coercion (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
+ Location locus)
+{
+ TyTy::BaseType *expected = lhs.get_ty ();
+ TyTy::BaseType *expr = rhs.get_ty ();
+
+ rust_debug ("try_coercion_site id={%u} expected={%s} expr={%s}", id,
+ expected->debug_str ().c_str (), expr->debug_str ().c_str ());
+
+ auto result = TypeCoercionRules::TryCoerce (expr, expected, locus,
+ true /*allow-autodref*/);
+ if (result.is_error ())
+ return new TyTy::ErrorType (id);
+
+ return result.tyty;
+}
+
TyTy::BaseType *
cast_site (HirId id, TyTy::TyWithLocation from, TyTy::TyWithLocation to,
Location cast_locus)
coercion_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
Location coercion_locus);
+TyTy::BaseType *
+try_coercion (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
+ Location coercion_locus);
+
TyTy::BaseType *
cast_site (HirId id, TyTy::TyWithLocation from, TyTy::TyWithLocation to,
Location cast_locus);
--- /dev/null
+#[lang = "add"]
+pub trait Add<RHS = Self> {
+ type Output;
+
+ fn add(self, rhs: RHS) -> Self::Output;
+}
+macro_rules! add_impl {
+ ($($t:ty)*) => ($(
+ impl Add for $t {
+ type Output = $t;
+
+ fn add(self, other: $t) -> $t { self + other }
+ }
+ )*)
+}
+
+add_impl! { usize u8 u16 u32 u64 /*isize i8 i16 i32 i64*/ f32 f64 }
+
+pub fn test() {
+ let x: usize = 123;
+ let mut i = 0;
+ let _bug = i + x;
+}