Skip to content

Commit 25845ff

Browse files
ldm0bogon-right
authored and
bogon-right
committed
Relay deref into block
1 parent 4b8f431 commit 25845ff

9 files changed

+107
-14
lines changed

compiler/rustc_hir_analysis/src/check/expectation.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@ pub enum Expectation<'tcx> {
1818
/// This expression will be cast to the `Ty`.
1919
ExpectCastableToType(Ty<'tcx>),
2020

21-
/// This rvalue expression will be wrapped in `&` or `Box` and coerced
22-
/// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
23-
ExpectRvalueLikeUnsized(Ty<'tcx>),
21+
/// This rvalue expression will be deref'd to the type Ty.
22+
///
23+
/// Given, for example, if you have let x: &Ty = &<foo>, this
24+
/// hint would be given when type-checking <foo>. It is
25+
/// not required that foo has the type Ty, but it must have some
26+
/// type that derefs to Ty for the program to be legal.
27+
ExpectRvalueDeref(Ty<'tcx>),
2428

2529
IsLast(Span),
2630
}
@@ -48,7 +52,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
4852
let ety = fcx.shallow_resolve(ety);
4953
if !ety.is_ty_var() { ExpectHasType(ety) } else { NoExpectation }
5054
}
51-
ExpectRvalueLikeUnsized(ety) => ExpectRvalueLikeUnsized(ety),
55+
ExpectRvalueDeref(ety) => ExpectRvalueDeref(ety),
5256
_ => NoExpectation,
5357
}
5458
}
@@ -74,7 +78,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
7478
/// for examples of where this comes up,.
7579
pub(super) fn rvalue_hint(fcx: &FnCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
7680
match fcx.tcx.struct_tail_without_normalization(ty).kind() {
77-
ty::Slice(_) | ty::Str | ty::Dynamic(..) => ExpectRvalueLikeUnsized(ty),
81+
ty::Slice(_) | ty::Str | ty::Dynamic(..) => ExpectRvalueDeref(ty),
7882
_ => ExpectHasType(ty),
7983
}
8084
}
@@ -87,15 +91,15 @@ impl<'a, 'tcx> Expectation<'tcx> {
8791
NoExpectation => NoExpectation,
8892
ExpectCastableToType(t) => ExpectCastableToType(fcx.resolve_vars_if_possible(t)),
8993
ExpectHasType(t) => ExpectHasType(fcx.resolve_vars_if_possible(t)),
90-
ExpectRvalueLikeUnsized(t) => ExpectRvalueLikeUnsized(fcx.resolve_vars_if_possible(t)),
94+
ExpectRvalueDeref(t) => ExpectRvalueDeref(fcx.resolve_vars_if_possible(t)),
9195
IsLast(sp) => IsLast(sp),
9296
}
9397
}
9498

9599
pub(super) fn to_option(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
96100
match self.resolve(fcx) {
97101
NoExpectation | IsLast(_) => None,
98-
ExpectCastableToType(ty) | ExpectHasType(ty) | ExpectRvalueLikeUnsized(ty) => Some(ty),
102+
ExpectCastableToType(ty) | ExpectHasType(ty) | ExpectRvalueDeref(ty) => Some(ty),
99103
}
100104
}
101105

@@ -106,9 +110,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
106110
pub(super) fn only_has_type(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
107111
match self {
108112
ExpectHasType(ty) => Some(fcx.resolve_vars_if_possible(ty)),
109-
NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) | IsLast(_) => {
110-
None
111-
}
113+
NoExpectation | ExpectCastableToType(_) | ExpectRvalueDeref(_) | IsLast(_) => None,
112114
}
113115
}
114116

compiler/rustc_hir_analysis/src/check/expr.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use crate::check::cast;
77
use crate::check::coercion::CoerceMany;
88
use crate::check::fatally_break_rust;
99
use crate::check::method::SelfSource;
10-
use crate::check::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
10+
use crate::check::Expectation::{
11+
self, ExpectCastableToType, ExpectHasType, ExpectRvalueDeref, NoExpectation,
12+
};
1113
use crate::check::{
1214
report_unexpected_variant_res, BreakableCtxt, Diverges, DynamicCoerceMany, FnCtxt, Needs,
1315
TupleArgumentsFlag::DontTupleArguments,
@@ -437,7 +439,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
437439
// the last field of a struct can be unsized.
438440
ExpectHasType(*ty)
439441
} else {
440-
Expectation::rvalue_hint(self, *ty)
442+
ExpectRvalueDeref(*ty)
441443
}
442444
}
443445
_ => NoExpectation,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// check-pass
2+
fn f(_: &i32) {}
3+
4+
fn main() {
5+
let x = Box::new(1i32);
6+
7+
f(&x);
8+
f(&(x));
9+
f(&{x});
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// check-pass
2+
use std::ops::Deref;
3+
4+
fn main() {
5+
fn save(who: &str) {
6+
println!("I'll save you, {}!", who);
7+
}
8+
9+
struct Madoka;
10+
11+
impl Deref for Madoka {
12+
type Target = str;
13+
fn deref(&self) -> &Self::Target {
14+
"Madoka"
15+
}
16+
}
17+
18+
save(&{ Madoka });
19+
20+
fn reset(how: &u32) {
21+
println!("Reset {} times", how);
22+
}
23+
24+
struct Homura;
25+
26+
impl Deref for Homura {
27+
type Target = u32;
28+
fn deref(&self) -> &Self::Target {
29+
&42
30+
}
31+
}
32+
33+
reset(&{ Homura });
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// check-pass
2+
// edition:2018
3+
fn _consume_reference<T: ?Sized>(_: &T) {}
4+
5+
async fn _foo() {
6+
_consume_reference::<i32>(&Box::new(7_i32));
7+
_consume_reference::<i32>(&async { Box::new(7_i32) }.await);
8+
_consume_reference::<[i32]>(&vec![7_i32]);
9+
_consume_reference::<[i32]>(&async { vec![7_i32] }.await);
10+
}
11+
12+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// check-fail
2+
fn f(_: &[i32]) {}
3+
4+
fn main() {
5+
f(&Box::new([1, 2]));
6+
//~^ ERROR mismatched types
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/coerce-block-tail-83850.rs:5:7
3+
|
4+
LL | f(&Box::new([1, 2]));
5+
| - ^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found struct `Box`
6+
| |
7+
| arguments to this function are incorrect
8+
|
9+
= note: expected reference `&[i32]`
10+
found reference `&Box<[{integer}; 2]>`
11+
note: function defined here
12+
--> $DIR/coerce-block-tail-83850.rs:2:4
13+
|
14+
LL | fn f(_: &[i32]) {}
15+
| ^ ---------
16+
17+
error: aborting due to previous error
18+
19+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// check-pass
2+
fn main() {
3+
let _: &str = & { String::from("hahah")};
4+
let _: &i32 = & { Box::new(1i32) };
5+
}

src/test/ui/did_you_mean/brackets-to-braces-single-element.stderr

+4-2
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@ LL | const B: &[u32] = &[ 1 ];
2323
| ~ ~
2424

2525
error[E0308]: mismatched types
26-
--> $DIR/brackets-to-braces-single-element.rs:7:27
26+
--> $DIR/brackets-to-braces-single-element.rs:7:23
2727
|
2828
LL | const C: &&[u32; 1] = &&{ 1 };
29-
| ^ expected array `[u32; 1]`, found integer
29+
| ^^^^^^^ expected array `[u32; 1]`, found integer
3030
|
31+
= note: expected reference `&'static &'static [u32; 1]`
32+
found reference `&&{integer}`
3133
help: to create an array, use square brackets instead of curly braces
3234
|
3335
LL | const C: &&[u32; 1] = &&[ 1 ];

0 commit comments

Comments
 (0)