Skip to content

Commit

Permalink
On type errors, show closure signature
Browse files Browse the repository at this point in the history
Instead of refering to closures with their span, format their signature.
  • Loading branch information
estebank committed Dec 2, 2017
1 parent 9053fdd commit 541cfb4
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 37 deletions.
9 changes: 7 additions & 2 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1440,8 +1440,13 @@ pub struct Ty {

impl fmt::Debug for Ty {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "type({})",
print::to_string(print::NO_ANN, |s| s.print_type(self)))
write!(f, "type({})", print::to_string(print::NO_ANN, |s| s.print_type(self)))
}
}

impl fmt::Display for Ty {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", print::to_string(print::NO_ANN, |s| s.print_type(self)))
}
}

Expand Down
36 changes: 34 additions & 2 deletions src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -723,8 +723,40 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// When encountering &T != &mut T, highlight only the borrow
(&ty::TyRef(r1, ref tnm1), &ty::TyRef(r2, ref tnm2)) if equals(&tnm1.ty, &tnm2.ty) => {
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
push_ty_ref(&r1, tnm1, &mut values.0);
push_ty_ref(&r2, tnm2, &mut values.1);
push_ty_ref(& r1, tnm1, & mut values.0);
push_ty_ref( & r2, tnm2, &mut values.1);
values
}
// When comparing against a closure, print its signature without location
(_, &ty::TyClosure(did, _)) => {
let mut values = (DiagnosticStyledString::highlighted(format!("{}", t1)),
DiagnosticStyledString::new());
if let Some(node_id) = self.tcx.hir.as_local_node_id(did) {
if let Some(hir::map::NodeExpr(expr)) = self.tcx.hir.find(node_id) {
if let hir::ExprClosure(capture, ref fn_decl, _, _, _) = expr.node {
let args = fn_decl.inputs.iter()
.map(|arg| format!("{}", arg))
.collect::<Vec<String>>()
.join(", ");
values.1.push_highlighted(
format!("{}fn({}) -> {}",
if capture == hir::CaptureByValue {
"move "
} else {
""
},
args,
if let hir::Return(ref r_ty) = fn_decl.output {
format!("{}", r_ty)
} else {
"_".to_string()
}));
return values;
}
}
}
// fallback
values.1.push_highlighted(format!("{}", t2));
values
}

Expand Down
57 changes: 28 additions & 29 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -938,51 +938,50 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
err
}

fn build_fn_sig_string(&self, trait_ref: &ty::TraitRef<'tcx>) -> String {
let inputs = trait_ref.substs.type_at(1);
let sig = if let ty::TyTuple(inputs, _) = inputs.sty {
self.tcx.mk_fn_sig(
inputs.iter().map(|&x| x),
self.tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
false,
hir::Unsafety::Normal,
::syntax::abi::Abi::Rust
)
} else {
self.tcx.mk_fn_sig(
::std::iter::once(inputs),
self.tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
false,
hir::Unsafety::Normal,
::syntax::abi::Abi::Rust
)
};
format!("{}", ty::Binder(sig))
}

fn report_closure_arg_mismatch(&self,
span: Span,
found_span: Option<Span>,
expected_ref: ty::PolyTraitRef<'tcx>,
found: ty::PolyTraitRef<'tcx>)
span: Span,
found_span: Option<Span>,
expected_ref: ty::PolyTraitRef<'tcx>,
found: ty::PolyTraitRef<'tcx>)
-> DiagnosticBuilder<'tcx>
{
fn build_fn_sig_string<'a, 'gcx, 'tcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>,
trait_ref: &ty::TraitRef<'tcx>) -> String {
let inputs = trait_ref.substs.type_at(1);
let sig = if let ty::TyTuple(inputs, _) = inputs.sty {
tcx.mk_fn_sig(
inputs.iter().map(|&x| x),
tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
false,
hir::Unsafety::Normal,
::syntax::abi::Abi::Rust
)
} else {
tcx.mk_fn_sig(
::std::iter::once(inputs),
tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
false,
hir::Unsafety::Normal,
::syntax::abi::Abi::Rust
)
};
format!("{}", ty::Binder(sig))
}

let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
let mut err = struct_span_err!(self.tcx.sess, span, E0631,
"type mismatch in {} arguments",
if argument_is_closure { "closure" } else { "function" });

let found_str = format!(
"expected signature of `{}`",
build_fn_sig_string(self.tcx, found.skip_binder())
self.build_fn_sig_string(found.skip_binder())
);
err.span_label(span, found_str);

let found_span = found_span.unwrap_or(span);
let expected_str = format!(
"found signature of `{}`",
build_fn_sig_string(self.tcx, expected_ref.skip_binder())
self.build_fn_sig_string(expected_ref.skip_binder())
);
err.span_label(found_span, expected_str);

Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/issue-24036.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fn closure_to_loc() {
//~| HELP consider boxing your closure and/or using it as a trait object
//~| expected closure, found a different closure
//~| expected type `[closure
//~| found type `[closure
//~| found type `fn(_) -> _`
}

fn closure_from_match() {
Expand All @@ -31,7 +31,7 @@ fn closure_from_match() {
//~| HELP consider boxing your closure and/or using it as a trait object
//~| expected closure, found a different closure
//~| expected type `[closure
//~| found type `[closure
//~| found type `fn(_) -> _`
}

fn main() { }
2 changes: 1 addition & 1 deletion src/test/ui/block-result/issue-20862.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ error[E0308]: mismatched types
| ^^^^^^^^^ expected (), found closure
|
= note: expected type `()`
found type `[closure@$DIR/issue-20862.rs:12:5: 12:14 x:_]`
found type `fn(_) -> _`

error[E0618]: expected function, found `()`
--> $DIR/issue-20862.rs:17:13
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/span/move-closure.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ error[E0308]: mismatched types
| ^^^^^^^^^^ expected (), found closure
|
= note: expected type `()`
found type `[closure@$DIR/move-closure.rs:15:17: 15:27]`
found type `move fn() -> _`

error: aborting due to previous error

0 comments on commit 541cfb4

Please sign in to comment.