Add info whether it's assignee expr to relevant HIR Expr variants

This commit is contained in:
Ryo Yoshida 2022-07-24 22:32:49 +09:00
parent fb063d360c
commit 64758bd481
No known key found for this signature in database
GPG key ID: E25698A930586171
3 changed files with 48 additions and 20 deletions

View file

@ -96,6 +96,7 @@ pub(super) fn lower(
expander, expander,
name_to_pat_grouping: Default::default(), name_to_pat_grouping: Default::default(),
is_lowering_inside_or_pat: false, is_lowering_inside_or_pat: false,
is_lowering_assignee_expr: false,
} }
.collect(params, body) .collect(params, body)
} }
@ -109,6 +110,7 @@ struct ExprCollector<'a> {
// a poor-mans union-find? // a poor-mans union-find?
name_to_pat_grouping: FxHashMap<Name, Vec<PatId>>, name_to_pat_grouping: FxHashMap<Name, Vec<PatId>>,
is_lowering_inside_or_pat: bool, is_lowering_inside_or_pat: bool,
is_lowering_assignee_expr: bool,
} }
impl ExprCollector<'_> { impl ExprCollector<'_> {
@ -283,7 +285,10 @@ impl ExprCollector<'_> {
} else { } else {
Box::default() 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) => { ast::Expr::MethodCallExpr(e) => {
let receiver = self.collect_expr_opt(e.receiver()); let receiver = self.collect_expr_opt(e.receiver());
@ -359,6 +364,7 @@ impl ExprCollector<'_> {
ast::Expr::RecordExpr(e) => { ast::Expr::RecordExpr(e) => {
let path = let path =
e.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new); 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 record_lit = if let Some(nfl) = e.record_expr_field_list() {
let fields = nfl let fields = nfl
.fields() .fields()
@ -379,9 +385,15 @@ impl ExprCollector<'_> {
.collect(); .collect();
let spread = nfl.spread().map(|s| self.collect_expr(s)); let spread = nfl.spread().map(|s| self.collect_expr(s));
let ellipsis = nfl.dotdot_token().is_some(); let ellipsis = nfl.dotdot_token().is_some();
Expr::RecordLit { path, fields, spread, ellipsis } Expr::RecordLit { path, fields, spread, ellipsis, is_assignee_expr }
} else { } 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) self.alloc_expr(record_lit, syntax_ptr)
@ -459,14 +471,21 @@ impl ExprCollector<'_> {
) )
} }
ast::Expr::BinExpr(e) => { ast::Expr::BinExpr(e) => {
let lhs = self.collect_expr_opt(e.lhs());
let rhs = self.collect_expr_opt(e.rhs());
let op = e.op_kind(); 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());
self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr) self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
} }
ast::Expr::TupleExpr(e) => { ast::Expr::TupleExpr(e) => {
let exprs = e.fields().map(|expr| self.collect_expr(expr)).collect(); 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) => { ast::Expr::BoxExpr(e) => {
let expr = self.collect_expr_opt(e.expr()); let expr = self.collect_expr_opt(e.expr());
@ -478,8 +497,14 @@ impl ExprCollector<'_> {
match kind { match kind {
ArrayExprKind::ElementList(e) => { ArrayExprKind::ElementList(e) => {
let exprs = e.map(|expr| self.collect_expr(expr)).collect(); let elements = e.map(|expr| self.collect_expr(expr)).collect();
self.alloc_expr(Expr::Array(Array::ElementList(exprs)), syntax_ptr) self.alloc_expr(
Expr::Array(Array::ElementList {
elements,
is_assignee_expr: self.is_lowering_assignee_expr,
}),
syntax_ptr,
)
} }
ArrayExprKind::Repeat { initializer, repeat } => { ArrayExprKind::Repeat { initializer, repeat } => {
let initializer = self.collect_expr_opt(initializer); let initializer = self.collect_expr_opt(initializer);

View file

@ -110,6 +110,7 @@ pub enum Expr {
Call { Call {
callee: ExprId, callee: ExprId,
args: Box<[ExprId]>, args: Box<[ExprId]>,
is_assignee_expr: bool,
}, },
MethodCall { MethodCall {
receiver: ExprId, receiver: ExprId,
@ -139,6 +140,7 @@ pub enum Expr {
fields: Box<[RecordLitField]>, fields: Box<[RecordLitField]>,
spread: Option<ExprId>, spread: Option<ExprId>,
ellipsis: bool, ellipsis: bool,
is_assignee_expr: bool,
}, },
Field { Field {
expr: ExprId, expr: ExprId,
@ -197,6 +199,7 @@ pub enum Expr {
}, },
Tuple { Tuple {
exprs: Box<[ExprId]>, exprs: Box<[ExprId]>,
is_assignee_expr: bool,
}, },
Unsafe { Unsafe {
body: ExprId, body: ExprId,
@ -212,7 +215,7 @@ pub enum Expr {
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
pub enum Array { pub enum Array {
ElementList(Box<[ExprId]>), ElementList { elements: Box<[ExprId]>, is_assignee_expr: bool },
Repeat { initializer: ExprId, repeat: ExprId }, Repeat { initializer: ExprId, repeat: ExprId },
} }
@ -286,7 +289,7 @@ impl Expr {
f(*iterable); f(*iterable);
f(*body); f(*body);
} }
Expr::Call { callee, args } => { Expr::Call { callee, args, .. } => {
f(*callee); f(*callee);
args.iter().copied().for_each(f); args.iter().copied().for_each(f);
} }
@ -340,9 +343,9 @@ impl Expr {
| Expr::Box { expr } => { | Expr::Box { expr } => {
f(*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 { 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 } => { Array::Repeat { initializer, repeat } => {
f(*initializer); f(*initializer);
f(*repeat) f(*repeat)

View file

@ -276,7 +276,7 @@ impl<'a> InferenceContext<'a> {
closure_ty closure_ty
} }
Expr::Call { callee, args } => { Expr::Call { callee, args, .. } => {
let callee_ty = self.infer_expr(*callee, &Expectation::none()); let callee_ty = self.infer_expr(*callee, &Expectation::none());
let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone()); let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone());
let mut res = None; let mut res = None;
@ -693,7 +693,7 @@ impl<'a> InferenceContext<'a> {
self.err_ty() self.err_ty()
} }
} }
Expr::Tuple { exprs } => { Expr::Tuple { exprs, .. } => {
let mut tys = match expected let mut tys = match expected
.only_has_type(&mut self.table) .only_has_type(&mut self.table)
.as_ref() .as_ref()
@ -724,12 +724,12 @@ impl<'a> InferenceContext<'a> {
let expected = Expectation::has_type(elem_ty.clone()); let expected = Expectation::has_type(elem_ty.clone());
let len = match array { let len = match array {
Array::ElementList(items) => { Array::ElementList { elements, .. } => {
for &expr in items.iter() { for &expr in elements.iter() {
let cur_elem_ty = self.infer_expr_inner(expr, &expected); let cur_elem_ty = self.infer_expr_inner(expr, &expected);
coerce.coerce(self, Some(expr), &cur_elem_ty); 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 } => { &Array::Repeat { initializer, repeat } => {
self.infer_expr_coerce(initializer, &Expectation::has_type(elem_ty)); 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 rhs_ty = self.resolve_ty_shallow(rhs_ty);
let ty = match &self.body[lhs] { let ty = match &self.body[lhs] {
Expr::Tuple { exprs } => { Expr::Tuple { exprs, .. } => {
// We don't consider multiple ellipses. This is analogous to // We don't consider multiple ellipses. This is analogous to
// `hir_def::body::lower::ExprCollector::collect_tuple_pat()`. // `hir_def::body::lower::ExprCollector::collect_tuple_pat()`.
let ellipsis = exprs.iter().position(|e| is_rest_expr(*e)); 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) self.infer_tuple_pat_like(&rhs_ty, (), ellipsis, &exprs)
} }
Expr::Call { callee, args } => { Expr::Call { callee, args, .. } => {
// Tuple structs // Tuple structs
let path = match &self.body[*callee] { let path = match &self.body[*callee] {
Expr::Path(path) => Some(path), 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) 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) { let elem_ty = match rhs_ty.kind(Interner) {
TyKind::Array(st, _) => st.clone(), TyKind::Array(st, _) => st.clone(),
_ => self.err_ty(), _ => self.err_ty(),