@@ -2221,6 +2221,60 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
22212221 }
22222222 }
22232223
2224+ fn is_place_expr ( & self , expr : & hir:: Expr ) -> bool {
2225+ match expr. node {
2226+ hir:: ExprPath ( hir:: QPath :: Resolved ( _, ref path) ) => {
2227+ match path. def {
2228+ Def :: Local ( ..) | Def :: Upvar ( ..) | Def :: Static ( ..) | Def :: Err => true ,
2229+ _ => false ,
2230+ }
2231+ }
2232+
2233+ hir:: ExprType ( ref e, _) => {
2234+ self . is_place_expr ( e)
2235+ }
2236+
2237+ hir:: ExprUnary ( hir:: UnDeref , _) |
2238+ hir:: ExprField ( ..) |
2239+ hir:: ExprTupField ( ..) |
2240+ hir:: ExprIndex ( ..) => {
2241+ true
2242+ }
2243+
2244+ // Partially qualified paths in expressions can only legally
2245+ // refer to associated items which are always rvalues.
2246+ hir:: ExprPath ( hir:: QPath :: TypeRelative ( ..) ) |
2247+
2248+ hir:: ExprCall ( ..) |
2249+ hir:: ExprMethodCall ( ..) |
2250+ hir:: ExprStruct ( ..) |
2251+ hir:: ExprTup ( ..) |
2252+ hir:: ExprIf ( ..) |
2253+ hir:: ExprMatch ( ..) |
2254+ hir:: ExprClosure ( ..) |
2255+ hir:: ExprBlock ( ..) |
2256+ hir:: ExprRepeat ( ..) |
2257+ hir:: ExprArray ( ..) |
2258+ hir:: ExprBreak ( ..) |
2259+ hir:: ExprAgain ( ..) |
2260+ hir:: ExprRet ( ..) |
2261+ hir:: ExprWhile ( ..) |
2262+ hir:: ExprLoop ( ..) |
2263+ hir:: ExprAssign ( ..) |
2264+ hir:: ExprInlineAsm ( ..) |
2265+ hir:: ExprAssignOp ( ..) |
2266+ hir:: ExprLit ( _) |
2267+ hir:: ExprUnary ( ..) |
2268+ hir:: ExprBox ( ..) |
2269+ hir:: ExprAddrOf ( ..) |
2270+ hir:: ExprBinary ( ..) |
2271+ hir:: ExprYield ( ..) |
2272+ hir:: ExprCast ( ..) => {
2273+ false
2274+ }
2275+ }
2276+ }
2277+
22242278 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait
22252279 /// returns a type of `&T`, but the actual type we assign to the
22262280 /// *expression* is `T`. So this function just peels off the return
@@ -3627,7 +3681,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
36273681 let hint = expected. only_has_type ( self ) . map_or ( NoExpectation , |ty| {
36283682 match ty. sty {
36293683 ty:: TyRef ( _, ref mt) | ty:: TyRawPtr ( ref mt) => {
3630- if self . tcx . expr_is_lval ( & oprnd) {
3684+ if self . is_place_expr ( & oprnd) {
36313685 // Lvalues may legitimately have unsized types.
36323686 // For example, dereferences of a fat pointer and
36333687 // the last field of a struct can be unsized.
@@ -3796,7 +3850,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
37963850 _ => {
37973851 // Only check this if not in an `if` condition, as the
37983852 // mistyped comparison help is more appropriate.
3799- if !self . tcx . expr_is_lval ( & lhs) {
3853+ if !self . is_place_expr ( & lhs) {
38003854 struct_span_err ! ( self . tcx. sess, expr. span, E0070 ,
38013855 "invalid left-hand side expression" )
38023856 . span_label ( expr. span , "left-hand of expression not valid" )
0 commit comments