Suggest dereferencing when Deref
is implemented.
This commit suggests dereferencing a type when it implements `Deref` with the correct `Output` associated type.
This commit is contained in:
parent
c9a2616e44
commit
fd95ba3574
@ -1,6 +1,6 @@
|
||||
use crate::check::FnCtxt;
|
||||
use rustc::infer::InferOk;
|
||||
use rustc::traits::{ObligationCause, ObligationCauseCode};
|
||||
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
|
||||
|
||||
use syntax::util::parser::PREC_POSTFIX;
|
||||
use syntax_pos::Span;
|
||||
@ -463,7 +463,37 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
_ => {
|
||||
// If neither type is a reference, then check for `Deref` implementations by
|
||||
// constructing a predicate to prove: `<T as Deref>::Output == U`
|
||||
let deref_trait = self.tcx.lang_items().deref_trait().unwrap();
|
||||
let item_def_id = self.tcx.associated_items(deref_trait).next().unwrap().def_id;
|
||||
let predicate = ty::Predicate::Projection(ty::Binder::bind(ty::ProjectionPredicate {
|
||||
// `<T as Deref>::Output`
|
||||
projection_ty: ty::ProjectionTy {
|
||||
// `T`
|
||||
substs: self.tcx.mk_substs_trait(
|
||||
checked_ty,
|
||||
self.fresh_substs_for_item(sp, item_def_id),
|
||||
),
|
||||
// `Deref::Output`
|
||||
item_def_id,
|
||||
},
|
||||
// `U`
|
||||
ty: expected,
|
||||
}));
|
||||
let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate);
|
||||
if self.infcx.predicate_may_hold(&obligation) {
|
||||
if let (Ok(code), true) = (cm.span_to_snippet(sp), sp == expr.span) {
|
||||
let msg = if is_struct_pat_shorthand_field {
|
||||
format!("{}: *{}", code, code)
|
||||
} else {
|
||||
format!("*{}", code)
|
||||
};
|
||||
return Some((sp, "consider dereferencing the type", msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ LL | x = box x;
|
||||
| ^^^^^
|
||||
| |
|
||||
| cyclic type of infinite size
|
||||
| help: try using a conversion method: `box x.to_string()`
|
||||
| help: consider dereferencing the type: `*box x`
|
||||
|
||||
error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
|
||||
--> $DIR/infinite-autoderef.rs:25:5
|
||||
|
@ -5,7 +5,7 @@ LL | f = box g;
|
||||
| ^^^^^
|
||||
| |
|
||||
| cyclic type of infinite size
|
||||
| help: try using a conversion method: `box g.to_string()`
|
||||
| help: consider dereferencing the type: `*box g`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -5,7 +5,7 @@ LL | f = box f;
|
||||
| ^^^^^
|
||||
| |
|
||||
| cyclic type of infinite size
|
||||
| help: try using a conversion method: `box f.to_string()`
|
||||
| help: consider dereferencing the type: `*box f`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -44,7 +44,7 @@ LL | f = box f;
|
||||
| ^^^^^
|
||||
| |
|
||||
| cyclic type of infinite size
|
||||
| help: try using a conversion method: `box f.to_string()`
|
||||
| help: consider dereferencing the type: `*box f`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/coerce-suggestions.rs:21:9
|
||||
|
22
src/test/ui/suggestions/issue-59819.fixed
Normal file
22
src/test/ui/suggestions/issue-59819.fixed
Normal file
@ -0,0 +1,22 @@
|
||||
// run-rustfix
|
||||
|
||||
#![allow(warnings)]
|
||||
|
||||
// Test that suggestion to add `*` characters applies to implementations of `Deref` as well as
|
||||
// references.
|
||||
|
||||
struct Foo(i32);
|
||||
|
||||
impl std::ops::Deref for Foo {
|
||||
type Target = i32;
|
||||
fn deref(&self) -> &i32 {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = Foo(42);
|
||||
let y: i32 = *x; //~ ERROR mismatched types
|
||||
let a = &42;
|
||||
let b: i32 = *a; //~ ERROR mismatched types
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
// run-rustfix
|
||||
|
||||
#![allow(warnings)]
|
||||
|
||||
// Test that suggestion to add `*` characters applies to implementations of `Deref` as well as
|
||||
|
@ -1,14 +1,17 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-59819.rs:17:18
|
||||
--> $DIR/issue-59819.rs:19:18
|
||||
|
|
||||
LL | let y: i32 = x;
|
||||
| ^ expected i32, found struct `Foo`
|
||||
| ^
|
||||
| |
|
||||
| expected i32, found struct `Foo`
|
||||
| help: consider dereferencing the type: `*x`
|
||||
|
|
||||
= note: expected type `i32`
|
||||
found type `Foo`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-59819.rs:19:18
|
||||
--> $DIR/issue-59819.rs:21:18
|
||||
|
|
||||
LL | let b: i32 = a;
|
||||
| ^
|
||||
|
@ -2,7 +2,10 @@ error[E0308]: mismatched types
|
||||
--> $DIR/terr-sorts.rs:10:14
|
||||
|
|
||||
LL | want_foo(b);
|
||||
| ^ expected struct `Foo`, found struct `std::boxed::Box`
|
||||
| ^
|
||||
| |
|
||||
| expected struct `Foo`, found struct `std::boxed::Box`
|
||||
| help: consider dereferencing the type: `*b`
|
||||
|
|
||||
= note: expected type `Foo`
|
||||
found type `std::boxed::Box<Foo>`
|
||||
|
Loading…
Reference in New Issue
Block a user