mirror of
https://github.com/openharmony/third_party_rust_rust.git
synced 2026-07-19 11:43:39 -04:00
Auto merge of #38605 - estebank:fix-38371, r=nikomatsakis
Suggest solutions for `fn foo(&foo: Foo)`
For a given file:
```rust
struct Foo {}
fn foo(&foo: Foo) {}
```
suggest:
```
error[E0308]: mismatched types
--> file.rs:3:8
|
3 | fn foo(&foo: Foo) {}
| ^^^^ expected struct `Foo`, found reference
|
= note: expected type `Foo`
= note: found type `&_`
= help: did you mean `foo: &Foo`?
```
Fix #38371.
This commit is contained in:
@@ -27,9 +27,17 @@ use syntax_pos::Span;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/// The `is_arg` argument indicates whether this pattern is the
|
||||
/// *outermost* pattern in an argument (e.g., in `fn foo(&x:
|
||||
/// &u32)`, it is true for the `&x` pattern but not `x`). This is
|
||||
/// used to tailor error reporting.
|
||||
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);
|
||||
debug!("check_pat(pat={:?},expected={:?},is_arg={})", pat, expected, is_arg);
|
||||
|
||||
let ty = match pat.node {
|
||||
PatKind::Wild => {
|
||||
@@ -202,6 +210,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// can, to avoid creating needless variables. This
|
||||
// also helps with the bad interactions of the given
|
||||
// hack detailed in (*) below.
|
||||
debug!("check_pat_arg: expected={:?}", expected);
|
||||
let (rptr_ty, inner_ty) = match expected.sty {
|
||||
ty::TyRef(_, mt) if mt.mutbl == mutbl => {
|
||||
(expected, mt.ty)
|
||||
@@ -212,7 +221,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
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);
|
||||
debug!("check_pat_arg: demanding {:?} = {:?}", expected, rptr_ty);
|
||||
let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
|
||||
|
||||
// Look for a case like `fn foo(&foo: u32)` and suggest
|
||||
// `fn foo(foo: &u32)`
|
||||
if let Some(mut err) = err {
|
||||
if is_arg {
|
||||
if let PatKind::Binding(..) = inner.node {
|
||||
if let Ok(snippet) = self.sess().codemap()
|
||||
.span_to_snippet(pat.span)
|
||||
{
|
||||
err.help(&format!("did you mean `{}: &{}`?",
|
||||
&snippet[1..],
|
||||
expected));
|
||||
}
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
(rptr_ty, inner_ty)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -19,6 +19,7 @@ use syntax_pos::{self, Span};
|
||||
use rustc::hir;
|
||||
use rustc::hir::def::Def;
|
||||
use rustc::ty::{self, AssociatedItem};
|
||||
use errors::DiagnosticBuilder;
|
||||
|
||||
use super::method::probe;
|
||||
|
||||
@@ -38,20 +39,29 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -796,7 +796,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -505,7 +505,9 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
|
||||
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,
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2017 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.
|
||||
#![feature(slice_patterns)]
|
||||
|
||||
|
||||
struct Foo {
|
||||
}
|
||||
|
||||
fn foo(&foo: Foo) {
|
||||
}
|
||||
|
||||
fn bar(foo: Foo) {
|
||||
}
|
||||
|
||||
fn qux(foo: &Foo) {
|
||||
}
|
||||
|
||||
fn zar(&foo: &Foo) {
|
||||
}
|
||||
|
||||
fn agh(&&bar: &u32) {
|
||||
}
|
||||
|
||||
fn bgh(&&bar: u32) {
|
||||
}
|
||||
|
||||
fn ugh(&[bar]: &u32) {
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,36 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-38371.rs:16:8
|
||||
|
|
||||
16 | fn foo(&foo: Foo) {
|
||||
| ^^^^ expected struct `Foo`, found reference
|
||||
|
|
||||
= note: expected type `Foo`
|
||||
= note: found type `&_`
|
||||
= help: did you mean `foo: &Foo`?
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-38371.rs:28:9
|
||||
|
|
||||
28 | fn agh(&&bar: &u32) {
|
||||
| ^^^^ expected u32, found reference
|
||||
|
|
||||
= note: expected type `u32`
|
||||
= note: found type `&_`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-38371.rs:31:8
|
||||
|
|
||||
31 | fn bgh(&&bar: u32) {
|
||||
| ^^^^^ expected u32, found reference
|
||||
|
|
||||
= note: expected type `u32`
|
||||
= note: found type `&_`
|
||||
|
||||
error[E0529]: expected an array or slice, found `u32`
|
||||
--> $DIR/issue-38371.rs:34:9
|
||||
|
|
||||
34 | fn ugh(&[bar]: &u32) {
|
||||
| ^^^^^ pattern cannot match with input type `u32`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Reference in New Issue
Block a user