Skip to content

Commit 0d04e63

Browse files
Merge remote-tracking branch 'origin/master' into sync-from-rust-2
2 parents dfe8449 + ac86b8e commit 0d04e63

File tree

12 files changed

+169
-64
lines changed

12 files changed

+169
-64
lines changed

crates/hir-def/src/body/lower.rs

+33-7
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ pub(super) fn lower(
9696
expander,
9797
name_to_pat_grouping: Default::default(),
9898
is_lowering_inside_or_pat: false,
99+
is_lowering_assignee_expr: false,
99100
}
100101
.collect(params, body)
101102
}
@@ -109,6 +110,7 @@ struct ExprCollector<'a> {
109110
// a poor-mans union-find?
110111
name_to_pat_grouping: FxHashMap<Name, Vec<PatId>>,
111112
is_lowering_inside_or_pat: bool,
113+
is_lowering_assignee_expr: bool,
112114
}
113115

114116
impl ExprCollector<'_> {
@@ -283,7 +285,10 @@ impl ExprCollector<'_> {
283285
} else {
284286
Box::default()
285287
};
286-
self.alloc_expr(Expr::Call { callee, args }, syntax_ptr)
288+
self.alloc_expr(
289+
Expr::Call { callee, args, is_assignee_expr: self.is_lowering_assignee_expr },
290+
syntax_ptr,
291+
)
287292
}
288293
ast::Expr::MethodCallExpr(e) => {
289294
let receiver = self.collect_expr_opt(e.receiver());
@@ -359,6 +364,7 @@ impl ExprCollector<'_> {
359364
ast::Expr::RecordExpr(e) => {
360365
let path =
361366
e.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
367+
let is_assignee_expr = self.is_lowering_assignee_expr;
362368
let record_lit = if let Some(nfl) = e.record_expr_field_list() {
363369
let fields = nfl
364370
.fields()
@@ -378,9 +384,16 @@ impl ExprCollector<'_> {
378384
})
379385
.collect();
380386
let spread = nfl.spread().map(|s| self.collect_expr(s));
381-
Expr::RecordLit { path, fields, spread }
387+
let ellipsis = nfl.dotdot_token().is_some();
388+
Expr::RecordLit { path, fields, spread, ellipsis, is_assignee_expr }
382389
} else {
383-
Expr::RecordLit { path, fields: Box::default(), spread: None }
390+
Expr::RecordLit {
391+
path,
392+
fields: Box::default(),
393+
spread: None,
394+
ellipsis: false,
395+
is_assignee_expr,
396+
}
384397
};
385398

386399
self.alloc_expr(record_lit, syntax_ptr)
@@ -458,14 +471,21 @@ impl ExprCollector<'_> {
458471
)
459472
}
460473
ast::Expr::BinExpr(e) => {
474+
let op = e.op_kind();
475+
if let Some(ast::BinaryOp::Assignment { op: None }) = op {
476+
self.is_lowering_assignee_expr = true;
477+
}
461478
let lhs = self.collect_expr_opt(e.lhs());
479+
self.is_lowering_assignee_expr = false;
462480
let rhs = self.collect_expr_opt(e.rhs());
463-
let op = e.op_kind();
464481
self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
465482
}
466483
ast::Expr::TupleExpr(e) => {
467484
let exprs = e.fields().map(|expr| self.collect_expr(expr)).collect();
468-
self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
485+
self.alloc_expr(
486+
Expr::Tuple { exprs, is_assignee_expr: self.is_lowering_assignee_expr },
487+
syntax_ptr,
488+
)
469489
}
470490
ast::Expr::BoxExpr(e) => {
471491
let expr = self.collect_expr_opt(e.expr());
@@ -477,8 +497,14 @@ impl ExprCollector<'_> {
477497

478498
match kind {
479499
ArrayExprKind::ElementList(e) => {
480-
let exprs = e.map(|expr| self.collect_expr(expr)).collect();
481-
self.alloc_expr(Expr::Array(Array::ElementList(exprs)), syntax_ptr)
500+
let elements = e.map(|expr| self.collect_expr(expr)).collect();
501+
self.alloc_expr(
502+
Expr::Array(Array::ElementList {
503+
elements,
504+
is_assignee_expr: self.is_lowering_assignee_expr,
505+
}),
506+
syntax_ptr,
507+
)
482508
}
483509
ArrayExprKind::Repeat { initializer, repeat } => {
484510
let initializer = self.collect_expr_opt(initializer);

crates/hir-def/src/expr.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ pub enum Expr {
110110
Call {
111111
callee: ExprId,
112112
args: Box<[ExprId]>,
113+
is_assignee_expr: bool,
113114
},
114115
MethodCall {
115116
receiver: ExprId,
@@ -138,6 +139,8 @@ pub enum Expr {
138139
path: Option<Box<Path>>,
139140
fields: Box<[RecordLitField]>,
140141
spread: Option<ExprId>,
142+
ellipsis: bool,
143+
is_assignee_expr: bool,
141144
},
142145
Field {
143146
expr: ExprId,
@@ -196,6 +199,7 @@ pub enum Expr {
196199
},
197200
Tuple {
198201
exprs: Box<[ExprId]>,
202+
is_assignee_expr: bool,
199203
},
200204
Unsafe {
201205
body: ExprId,
@@ -211,7 +215,7 @@ pub enum Expr {
211215

212216
#[derive(Debug, Clone, Eq, PartialEq)]
213217
pub enum Array {
214-
ElementList(Box<[ExprId]>),
218+
ElementList { elements: Box<[ExprId]>, is_assignee_expr: bool },
215219
Repeat { initializer: ExprId, repeat: ExprId },
216220
}
217221

@@ -285,7 +289,7 @@ impl Expr {
285289
f(*iterable);
286290
f(*body);
287291
}
288-
Expr::Call { callee, args } => {
292+
Expr::Call { callee, args, .. } => {
289293
f(*callee);
290294
args.iter().copied().for_each(f);
291295
}
@@ -339,9 +343,9 @@ impl Expr {
339343
| Expr::Box { expr } => {
340344
f(*expr);
341345
}
342-
Expr::Tuple { exprs } => exprs.iter().copied().for_each(f),
346+
Expr::Tuple { exprs, .. } => exprs.iter().copied().for_each(f),
343347
Expr::Array(a) => match a {
344-
Array::ElementList(exprs) => exprs.iter().copied().for_each(f),
348+
Array::ElementList { elements, .. } => elements.iter().copied().for_each(f),
345349
Array::Repeat { initializer, repeat } => {
346350
f(*initializer);
347351
f(*repeat)

crates/hir-ty/src/diagnostics/expr.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,10 @@ pub fn record_literal_missing_fields(
305305
expr: &Expr,
306306
) -> Option<(VariantId, Vec<LocalFieldId>, /*exhaustive*/ bool)> {
307307
let (fields, exhaustive) = match expr {
308-
Expr::RecordLit { path: _, fields, spread } => (fields, spread.is_none()),
308+
Expr::RecordLit { fields, spread, ellipsis, is_assignee_expr, .. } => {
309+
let exhaustive = if *is_assignee_expr { !*ellipsis } else { spread.is_none() };
310+
(fields, exhaustive)
311+
}
309312
_ => return None,
310313
};
311314

crates/hir-ty/src/infer/expr.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ impl<'a> InferenceContext<'a> {
276276

277277
closure_ty
278278
}
279-
Expr::Call { callee, args } => {
279+
Expr::Call { callee, args, .. } => {
280280
let callee_ty = self.infer_expr(*callee, &Expectation::none());
281281
let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone());
282282
let mut res = None;
@@ -421,7 +421,7 @@ impl<'a> InferenceContext<'a> {
421421
}
422422
TyKind::Never.intern(Interner)
423423
}
424-
Expr::RecordLit { path, fields, spread } => {
424+
Expr::RecordLit { path, fields, spread, .. } => {
425425
let (ty, def_id) = self.resolve_variant(path.as_deref(), false);
426426
if let Some(variant) = def_id {
427427
self.write_variant_resolution(tgt_expr.into(), variant);
@@ -693,7 +693,7 @@ impl<'a> InferenceContext<'a> {
693693
self.err_ty()
694694
}
695695
}
696-
Expr::Tuple { exprs } => {
696+
Expr::Tuple { exprs, .. } => {
697697
let mut tys = match expected
698698
.only_has_type(&mut self.table)
699699
.as_ref()
@@ -724,12 +724,12 @@ impl<'a> InferenceContext<'a> {
724724

725725
let expected = Expectation::has_type(elem_ty.clone());
726726
let len = match array {
727-
Array::ElementList(items) => {
728-
for &expr in items.iter() {
727+
Array::ElementList { elements, .. } => {
728+
for &expr in elements.iter() {
729729
let cur_elem_ty = self.infer_expr_inner(expr, &expected);
730730
coerce.coerce(self, Some(expr), &cur_elem_ty);
731731
}
732-
consteval::usize_const(Some(items.len() as u128))
732+
consteval::usize_const(Some(elements.len() as u128))
733733
}
734734
&Array::Repeat { initializer, repeat } => {
735735
self.infer_expr_coerce(initializer, &Expectation::has_type(elem_ty));
@@ -850,15 +850,15 @@ impl<'a> InferenceContext<'a> {
850850
let rhs_ty = self.resolve_ty_shallow(rhs_ty);
851851

852852
let ty = match &self.body[lhs] {
853-
Expr::Tuple { exprs } => {
853+
Expr::Tuple { exprs, .. } => {
854854
// We don't consider multiple ellipses. This is analogous to
855855
// `hir_def::body::lower::ExprCollector::collect_tuple_pat()`.
856856
let ellipsis = exprs.iter().position(|e| is_rest_expr(*e));
857857
let exprs: Vec<_> = exprs.iter().filter(|e| !is_rest_expr(**e)).copied().collect();
858858

859859
self.infer_tuple_pat_like(&rhs_ty, (), ellipsis, &exprs)
860860
}
861-
Expr::Call { callee, args } => {
861+
Expr::Call { callee, args, .. } => {
862862
// Tuple structs
863863
let path = match &self.body[*callee] {
864864
Expr::Path(path) => Some(path),
@@ -872,7 +872,7 @@ impl<'a> InferenceContext<'a> {
872872

873873
self.infer_tuple_struct_pat_like(path, &rhs_ty, (), lhs, ellipsis, &args)
874874
}
875-
Expr::Array(Array::ElementList(elements)) => {
875+
Expr::Array(Array::ElementList { elements, .. }) => {
876876
let elem_ty = match rhs_ty.kind(Interner) {
877877
TyKind::Array(st, _) => st.clone(),
878878
_ => self.err_ty(),

crates/ide-assists/src/handlers/add_missing_impl_members.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,16 @@ fn add_missing_impl_members_inner(
145145
Some(cap) => {
146146
let mut cursor = Cursor::Before(first_new_item.syntax());
147147
let placeholder;
148-
if let ast::AssocItem::Fn(func) = &first_new_item {
149-
if try_gen_trait_body(ctx, func, &trait_, &impl_def).is_none() {
150-
if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast)
151-
{
152-
if m.syntax().text() == "todo!()" {
153-
placeholder = m;
154-
cursor = Cursor::Replace(placeholder.syntax());
148+
if let DefaultMethods::No = mode {
149+
if let ast::AssocItem::Fn(func) = &first_new_item {
150+
if try_gen_trait_body(ctx, func, &trait_, &impl_def).is_none() {
151+
if let Some(m) =
152+
func.syntax().descendants().find_map(ast::MacroCall::cast)
153+
{
154+
if m.syntax().text() == "todo!()" {
155+
placeholder = m;
156+
cursor = Cursor::Replace(placeholder.syntax());
157+
}
155158
}
156159
}
157160
}

crates/ide-assists/src/utils/gen_trait_fn_body.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use syntax::{
55
ted,
66
};
77

8-
/// Generate custom trait bodies where possible.
8+
/// Generate custom trait bodies without default implementation where possible.
99
///
1010
/// Returns `Option` so that we can use `?` rather than `if let Some`. Returning
1111
/// `None` means that generating a custom trait body failed, and the body will remain
@@ -28,6 +28,7 @@ pub(crate) fn gen_trait_fn_body(
2828

2929
/// Generate a `Clone` impl based on the fields and members of the target type.
3030
fn gen_clone_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
31+
stdx::always!(func.name().map_or(false, |name| name.text() == "clone"));
3132
fn gen_clone_call(target: ast::Expr) -> ast::Expr {
3233
let method = make::name_ref("clone");
3334
make::expr_method_call(target, method, make::arg_list(None))
@@ -339,6 +340,7 @@ fn gen_default_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
339340

340341
/// Generate a `Hash` impl based on the fields and members of the target type.
341342
fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
343+
stdx::always!(func.name().map_or(false, |name| name.text() == "hash"));
342344
fn gen_hash_call(target: ast::Expr) -> ast::Stmt {
343345
let method = make::name_ref("hash");
344346
let arg = make::expr_path(make::ext::ident_path("state"));
@@ -394,9 +396,7 @@ fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
394396

395397
/// Generate a `PartialEq` impl based on the fields and members of the target type.
396398
fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
397-
if func.name().map_or(false, |name| name.text() == "ne") {
398-
return None;
399-
}
399+
stdx::always!(func.name().map_or(false, |name| name.text() == "eq"));
400400
fn gen_eq_chain(expr: Option<ast::Expr>, cmp: ast::Expr) -> Option<ast::Expr> {
401401
match expr {
402402
Some(expr) => Some(make::expr_bin_op(expr, BinaryOp::LogicOp(LogicOp::And), cmp)),
@@ -573,6 +573,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
573573
}
574574

575575
fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
576+
stdx::always!(func.name().map_or(false, |name| name.text() == "partial_cmp"));
576577
fn gen_partial_eq_match(match_target: ast::Expr) -> Option<ast::Stmt> {
577578
let mut arms = vec![];
578579

@@ -643,7 +644,7 @@ fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
643644
make::block_expr(stmts.into_iter(), tail).indent(ast::edit::IndentLevel(1))
644645
}
645646

646-
// No fields in the body means there's nothing to hash.
647+
// No fields in the body means there's nothing to compare.
647648
None => {
648649
let expr = make::expr_literal("true").into();
649650
make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1))

crates/ide-completion/src/render.rs

+37-3
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ pub(crate) fn render_field(
121121
let mut item = CompletionItem::new(
122122
SymbolKind::Field,
123123
ctx.source_range(),
124-
receiver.map_or_else(|| name.clone(), |receiver| format!("{}.{}", receiver, name).into()),
124+
field_with_receiver(receiver.as_ref(), &name),
125125
);
126126
item.set_relevance(CompletionRelevance {
127127
type_match: compute_type_match(ctx.completion, ty),
@@ -132,7 +132,7 @@ pub(crate) fn render_field(
132132
.set_documentation(field.docs(ctx.db()))
133133
.set_deprecated(is_deprecated)
134134
.lookup_by(name.clone());
135-
item.insert_text(escaped_name);
135+
item.insert_text(field_with_receiver(receiver.as_ref(), &escaped_name));
136136
if let Some(receiver) = &dot_access.receiver {
137137
if let Some(original) = ctx.completion.sema.original_ast_node(receiver.clone()) {
138138
if let Some(ref_match) = compute_ref_match(ctx.completion, ty) {
@@ -143,6 +143,11 @@ pub(crate) fn render_field(
143143
item.build()
144144
}
145145

146+
fn field_with_receiver(receiver: Option<&hir::Name>, field_name: &str) -> SmolStr {
147+
receiver
148+
.map_or_else(|| field_name.into(), |receiver| format!("{}.{}", receiver, field_name).into())
149+
}
150+
146151
pub(crate) fn render_tuple_field(
147152
ctx: RenderContext<'_>,
148153
receiver: Option<hir::Name>,
@@ -152,7 +157,7 @@ pub(crate) fn render_tuple_field(
152157
let mut item = CompletionItem::new(
153158
SymbolKind::Field,
154159
ctx.source_range(),
155-
receiver.map_or_else(|| field.to_string(), |receiver| format!("{}.{}", receiver, field)),
160+
field_with_receiver(receiver.as_ref(), &field.to_string()),
156161
);
157162
item.detail(ty.display(ctx.db()).to_string()).lookup_by(field.to_string());
158163
item.build()
@@ -1873,6 +1878,35 @@ impl r#trait for r#struct { type t$0 }
18731878
struct r#struct {}
18741879
trait r#trait { type r#type; }
18751880
impl r#trait for r#struct { type r#type = $0; }
1881+
"#,
1882+
)
1883+
}
1884+
1885+
#[test]
1886+
fn field_access_includes_self() {
1887+
check_edit(
1888+
"length",
1889+
r#"
1890+
struct S {
1891+
length: i32
1892+
}
1893+
1894+
impl S {
1895+
fn some_fn(&self) {
1896+
let l = len$0
1897+
}
1898+
}
1899+
"#,
1900+
r#"
1901+
struct S {
1902+
length: i32
1903+
}
1904+
1905+
impl S {
1906+
fn some_fn(&self) {
1907+
let l = self.length
1908+
}
1909+
}
18761910
"#,
18771911
)
18781912
}

0 commit comments

Comments
 (0)