impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
+ self.check_pat_arg(pat, expected, false);
+ }
+
+ pub fn check_pat_arg(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>, is_arg: bool) {
let tcx = self.tcx;
debug!("check_pat(pat={:?},expected={:?})", pat, expected);
let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
let region = self.next_region_var(infer::PatternRegion(pat.span));
let rptr_ty = tcx.mk_ref(region, mt);
- self.demand_eqtype(pat.span, expected, rptr_ty);
+ let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
+ if let Some(mut err) = err {
+ if is_arg {
+ if let Ok(snippet) = self.sess().codemap()
+ .span_to_snippet(pat.span)
+ {
+ err.help(&format!("did you mean `{}: &{}`?",
+ snippet,
+ expected));
+ err.help(&format!("did you mean `{}: {}`?",
+ &snippet[1..],
+ expected));
+ }
+ }
+ err.emit();
+ }
(rptr_ty, inner_ty)
}
};
use rustc::hir;
use rustc::hir::def::Def;
use rustc::ty::{self, AssociatedItem};
+use errors::DiagnosticBuilder;
use super::method::probe;
}
pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
- self.demand_eqtype_with_origin(&self.misc(sp), expected, actual);
+ if let Some(mut err) = self.demand_eqtype_diag(sp, expected, actual) {
+ err.emit();
+ }
+ }
+
+ pub fn demand_eqtype_diag(&self,
+ sp: Span,
+ expected: Ty<'tcx>,
+ actual: Ty<'tcx>) -> Option<DiagnosticBuilder<'tcx>> {
+ self.demand_eqtype_with_origin(&self.misc(sp), expected, actual)
}
pub fn demand_eqtype_with_origin(&self,
cause: &ObligationCause<'tcx>,
expected: Ty<'tcx>,
- actual: Ty<'tcx>)
- {
+ actual: Ty<'tcx>) -> Option<DiagnosticBuilder<'tcx>> {
match self.eq_types(false, cause, actual, expected) {
Ok(InferOk { obligations, value: () }) => {
self.register_predicates(obligations);
+ None
},
Err(e) => {
- self.report_mismatched_types(cause, expected, actual, e).emit();
+ Some(self.report_mismatched_types(cause, expected, actual, e))
}
}
}
fcx.register_old_wf_obligation(arg_ty, arg.pat.span, traits::MiscObligation);
// Check the pattern.
- fcx.check_pat(&arg.pat, arg_ty);
+ fcx.check_pat_arg(&arg.pat, arg_ty, true);
fcx.write_ty(arg.id, arg_ty);
}
debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver);
- fcx.demand_eqtype_with_origin(&cause, rcvr_ty, self_arg_ty);
+ if let Some(mut err) = fcx.demand_eqtype_with_origin(&cause, rcvr_ty, self_arg_ty) {
+ err.emit();
+ }
}
fn check_variances_for_type_defn(&self,
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo {
+}
+
+fn foo(&foo: Foo) { // illegal syntax
+}
+
+fn bar(foo: Foo) { // legal
+}
+
+fn qux(foo: &Foo) { // legal
+}
+
+fn zar(&foo: &Foo) { // legal
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-38371.rs:14:8
+ |
+14 | fn foo(&foo: Foo) { // illegal syntax
+ | ^^^^ expected struct `Foo`, found reference
+ |
+ = note: expected type `Foo`
+ = note: found type `&_`
+ = help: did you mean `&foo: &Foo`?
+ = help: did you mean `foo: Foo`?
+
+error: aborting due to previous error
+