Display secondary span for E0053 for Sort TypeErrors
This commit is contained in:
parent
7ac11cad3f
commit
3c4ecc9e7c
@ -569,6 +569,13 @@ impl<'ast> Map<'ast> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn expect_impl_item(&self, id: NodeId) -> &'ast ImplItem {
|
||||||
|
match self.find(id) {
|
||||||
|
Some(NodeImplItem(item)) => item,
|
||||||
|
_ => bug!("expected impl item, found {}", self.node_to_string(id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn expect_trait_item(&self, id: NodeId) -> &'ast TraitItem {
|
pub fn expect_trait_item(&self, id: NodeId) -> &'ast TraitItem {
|
||||||
match self.find(id) {
|
match self.find(id) {
|
||||||
Some(NodeTraitItem(item)) => item,
|
Some(NodeTraitItem(item)) => item,
|
||||||
|
@ -523,6 +523,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||||||
pub fn note_type_err(&self,
|
pub fn note_type_err(&self,
|
||||||
diag: &mut DiagnosticBuilder<'tcx>,
|
diag: &mut DiagnosticBuilder<'tcx>,
|
||||||
origin: TypeOrigin,
|
origin: TypeOrigin,
|
||||||
|
secondary_span: Option<(Span, String)>,
|
||||||
values: Option<ValuePairs<'tcx>>,
|
values: Option<ValuePairs<'tcx>>,
|
||||||
terr: &TypeError<'tcx>)
|
terr: &TypeError<'tcx>)
|
||||||
{
|
{
|
||||||
@ -553,6 +554,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
diag.span_label(span, &terr);
|
diag.span_label(span, &terr);
|
||||||
|
if let Some((sp, msg)) = secondary_span {
|
||||||
|
diag.span_label(sp, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
self.note_error_origin(diag, &origin);
|
self.note_error_origin(diag, &origin);
|
||||||
self.check_and_note_conflicting_crates(diag, terr, span);
|
self.check_and_note_conflicting_crates(diag, terr, span);
|
||||||
@ -569,7 +573,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||||||
self.tcx.sess, trace.origin.span(), E0308,
|
self.tcx.sess, trace.origin.span(), E0308,
|
||||||
"{}", trace.origin.as_failure_str()
|
"{}", trace.origin.as_failure_str()
|
||||||
);
|
);
|
||||||
self.note_type_err(&mut diag, trace.origin, Some(trace.values), terr);
|
self.note_type_err(&mut diag, trace.origin, None, Some(trace.values), terr);
|
||||||
diag
|
diag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||||||
self.tcx.sess, origin.span(), E0271,
|
self.tcx.sess, origin.span(), E0271,
|
||||||
"type mismatch resolving `{}`", predicate
|
"type mismatch resolving `{}`", predicate
|
||||||
);
|
);
|
||||||
self.note_type_err(&mut diag, origin, values, err);
|
self.note_type_err(&mut diag, origin, None, values, err);
|
||||||
self.note_obligation_cause(&mut diag, obligation);
|
self.note_obligation_cause(&mut diag, obligation);
|
||||||
diag.emit();
|
diag.emit();
|
||||||
});
|
});
|
||||||
|
@ -12,10 +12,9 @@ use middle::free_region::FreeRegionMap;
|
|||||||
use rustc::infer::{self, InferOk, TypeOrigin};
|
use rustc::infer::{self, InferOk, TypeOrigin};
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use rustc::traits::{self, Reveal};
|
use rustc::traits::{self, Reveal};
|
||||||
use rustc::ty::error::ExpectedFound;
|
use rustc::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc::ty::subst::{Subst, Substs};
|
use rustc::ty::subst::{Subst, Substs};
|
||||||
use rustc::hir::map::Node;
|
use rustc::hir::{ImplItemKind, TraitItem_, Ty_};
|
||||||
use rustc::hir::{ImplItemKind, TraitItem_};
|
|
||||||
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
@ -300,6 +299,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||||||
impl_m_span,
|
impl_m_span,
|
||||||
impl_m_body_id,
|
impl_m_body_id,
|
||||||
&impl_sig);
|
&impl_sig);
|
||||||
|
let impl_args = impl_sig.inputs.clone();
|
||||||
let impl_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
|
let impl_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
|
||||||
unsafety: impl_m.fty.unsafety,
|
unsafety: impl_m.fty.unsafety,
|
||||||
abi: impl_m.fty.abi,
|
abi: impl_m.fty.abi,
|
||||||
@ -318,6 +318,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||||||
impl_m_span,
|
impl_m_span,
|
||||||
impl_m_body_id,
|
impl_m_body_id,
|
||||||
&trait_sig);
|
&trait_sig);
|
||||||
|
let trait_args = trait_sig.inputs.clone();
|
||||||
let trait_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
|
let trait_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
|
||||||
unsafety: trait_m.fty.unsafety,
|
unsafety: trait_m.fty.unsafety,
|
||||||
abi: trait_m.fty.abi,
|
abi: trait_m.fty.abi,
|
||||||
@ -331,16 +332,54 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||||||
impl_fty,
|
impl_fty,
|
||||||
trait_fty);
|
trait_fty);
|
||||||
|
|
||||||
|
let impl_m_iter = match tcx.map.expect_impl_item(impl_m_node_id).node {
|
||||||
|
ImplItemKind::Method(ref impl_m_sig, _) => impl_m_sig.decl.inputs.iter(),
|
||||||
|
_ => bug!("{:?} is not a method", impl_m)
|
||||||
|
};
|
||||||
|
|
||||||
|
let (impl_err_span, trait_err_span) = match terr {
|
||||||
|
TypeError::Sorts(ExpectedFound { expected, found }) => {
|
||||||
|
if let Some(trait_m_node_id) = tcx.map.as_local_node_id(trait_m.def_id) {
|
||||||
|
let trait_m_iter = match tcx.map.expect_trait_item(trait_m_node_id).node {
|
||||||
|
TraitItem_::MethodTraitItem(ref trait_m_sig, _) =>
|
||||||
|
trait_m_sig.decl.inputs.iter(),
|
||||||
|
_ => bug!("{:?} is not a MethodTraitItem", trait_m)
|
||||||
|
};
|
||||||
|
let impl_iter = impl_args.iter();
|
||||||
|
let trait_iter = trait_args.iter();
|
||||||
|
let arg_idx = impl_iter.zip(trait_iter)
|
||||||
|
.position(|(impl_arg_ty, trait_arg_ty)| {
|
||||||
|
*impl_arg_ty == found && *trait_arg_ty == expected
|
||||||
|
}).unwrap();
|
||||||
|
impl_m_iter.zip(trait_m_iter)
|
||||||
|
.nth(arg_idx)
|
||||||
|
.map(|(impl_arg, trait_arg)|
|
||||||
|
(impl_arg.ty.span, Some(trait_arg.ty.span)))
|
||||||
|
.unwrap_or(
|
||||||
|
(origin.span(), tcx.map.span_if_local(trait_m.def_id)))
|
||||||
|
} else {
|
||||||
|
(origin.span(), tcx.map.span_if_local(trait_m.def_id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (origin.span(), tcx.map.span_if_local(trait_m.def_id))
|
||||||
|
};
|
||||||
|
|
||||||
|
let origin = TypeOrigin::MethodCompatCheck(impl_err_span);
|
||||||
|
|
||||||
let mut diag = struct_span_err!(
|
let mut diag = struct_span_err!(
|
||||||
tcx.sess, origin.span(), E0053,
|
tcx.sess, origin.span(), E0053,
|
||||||
"method `{}` has an incompatible type for trait", trait_m.name
|
"method `{}` has an incompatible type for trait", trait_m.name
|
||||||
);
|
);
|
||||||
|
|
||||||
infcx.note_type_err(
|
infcx.note_type_err(
|
||||||
&mut diag, origin,
|
&mut diag,
|
||||||
|
origin,
|
||||||
|
trait_err_span.map(|sp| (sp, format!("original trait requirement"))),
|
||||||
Some(infer::ValuePairs::Types(ExpectedFound {
|
Some(infer::ValuePairs::Types(ExpectedFound {
|
||||||
expected: trait_fty,
|
expected: trait_fty,
|
||||||
found: impl_fty
|
found: impl_fty
|
||||||
})), &terr
|
})),
|
||||||
|
&terr
|
||||||
);
|
);
|
||||||
diag.emit();
|
diag.emit();
|
||||||
return
|
return
|
||||||
@ -487,12 +526,9 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||||||
trait_ty);
|
trait_ty);
|
||||||
|
|
||||||
// Locate the Span containing just the type of the offending impl
|
// Locate the Span containing just the type of the offending impl
|
||||||
if let Some(impl_trait_node) = tcx.map.get_if_local(impl_c.def_id) {
|
match tcx.map.expect_impl_item(impl_c_node_id).node {
|
||||||
if let Node::NodeImplItem(impl_trait_item) = impl_trait_node {
|
ImplItemKind::Const(ref ty, _) => origin = TypeOrigin::Misc(ty.span),
|
||||||
if let ImplItemKind::Const(ref ty, _) = impl_trait_item.node {
|
_ => bug!("{:?} is not a impl const", impl_c)
|
||||||
origin = TypeOrigin::Misc(ty.span);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut diag = struct_span_err!(
|
let mut diag = struct_span_err!(
|
||||||
@ -502,16 +538,16 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Add a label to the Span containing just the type of the item
|
// Add a label to the Span containing just the type of the item
|
||||||
if let Some(orig_trait_node) = tcx.map.get_if_local(trait_c.def_id) {
|
let trait_c_node_id = tcx.map.as_local_node_id(trait_c.def_id).unwrap();
|
||||||
if let Node::NodeTraitItem(orig_trait_item) = orig_trait_node {
|
let trait_c_span = match tcx.map.expect_trait_item(trait_c_node_id).node {
|
||||||
if let TraitItem_::ConstTraitItem(ref ty, _) = orig_trait_item.node {
|
TraitItem_::ConstTraitItem(ref ty, _) => ty.span,
|
||||||
diag.span_label(ty.span, &format!("original trait requirement"));
|
_ => bug!("{:?} is not a trait const", trait_c)
|
||||||
}
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
infcx.note_type_err(
|
infcx.note_type_err(
|
||||||
&mut diag, origin,
|
&mut diag,
|
||||||
|
origin,
|
||||||
|
Some((trait_c_span, format!("original trait requirement"))),
|
||||||
Some(infer::ValuePairs::Types(ExpectedFound {
|
Some(infer::ValuePairs::Types(ExpectedFound {
|
||||||
expected: trait_ty,
|
expected: trait_ty,
|
||||||
found: impl_ty
|
found: impl_ty
|
||||||
|
Loading…
Reference in New Issue
Block a user