Skip to content

Commit 5598f35

Browse files
committed
Suggest solutions for fn foo(&foo: Foo)
1 parent 4ecc85b commit 5598f35

File tree

6 files changed

+77
-7
lines changed

6 files changed

+77
-7
lines changed

src/librustc_typeck/check/_match.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ use syntax_pos::Span;
2727

2828
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
2929
pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
30+
self.check_pat_arg(pat, expected, false);
31+
}
32+
33+
pub fn check_pat_arg(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>, is_arg: bool) {
3034
let tcx = self.tcx;
3135

3236
debug!("check_pat(pat={:?},expected={:?})", pat, expected);
@@ -212,7 +216,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
212216
let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
213217
let region = self.next_region_var(infer::PatternRegion(pat.span));
214218
let rptr_ty = tcx.mk_ref(region, mt);
215-
self.demand_eqtype(pat.span, expected, rptr_ty);
219+
let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
220+
if let Some(mut err) = err {
221+
if is_arg {
222+
if let Ok(snippet) = self.sess().codemap()
223+
.span_to_snippet(pat.span)
224+
{
225+
err.help(&format!("did you mean `{}: &{}`?",
226+
snippet,
227+
expected));
228+
err.help(&format!("did you mean `{}: {}`?",
229+
&snippet[1..],
230+
expected));
231+
}
232+
}
233+
err.emit();
234+
}
216235
(rptr_ty, inner_ty)
217236
}
218237
};

src/librustc_typeck/check/demand.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use syntax_pos::{self, Span};
1919
use rustc::hir;
2020
use rustc::hir::def::Def;
2121
use rustc::ty::{self, AssociatedItem};
22+
use errors::DiagnosticBuilder;
2223

2324
use super::method::probe;
2425

@@ -38,20 +39,29 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3839
}
3940

4041
pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
41-
self.demand_eqtype_with_origin(&self.misc(sp), expected, actual);
42+
if let Some(mut err) = self.demand_eqtype_diag(sp, expected, actual) {
43+
err.emit();
44+
}
45+
}
46+
47+
pub fn demand_eqtype_diag(&self,
48+
sp: Span,
49+
expected: Ty<'tcx>,
50+
actual: Ty<'tcx>) -> Option<DiagnosticBuilder<'tcx>> {
51+
self.demand_eqtype_with_origin(&self.misc(sp), expected, actual)
4252
}
4353

4454
pub fn demand_eqtype_with_origin(&self,
4555
cause: &ObligationCause<'tcx>,
4656
expected: Ty<'tcx>,
47-
actual: Ty<'tcx>)
48-
{
57+
actual: Ty<'tcx>) -> Option<DiagnosticBuilder<'tcx>> {
4958
match self.eq_types(false, cause, actual, expected) {
5059
Ok(InferOk { obligations, value: () }) => {
5160
self.register_predicates(obligations);
61+
None
5262
},
5363
Err(e) => {
54-
self.report_mismatched_types(cause, expected, actual, e).emit();
64+
Some(self.report_mismatched_types(cause, expected, actual, e))
5565
}
5666
}
5767
}

src/librustc_typeck/check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
798798
fcx.register_old_wf_obligation(arg_ty, arg.pat.span, traits::MiscObligation);
799799

800800
// Check the pattern.
801-
fcx.check_pat(&arg.pat, arg_ty);
801+
fcx.check_pat_arg(&arg.pat, arg_ty, true);
802802
fcx.write_ty(arg.id, arg_ty);
803803
}
804804

src/librustc_typeck/check/wfcheck.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,9 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
505505
debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
506506

507507
let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver);
508-
fcx.demand_eqtype_with_origin(&cause, rcvr_ty, self_arg_ty);
508+
if let Some(mut err) = fcx.demand_eqtype_with_origin(&cause, rcvr_ty, self_arg_ty) {
509+
err.emit();
510+
}
509511
}
510512

511513
fn check_variances_for_type_defn(&self,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
struct Foo {
12+
}
13+
14+
fn foo(&foo: Foo) { // illegal syntax
15+
}
16+
17+
fn bar(foo: Foo) { // legal
18+
}
19+
20+
fn qux(foo: &Foo) { // legal
21+
}
22+
23+
fn zar(&foo: &Foo) { // legal
24+
}
25+
26+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-38371.rs:14:8
3+
|
4+
14 | fn foo(&foo: Foo) { // illegal syntax
5+
| ^^^^ expected struct `Foo`, found reference
6+
|
7+
= note: expected type `Foo`
8+
= note: found type `&_`
9+
= help: did you mean `&foo: &Foo`?
10+
= help: did you mean `foo: Foo`?
11+
12+
error: aborting due to previous error
13+

0 commit comments

Comments
 (0)