@@ -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
}
@@ -3658,7 +3665,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3658
3665
match unop {
3659
3666
ast:: UnUniq => match ty. sty {
3660
3667
ty:: ty_uniq( ty) => {
3661
- ExpectHasType ( ty)
3668
+ Expectation :: rvalue_hint ( ty)
3662
3669
}
3663
3670
_ => {
3664
3671
NoExpectation
@@ -3747,7 +3754,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3747
3754
let expected = expected. only_has_type ( ) ;
3748
3755
let hint = expected. map ( fcx, |ty| {
3749
3756
match ty. sty {
3750
- ty:: ty_rptr( _, ref mt) | ty:: ty_ptr( ref mt) => ExpectHasType ( mt. ty ) ,
3757
+ ty:: ty_rptr( _, ref mt) | ty:: ty_ptr( ref mt) => {
3758
+ if ty:: expr_is_lval ( fcx. tcx ( ) , & * * oprnd) {
3759
+ ExpectHasType ( mt. ty )
3760
+ } else {
3761
+ Expectation :: rvalue_hint ( mt. ty )
3762
+ }
3763
+ }
3751
3764
_ => NoExpectation
3752
3765
}
3753
3766
} ) ;
@@ -3965,15 +3978,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3965
3978
check_cast ( fcx, expr, & * * e, & * * t) ;
3966
3979
}
3967
3980
ast:: ExprVec ( ref args) => {
3968
- let uty = match expected {
3969
- ExpectHasType ( uty) => {
3970
- match uty. sty {
3971
- ty:: ty_vec( ty, _) => Some ( ty) ,
3972
- _ => None
3973
- }
3981
+ let uty = expected. map_to_option ( fcx, |uty| {
3982
+ match uty. sty {
3983
+ ty:: ty_vec( ty, _) => Some ( ty) ,
3984
+ _ => None
3974
3985
}
3975
- _ => None
3976
- } ;
3986
+ } ) ;
3977
3987
3978
3988
let typ = match uty {
3979
3989
Some ( uty) => {
@@ -4000,8 +4010,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
4000
4010
let uty = match expected {
4001
4011
ExpectHasType ( uty) => {
4002
4012
match uty. sty {
4003
- ty:: ty_vec( ty, _) => Some ( ty) ,
4004
- _ => None
4013
+ ty:: ty_vec( ty, _) => Some ( ty) ,
4014
+ _ => None
4005
4015
}
4006
4016
}
4007
4017
_ => None
@@ -4278,10 +4288,29 @@ fn constrain_path_type_parameters(fcx: &FnCtxt,
4278
4288
}
4279
4289
4280
4290
impl < ' tcx > Expectation < ' tcx > {
4291
+ /// Provide an expectation for an rvalue expression given an *optional*
4292
+ /// hint, which is not required for type safety (the resulting type might
4293
+ /// be checked higher up, as is the case with `&expr` and `box expr`), but
4294
+ /// is useful in determining the concrete type.
4295
+ ///
4296
+ /// The primary usecase is unpacking `&T` and `Box<T>`, where `T` is
4297
+ /// unsized and propagating `ExpectHasType(T)` would try to assign `T` to
4298
+ /// an rvalue expression, which is invalid. Instead, a weaker hint is used.
4299
+ /// This is required, when e.g `T` is `[u8]` and the rvalue is `[1, 2, 3]`,
4300
+ /// without the hint the integer literals would remain uninferred.
4301
+ fn rvalue_hint ( ty : Ty < ' tcx > ) -> Expectation < ' tcx > {
4302
+ match ty. sty {
4303
+ ty:: ty_vec( _, None ) | ty:: ty_trait( ..) => {
4304
+ ExpectRvalueLikeUnsized ( ty)
4305
+ }
4306
+ _ => ExpectHasType ( ty)
4307
+ }
4308
+ }
4309
+
4281
4310
fn only_has_type ( self ) -> Expectation < ' tcx > {
4282
4311
match self {
4283
- NoExpectation | ExpectCastableToType ( .. ) => NoExpectation ,
4284
- ExpectHasType ( t ) => ExpectHasType ( t )
4312
+ ExpectHasType ( t ) => ExpectHasType ( t ) ,
4313
+ _ => NoExpectation
4285
4314
}
4286
4315
}
4287
4316
@@ -4301,6 +4330,10 @@ impl<'tcx> Expectation<'tcx> {
4301
4330
ExpectHasType (
4302
4331
fcx. infcx ( ) . resolve_type_vars_if_possible ( & t) )
4303
4332
}
4333
+ ExpectRvalueLikeUnsized ( t) => {
4334
+ ExpectRvalueLikeUnsized (
4335
+ fcx. infcx ( ) . resolve_type_vars_if_possible ( & t) )
4336
+ }
4304
4337
}
4305
4338
}
4306
4339
@@ -4309,7 +4342,9 @@ impl<'tcx> Expectation<'tcx> {
4309
4342
{
4310
4343
match self . resolve ( fcx) {
4311
4344
NoExpectation => NoExpectation ,
4312
- ExpectCastableToType ( ty) | ExpectHasType ( ty) => unpack ( ty) ,
4345
+ ExpectCastableToType ( ty) |
4346
+ ExpectHasType ( ty) |
4347
+ ExpectRvalueLikeUnsized ( ty) => unpack ( ty) ,
4313
4348
}
4314
4349
}
4315
4350
@@ -4318,7 +4353,9 @@ impl<'tcx> Expectation<'tcx> {
4318
4353
{
4319
4354
match self . resolve ( fcx) {
4320
4355
NoExpectation => None ,
4321
- ExpectCastableToType ( ty) | ExpectHasType ( ty) => unpack ( ty) ,
4356
+ ExpectCastableToType ( ty) |
4357
+ ExpectHasType ( ty) |
4358
+ ExpectRvalueLikeUnsized ( ty) => unpack ( ty) ,
4322
4359
}
4323
4360
}
4324
4361
}
@@ -4331,6 +4368,8 @@ impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
4331
4368
t. repr( tcx) ) ,
4332
4369
ExpectCastableToType ( t) => format ! ( "ExpectCastableToType({})" ,
4333
4370
t. repr( tcx) ) ,
4371
+ ExpectRvalueLikeUnsized ( t) => format ! ( "ExpectRvalueLikeUnsized({})" ,
4372
+ t. repr( tcx) ) ,
4334
4373
}
4335
4374
}
4336
4375
}
0 commit comments