@@ -176,6 +176,10 @@ enum Expectation<'tcx> {
176176
177177 /// This expression will be cast to the `Ty`
178178 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 > ) ,
179183}
180184
181185impl < ' tcx > Expectation < ' tcx > {
@@ -196,7 +200,7 @@ impl<'tcx> Expectation<'tcx> {
196200 // when checking the 'then' block which are incompatible with the
197201 // 'else' branch.
198202 fn adjust_for_branches < ' a > ( & self , fcx : & FnCtxt < ' a , ' tcx > ) -> Expectation < ' tcx > {
199- match self . only_has_type ( ) {
203+ match * self {
200204 ExpectHasType ( ety) => {
201205 let ety = fcx. infcx ( ) . shallow_resolve ( ety) ;
202206 if !ty:: type_is_ty_var ( ety) {
@@ -205,6 +209,9 @@ impl<'tcx> Expectation<'tcx> {
205209 NoExpectation
206210 }
207211 }
212+ ExpectRvalueLikeUnsized ( ety) => {
213+ ExpectRvalueLikeUnsized ( ety)
214+ }
208215 _ => NoExpectation
209216 }
210217 }
@@ -3658,7 +3665,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
36583665 match unop {
36593666 ast:: UnUniq => match ty. sty {
36603667 ty:: ty_uniq( ty) => {
3661- ExpectHasType ( ty)
3668+ Expectation :: rvalue_hint ( ty)
36623669 }
36633670 _ => {
36643671 NoExpectation
@@ -3747,7 +3754,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
37473754 let expected = expected. only_has_type ( ) ;
37483755 let hint = expected. map ( fcx, |ty| {
37493756 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+ }
37513764 _ => NoExpectation
37523765 }
37533766 } ) ;
@@ -3965,15 +3978,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
39653978 check_cast ( fcx, expr, & * * e, & * * t) ;
39663979 }
39673980 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
39743985 }
3975- _ => None
3976- } ;
3986+ } ) ;
39773987
39783988 let typ = match uty {
39793989 Some ( uty) => {
@@ -4000,8 +4010,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
40004010 let uty = match expected {
40014011 ExpectHasType ( uty) => {
40024012 match uty. sty {
4003- ty:: ty_vec( ty, _) => Some ( ty) ,
4004- _ => None
4013+ ty:: ty_vec( ty, _) => Some ( ty) ,
4014+ _ => None
40054015 }
40064016 }
40074017 _ => None
@@ -4278,10 +4288,29 @@ fn constrain_path_type_parameters(fcx: &FnCtxt,
42784288}
42794289
42804290impl < ' 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+
42814310 fn only_has_type ( self ) -> Expectation < ' tcx > {
42824311 match self {
4283- NoExpectation | ExpectCastableToType ( .. ) => NoExpectation ,
4284- ExpectHasType ( t ) => ExpectHasType ( t )
4312+ ExpectHasType ( t ) => ExpectHasType ( t ) ,
4313+ _ => NoExpectation
42854314 }
42864315 }
42874316
@@ -4301,6 +4330,10 @@ impl<'tcx> Expectation<'tcx> {
43014330 ExpectHasType (
43024331 fcx. infcx ( ) . resolve_type_vars_if_possible ( & t) )
43034332 }
4333+ ExpectRvalueLikeUnsized ( t) => {
4334+ ExpectRvalueLikeUnsized (
4335+ fcx. infcx ( ) . resolve_type_vars_if_possible ( & t) )
4336+ }
43044337 }
43054338 }
43064339
@@ -4309,7 +4342,9 @@ impl<'tcx> Expectation<'tcx> {
43094342 {
43104343 match self . resolve ( fcx) {
43114344 NoExpectation => NoExpectation ,
4312- ExpectCastableToType ( ty) | ExpectHasType ( ty) => unpack ( ty) ,
4345+ ExpectCastableToType ( ty) |
4346+ ExpectHasType ( ty) |
4347+ ExpectRvalueLikeUnsized ( ty) => unpack ( ty) ,
43134348 }
43144349 }
43154350
@@ -4318,7 +4353,9 @@ impl<'tcx> Expectation<'tcx> {
43184353 {
43194354 match self . resolve ( fcx) {
43204355 NoExpectation => None ,
4321- ExpectCastableToType ( ty) | ExpectHasType ( ty) => unpack ( ty) ,
4356+ ExpectCastableToType ( ty) |
4357+ ExpectHasType ( ty) |
4358+ ExpectRvalueLikeUnsized ( ty) => unpack ( ty) ,
43224359 }
43234360 }
43244361}
@@ -4331,6 +4368,8 @@ impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
43314368 t. repr( tcx) ) ,
43324369 ExpectCastableToType ( t) => format ! ( "ExpectCastableToType({})" ,
43334370 t. repr( tcx) ) ,
4371+ ExpectRvalueLikeUnsized ( t) => format ! ( "ExpectRvalueLikeUnsized({})" ,
4372+ t. repr( tcx) ) ,
43344373 }
43354374 }
43364375}
0 commit comments