@@ -176,6 +176,10 @@ enum Expectation<'tcx> {
176
176
177
177
/// This expression will be cast to the `Ty`
178
178
ExpectCastableToType ( Ty < ' tcx > ) ,
179
+
180
+ /// This rvalue expression will be wrapped in `&` or `Box` and coerced
181
+ /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
182
+ ExpectRvalueLikeUnsized ( Ty < ' tcx > ) ,
179
183
}
180
184
181
185
impl < ' tcx > Expectation < ' tcx > {
@@ -196,7 +200,7 @@ impl<'tcx> Expectation<'tcx> {
196
200
// when checking the 'then' block which are incompatible with the
197
201
// 'else' branch.
198
202
fn adjust_for_branches < ' a > ( & self , fcx : & FnCtxt < ' a , ' tcx > ) -> Expectation < ' tcx > {
199
- match self . only_has_type ( ) {
203
+ match * self {
200
204
ExpectHasType ( ety) => {
201
205
let ety = fcx. infcx ( ) . shallow_resolve ( ety) ;
202
206
if !ty:: type_is_ty_var ( ety) {
@@ -205,6 +209,9 @@ impl<'tcx> Expectation<'tcx> {
205
209
NoExpectation
206
210
}
207
211
}
212
+ ExpectRvalueLikeUnsized ( ety) => {
213
+ ExpectRvalueLikeUnsized ( ety)
214
+ }
208
215
_ => NoExpectation
209
216
}
210
217
}
@@ -3678,7 +3685,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3678
3685
match unop {
3679
3686
ast:: UnUniq => match ty. sty {
3680
3687
ty:: ty_uniq( ty) => {
3681
- ExpectHasType ( ty)
3688
+ Expectation :: rvalue_hint ( ty)
3682
3689
}
3683
3690
_ => {
3684
3691
NoExpectation
@@ -3767,7 +3774,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3767
3774
let expected = expected. only_has_type ( ) ;
3768
3775
let hint = expected. map ( fcx, |ty| {
3769
3776
match ty. sty {
3770
- ty:: ty_rptr( _, ref mt) | ty:: ty_ptr( ref mt) => ExpectHasType ( mt. ty ) ,
3777
+ ty:: ty_rptr( _, ref mt) | ty:: ty_ptr( ref mt) => {
3778
+ if ty:: expr_is_lval ( fcx. tcx ( ) , & * * oprnd) {
3779
+ ExpectHasType ( mt. ty )
3780
+ } else {
3781
+ Expectation :: rvalue_hint ( mt. ty )
3782
+ }
3783
+ }
3771
3784
_ => NoExpectation
3772
3785
}
3773
3786
} ) ;
@@ -3985,15 +3998,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3985
3998
check_cast ( fcx, expr, & * * e, & * * t) ;
3986
3999
}
3987
4000
ast:: ExprVec ( ref args) => {
3988
- let uty = match expected {
3989
- ExpectHasType ( uty) => {
3990
- match uty. sty {
3991
- ty:: ty_vec( ty, _) => Some ( ty) ,
3992
- _ => None
3993
- }
4001
+ let uty = expected. map_to_option ( fcx, |uty| {
4002
+ match uty. sty {
4003
+ ty:: ty_vec( ty, _) => Some ( ty) ,
4004
+ _ => None
3994
4005
}
3995
- _ => None
3996
- } ;
4006
+ } ) ;
3997
4007
3998
4008
let typ = match uty {
3999
4009
Some ( uty) => {
@@ -4020,8 +4030,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
4020
4030
let uty = match expected {
4021
4031
ExpectHasType ( uty) => {
4022
4032
match uty. sty {
4023
- ty:: ty_vec( ty, _) => Some ( ty) ,
4024
- _ => None
4033
+ ty:: ty_vec( ty, _) => Some ( ty) ,
4034
+ _ => None
4025
4035
}
4026
4036
}
4027
4037
_ => None
@@ -4298,10 +4308,29 @@ fn constrain_path_type_parameters(fcx: &FnCtxt,
4298
4308
}
4299
4309
4300
4310
impl < ' tcx > Expectation < ' tcx > {
4311
+ /// Provide an expectation for an rvalue expression given an *optional*
4312
+ /// hint, which is not required for type safety (the resulting type might
4313
+ /// be checked higher up, as is the case with `&expr` and `box expr`), but
4314
+ /// is useful in determining the concrete type.
4315
+ ///
4316
+ /// The primary usecase is unpacking `&T` and `Box<T>`, where `T` is
4317
+ /// unsized and propagating `ExpectHasType(T)` would try to assign `T` to
4318
+ /// an rvalue expression, which is invalid. Instead, a weaker hint is used.
4319
+ /// This is required, when e.g `T` is `[u8]` and the rvalue is `[1, 2, 3]`,
4320
+ /// without the hint the integer literals would remain uninferred.
4321
+ fn rvalue_hint ( ty : Ty < ' tcx > ) -> Expectation < ' tcx > {
4322
+ match ty. sty {
4323
+ ty:: ty_vec( _, None ) | ty:: ty_trait( ..) => {
4324
+ ExpectRvalueLikeUnsized ( ty)
4325
+ }
4326
+ _ => ExpectHasType ( ty)
4327
+ }
4328
+ }
4329
+
4301
4330
fn only_has_type ( self ) -> Expectation < ' tcx > {
4302
4331
match self {
4303
- NoExpectation | ExpectCastableToType ( .. ) => NoExpectation ,
4304
- ExpectHasType ( t ) => ExpectHasType ( t )
4332
+ ExpectHasType ( t ) => ExpectHasType ( t ) ,
4333
+ _ => NoExpectation
4305
4334
}
4306
4335
}
4307
4336
@@ -4321,6 +4350,10 @@ impl<'tcx> Expectation<'tcx> {
4321
4350
ExpectHasType (
4322
4351
fcx. infcx ( ) . resolve_type_vars_if_possible ( & t) )
4323
4352
}
4353
+ ExpectRvalueLikeUnsized ( t) => {
4354
+ ExpectRvalueLikeUnsized (
4355
+ fcx. infcx ( ) . resolve_type_vars_if_possible ( & t) )
4356
+ }
4324
4357
}
4325
4358
}
4326
4359
@@ -4329,7 +4362,9 @@ impl<'tcx> Expectation<'tcx> {
4329
4362
{
4330
4363
match self . resolve ( fcx) {
4331
4364
NoExpectation => NoExpectation ,
4332
- ExpectCastableToType ( ty) | ExpectHasType ( ty) => unpack ( ty) ,
4365
+ ExpectCastableToType ( ty) |
4366
+ ExpectHasType ( ty) |
4367
+ ExpectRvalueLikeUnsized ( ty) => unpack ( ty) ,
4333
4368
}
4334
4369
}
4335
4370
@@ -4338,7 +4373,9 @@ impl<'tcx> Expectation<'tcx> {
4338
4373
{
4339
4374
match self . resolve ( fcx) {
4340
4375
NoExpectation => None ,
4341
- ExpectCastableToType ( ty) | ExpectHasType ( ty) => unpack ( ty) ,
4376
+ ExpectCastableToType ( ty) |
4377
+ ExpectHasType ( ty) |
4378
+ ExpectRvalueLikeUnsized ( ty) => unpack ( ty) ,
4342
4379
}
4343
4380
}
4344
4381
}
@@ -4351,6 +4388,8 @@ impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
4351
4388
t. repr( tcx) ) ,
4352
4389
ExpectCastableToType ( t) => format ! ( "ExpectCastableToType({})" ,
4353
4390
t. repr( tcx) ) ,
4391
+ ExpectRvalueLikeUnsized ( t) => format ! ( "ExpectRvalueLikeUnsized({})" ,
4392
+ t. repr( tcx) ) ,
4354
4393
}
4355
4394
}
4356
4395
}
0 commit comments