about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRyo Yoshida <low.ryoshida@gmail.com>2022-07-24 22:32:49 +0900
committerRyo Yoshida <low.ryoshida@gmail.com>2022-07-24 22:40:00 +0900
commit64758bd48195241dbf39a63974ecbcdcd151f399 (patch)
treeeacbb59080b41b4292db4e85ad9b81daa02ff119
parentfb063d360ce66e9f1316c3e64885e00344062e55 (diff)
downloadrust-64758bd48195241dbf39a63974ecbcdcd151f399.tar.gz
rust-64758bd48195241dbf39a63974ecbcdcd151f399.zip
Add info whether it's assignee expr to relevant HIR `Expr` variants
-rw-r--r--crates/hir-def/src/body/lower.rs39
-rw-r--r--crates/hir-def/src/expr.rs11
-rw-r--r--crates/hir-ty/src/infer/expr.rs16
3 files changed, 47 insertions, 19 deletions
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index b43699de120..66f9c24e872 100644
--- a/crates/hir-def/src/body/lower.rs
+++ b/crates/hir-def/src/body/lower.rs
@@ -96,6 +96,7 @@ pub(super) fn lower(
         expander,
         name_to_pat_grouping: Default::default(),
         is_lowering_inside_or_pat: false,
+        is_lowering_assignee_expr: false,
     }
     .collect(params, body)
 }
@@ -109,6 +110,7 @@ struct ExprCollector<'a> {
     // a poor-mans union-find?
     name_to_pat_grouping: FxHashMap<Name, Vec<PatId>>,
     is_lowering_inside_or_pat: bool,
+    is_lowering_assignee_expr: bool,
 }
 
 impl ExprCollector<'_> {
@@ -283,7 +285,10 @@ impl ExprCollector<'_> {
                 } else {
                     Box::default()
                 };
-                self.alloc_expr(Expr::Call { callee, args }, syntax_ptr)
+                self.alloc_expr(
+                    Expr::Call { callee, args, is_assignee_expr: self.is_lowering_assignee_expr },
+                    syntax_ptr,
+                )
             }
             ast::Expr::MethodCallExpr(e) => {
                 let receiver = self.collect_expr_opt(e.receiver());
@@ -359,6 +364,7 @@ impl ExprCollector<'_> {
             ast::Expr::RecordExpr(e) => {
                 let path =
                     e.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
+                let is_assignee_expr = self.is_lowering_assignee_expr;
                 let record_lit = if let Some(nfl) = e.record_expr_field_list() {
                     let fields = nfl
                         .fields()
@@ -379,9 +385,15 @@ impl ExprCollector<'_> {
                         .collect();
                     let spread = nfl.spread().map(|s| self.collect_expr(s));
                     let ellipsis = nfl.dotdot_token().is_some();
-                    Expr::RecordLit { path, fields, spread, ellipsis }
+                    Expr::RecordLit { path, fields, spread, ellipsis, is_assignee_expr }
                 } else {
-                    Expr::RecordLit { path, fields: Box::default(), spread: None, ellipsis: false }
+                    Expr::RecordLit {
+                        path,
+                        fields: Box::default(),
+                        spread: None,
+                        ellipsis: false,
+                        is_assignee_expr,
+                    }
                 };
 
                 self.alloc_expr(record_lit, syntax_ptr)
@@ -459,14 +471,21 @@ impl ExprCollector<'_> {
                 )
             }
             ast::Expr::BinExpr(e) => {
+                let op = e.op_kind();
+                if let Some(ast::BinaryOp::Assignment { op: None }) = op {
+                    self.is_lowering_assignee_expr = true;
+                }
                 let lhs = self.collect_expr_opt(e.lhs());
+                self.is_lowering_assignee_expr = false;
                 let rhs = self.collect_expr_opt(e.rhs());
-                let op = e.op_kind();
                 self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
             }
             ast::Expr::TupleExpr(e) => {
                 let exprs = e.fields().map(|expr| self.collect_expr(expr)).collect();
-                self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
+                self.alloc_expr(
+                    Expr::Tuple { exprs, is_assignee_expr: self.is_lowering_assignee_expr },
+                    syntax_ptr,
+                )
             }
             ast::Expr::BoxExpr(e) => {
                 let expr = self.collect_expr_opt(e.expr());
@@ -478,8 +497,14 @@ impl ExprCollector<'_> {
 
                 match kind {
                     ArrayExprKind::ElementList(e) => {
-                        let exprs = e.map(|expr| self.collect_expr(expr)).collect();
-                        self.alloc_expr(Expr::Array(Array::ElementList(exprs)), syntax_ptr)
+                        let elements = e.map(|expr| self.collect_expr(expr)).collect();
+                        self.alloc_expr(
+                            Expr::Array(Array::ElementList {
+                                elements,
+                                is_assignee_expr: self.is_lowering_assignee_expr,
+                            }),
+                            syntax_ptr,
+                        )
                     }
                     ArrayExprKind::Repeat { initializer, repeat } => {
                         let initializer = self.collect_expr_opt(initializer);
diff --git a/crates/hir-def/src/expr.rs b/crates/hir-def/src/expr.rs
index 145fe4c19db..c1b3788acb7 100644
--- a/crates/hir-def/src/expr.rs
+++ b/crates/hir-def/src/expr.rs
@@ -110,6 +110,7 @@ pub enum Expr {
     Call {
         callee: ExprId,
         args: Box<[ExprId]>,
+        is_assignee_expr: bool,
     },
     MethodCall {
         receiver: ExprId,
@@ -139,6 +140,7 @@ pub enum Expr {
         fields: Box<[RecordLitField]>,
         spread: Option<ExprId>,
         ellipsis: bool,
+        is_assignee_expr: bool,
     },
     Field {
         expr: ExprId,
@@ -197,6 +199,7 @@ pub enum Expr {
     },
     Tuple {
         exprs: Box<[ExprId]>,
+        is_assignee_expr: bool,
     },
     Unsafe {
         body: ExprId,
@@ -212,7 +215,7 @@ pub enum Expr {
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub enum Array {
-    ElementList(Box<[ExprId]>),
+    ElementList { elements: Box<[ExprId]>, is_assignee_expr: bool },
     Repeat { initializer: ExprId, repeat: ExprId },
 }
 
@@ -286,7 +289,7 @@ impl Expr {
                 f(*iterable);
                 f(*body);
             }
-            Expr::Call { callee, args } => {
+            Expr::Call { callee, args, .. } => {
                 f(*callee);
                 args.iter().copied().for_each(f);
             }
@@ -340,9 +343,9 @@ impl Expr {
             | Expr::Box { expr } => {
                 f(*expr);
             }
-            Expr::Tuple { exprs } => exprs.iter().copied().for_each(f),
+            Expr::Tuple { exprs, .. } => exprs.iter().copied().for_each(f),
             Expr::Array(a) => match a {
-                Array::ElementList(exprs) => exprs.iter().copied().for_each(f),
+                Array::ElementList { elements, .. } => elements.iter().copied().for_each(f),
                 Array::Repeat { initializer, repeat } => {
                     f(*initializer);
                     f(*repeat)
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 9debe835473..d164e64a8be 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -276,7 +276,7 @@ impl<'a> InferenceContext<'a> {
 
                 closure_ty
             }
-            Expr::Call { callee, args } => {
+            Expr::Call { callee, args, .. } => {
                 let callee_ty = self.infer_expr(*callee, &Expectation::none());
                 let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone());
                 let mut res = None;
@@ -693,7 +693,7 @@ impl<'a> InferenceContext<'a> {
                     self.err_ty()
                 }
             }
-            Expr::Tuple { exprs } => {
+            Expr::Tuple { exprs, .. } => {
                 let mut tys = match expected
                     .only_has_type(&mut self.table)
                     .as_ref()
@@ -724,12 +724,12 @@ impl<'a> InferenceContext<'a> {
 
                 let expected = Expectation::has_type(elem_ty.clone());
                 let len = match array {
-                    Array::ElementList(items) => {
-                        for &expr in items.iter() {
+                    Array::ElementList { elements, .. } => {
+                        for &expr in elements.iter() {
                             let cur_elem_ty = self.infer_expr_inner(expr, &expected);
                             coerce.coerce(self, Some(expr), &cur_elem_ty);
                         }
-                        consteval::usize_const(Some(items.len() as u128))
+                        consteval::usize_const(Some(elements.len() as u128))
                     }
                     &Array::Repeat { initializer, repeat } => {
                         self.infer_expr_coerce(initializer, &Expectation::has_type(elem_ty));
@@ -850,7 +850,7 @@ impl<'a> InferenceContext<'a> {
         let rhs_ty = self.resolve_ty_shallow(rhs_ty);
 
         let ty = match &self.body[lhs] {
-            Expr::Tuple { exprs } => {
+            Expr::Tuple { exprs, .. } => {
                 // We don't consider multiple ellipses. This is analogous to
                 // `hir_def::body::lower::ExprCollector::collect_tuple_pat()`.
                 let ellipsis = exprs.iter().position(|e| is_rest_expr(*e));
@@ -858,7 +858,7 @@ impl<'a> InferenceContext<'a> {
 
                 self.infer_tuple_pat_like(&rhs_ty, (), ellipsis, &exprs)
             }
-            Expr::Call { callee, args } => {
+            Expr::Call { callee, args, .. } => {
                 // Tuple structs
                 let path = match &self.body[*callee] {
                     Expr::Path(path) => Some(path),
@@ -872,7 +872,7 @@ impl<'a> InferenceContext<'a> {
 
                 self.infer_tuple_struct_pat_like(path, &rhs_ty, (), lhs, ellipsis, &args)
             }
-            Expr::Array(Array::ElementList(elements)) => {
+            Expr::Array(Array::ElementList { elements, .. }) => {
                 let elem_ty = match rhs_ty.kind(Interner) {
                     TyKind::Array(st, _) => st.clone(),
                     _ => self.err_ty(),