Skip to content

Commit 601bbf2

Browse files
Start of implementation of proposal for E0308
1 parent 94ae2a2 commit 601bbf2

File tree

2 files changed

+78
-2
lines changed

2 files changed

+78
-2
lines changed

src/librustc/infer/error_reporting.rs

+77-2
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ use hir::def_id::DefId;
8383
use infer;
8484
use middle::region;
8585
use traits::{ObligationCause, ObligationCauseCode};
86-
use ty::{self, TyCtxt, TypeFoldable};
86+
use ty::{self, ImplOrTraitItem, Ty, TyCtxt, TypeFoldable};
8787
use ty::{Region, ReFree};
8888
use ty::error::TypeError;
8989

@@ -549,7 +549,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
549549
{
550550
let expected_found = match values {
551551
None => None,
552-
Some(values) => match self.values_str(&values) {
552+
Some(ref values) => match self.values_str(&values) {
553553
Some((expected, found)) => Some((expected, found)),
554554
None => {
555555
// Derived error. Cancel the emitter.
@@ -582,6 +582,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
582582
diag.note_expected_found(&"type", &expected, &found);
583583
}
584584
}
585+
586+
if let Some((found, (expected_ty, _))) = self.get_ids(values) {
587+
// look for expected with found id
588+
self.tcx.populate_inherent_implementations_for_type_if_necessary(found);
589+
if let Some(impl_infos) = self.tcx.inherent_impls.borrow().get(&found) {
590+
let mut methods = Vec::new();
591+
for impl_ in impl_infos {
592+
methods.append(&mut self.tcx
593+
.impl_or_trait_items(*impl_)
594+
.iter()
595+
.map(|&did| self.tcx.impl_or_trait_item(did))
596+
.filter(|x| {
597+
self.matches_return_type(x, &expected_ty)
598+
})
599+
.collect());
600+
}
601+
for method in methods {
602+
println!("==> {:?}", method.name());
603+
}
604+
}
605+
}
585606
}
586607

587608
diag.span_label(span, &terr);
@@ -622,6 +643,60 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
622643
}
623644
}
624645

646+
fn matches_return_type(&self, method: &ImplOrTraitItem<'tcx>, expected: &ty::Ty<'tcx>) -> bool {
647+
match *method {
648+
ImplOrTraitItem::MethodTraitItem(ref x) => {
649+
self.can_sub_types(x.fty.sig.skip_binder().output, expected).is_ok()
650+
}
651+
_ => false,
652+
}
653+
}
654+
655+
fn get_id(&self, ty: Ty<'tcx>) -> Option<DefId> {
656+
match ty.sty {
657+
ty::TyTrait(box ref data) => Some(data.principal.def_id()),
658+
ty::TyAdt(def, _) => Some(def.did),
659+
ty::TyBox(ref ty) => self.get_id(*ty), // since we don't want box's methods by type's
660+
ty::TyChar => self.tcx.lang_items.char_impl(),
661+
ty::TyStr => self.tcx.lang_items.str_impl(),
662+
ty::TySlice(_) => self.tcx.lang_items.slice_impl(),
663+
ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
664+
self.tcx.lang_items.const_ptr_impl()
665+
}
666+
ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
667+
self.tcx.lang_items.mut_ptr_impl()
668+
}
669+
ty::TyInt(ast::IntTy::I8) => self.tcx.lang_items.i8_impl(),
670+
ty::TyInt(ast::IntTy::I16) => self.tcx.lang_items.i16_impl(),
671+
ty::TyInt(ast::IntTy::I32) => self.tcx.lang_items.i32_impl(),
672+
ty::TyInt(ast::IntTy::I64) => self.tcx.lang_items.i64_impl(),
673+
ty::TyInt(ast::IntTy::Is) => self.tcx.lang_items.isize_impl(),
674+
ty::TyUint(ast::UintTy::U8) => self.tcx.lang_items.u8_impl(),
675+
ty::TyUint(ast::UintTy::U16) => self.tcx.lang_items.u16_impl(),
676+
ty::TyUint(ast::UintTy::U32) => self.tcx.lang_items.u32_impl(),
677+
ty::TyUint(ast::UintTy::U64) => self.tcx.lang_items.u64_impl(),
678+
ty::TyUint(ast::UintTy::Us) => self.tcx.lang_items.usize_impl(),
679+
ty::TyFloat(ast::FloatTy::F32) => self.tcx.lang_items.f32_impl(),
680+
ty::TyFloat(ast::FloatTy::F64) => self.tcx.lang_items.f64_impl(),
681+
_ => None,
682+
}
683+
}
684+
685+
// Yep, returned value super ugly. it'll certainly become `Option<(DefId, ty::Ty<'tcx>)>`
686+
// in a close future. Or maybe a struct?
687+
fn get_ids(&self, values: Option<ValuePairs<'tcx>>) -> Option<(DefId, (ty::Ty<'tcx>, DefId))> {
688+
match values {
689+
// for now, only handling non trait types
690+
Some(infer::Types(ref exp_found)) => {
691+
match (self.get_id(exp_found.found), self.get_id(exp_found.expected)) {
692+
(Some(found), Some(expected)) => Some((found, (exp_found.expected, expected))),
693+
_ => None,
694+
}
695+
}
696+
_ => None,
697+
}
698+
}
699+
625700
fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
626701
&self,
627702
exp_found: &ty::error::ExpectedFound<T>)

src/librustc/ty/sty.rs

+1
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@ pub struct ProjectionTy<'tcx> {
543543
pub struct BareFnTy<'tcx> {
544544
pub unsafety: hir::Unsafety,
545545
pub abi: abi::Abi,
546+
/// Signature (inputs and output) of this function type.
546547
pub sig: PolyFnSig<'tcx>,
547548
}
548549

0 commit comments

Comments
 (0)