Skip to content

Commit 046077b

Browse files
committed
enum 3
1 parent c40c06d commit 046077b

File tree

11 files changed

+120
-76
lines changed

11 files changed

+120
-76
lines changed

crates/hir-def/src/expr_store.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use crate::{
3232
expr_store::path::Path,
3333
hir::{
3434
Array, AsmOperand, Binding, BindingId, Expr, ExprId, ExprOrPatId, Label, LabelId, Pat,
35-
PatId, RecordFieldPat, Statement,
35+
PatId, RecordFieldPat, RecordSpread, Statement,
3636
},
3737
nameres::{DefMap, block_def_map},
3838
type_ref::{LifetimeRef, LifetimeRefId, PathId, TypeRef, TypeRefId},
@@ -575,8 +575,8 @@ impl ExpressionStore {
575575
for field in fields.iter() {
576576
f(field.expr);
577577
}
578-
if let &Some(expr) = spread {
579-
f(expr);
578+
if let RecordSpread::Expr(ref expr) = *spread {
579+
f(*expr);
580580
}
581581
}
582582
Expr::Closure { body, .. } => {
@@ -706,8 +706,8 @@ impl ExpressionStore {
706706
for field in fields.iter() {
707707
f(field.expr);
708708
}
709-
if let &Some(expr) = spread {
710-
f(expr);
709+
if let RecordSpread::Expr(ref expr) = *spread {
710+
f(*expr);
711711
}
712712
}
713713
Expr::Closure { body, .. } => {

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ use crate::{
4747
hir::{
4848
Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy, ClosureKind,
4949
Expr, ExprId, Item, Label, LabelId, Literal, MatchArm, Movability, OffsetOf, Pat, PatId,
50-
RecordFieldPat, RecordLitField, Statement, generics::GenericParams,
50+
RecordFieldPat, RecordLitField, RecordSpread, Statement, generics::GenericParams,
5151
},
5252
item_scope::BuiltinShadowMode,
5353
item_tree::FieldsShape,
@@ -1232,16 +1232,16 @@ impl<'db> ExprCollector<'db> {
12321232
Some(RecordLitField { name, expr })
12331233
})
12341234
.collect();
1235-
let spread = nfl.spread().map(|s| self.collect_expr(s));
1235+
let spread_expr = nfl.spread().map(|s| self.collect_expr(s));
12361236
let has_spread_syntax = nfl.dotdot_token().is_some();
1237-
Expr::RecordLit { path, fields, spread, has_spread_syntax }
1237+
let spread = match (spread_expr, has_spread_syntax) {
1238+
(None, false) => RecordSpread::None,
1239+
(None, true) => RecordSpread::Empty,
1240+
(Some(expr), _) => RecordSpread::Expr(expr),
1241+
};
1242+
Expr::RecordLit { path, fields, spread }
12381243
} else {
1239-
Expr::RecordLit {
1240-
path,
1241-
fields: Box::default(),
1242-
spread: None,
1243-
has_spread_syntax: false,
1244-
}
1244+
Expr::RecordLit { path, fields: Box::default(), spread: RecordSpread::None }
12451245
};
12461246

12471247
self.alloc_expr(record_lit, syntax_ptr)

crates/hir-def/src/expr_store/lower/format_args.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ use crate::{
1010
builtin_type::BuiltinUint,
1111
expr_store::{HygieneId, lower::ExprCollector, path::Path},
1212
hir::{
13-
Array, BindingAnnotation, Expr, ExprId, Literal, Pat, RecordLitField, Statement,
13+
Array, BindingAnnotation, Expr, ExprId, Literal, Pat, RecordLitField, RecordSpread,
14+
Statement,
1415
format_args::{
1516
self, FormatAlignment, FormatArgs, FormatArgsPiece, FormatArgument, FormatArgumentKind,
1617
FormatArgumentsCollector, FormatCount, FormatDebugHex, FormatOptions,
@@ -869,8 +870,7 @@ impl<'db> ExprCollector<'db> {
869870
self.alloc_expr_desugared(Expr::RecordLit {
870871
path: self.lang_path(lang_items.FormatPlaceholder).map(Box::new),
871872
fields: Box::new([position, flags, precision, width]),
872-
spread: None,
873-
has_spread_syntax: false,
873+
spread: RecordSpread::None,
874874
})
875875
} else {
876876
let format_placeholder_new =

crates/hir-def/src/expr_store/pretty.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ use crate::{
1616
attrs::AttrFlags,
1717
expr_store::path::{GenericArg, GenericArgs},
1818
hir::{
19-
Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, Movability, Statement,
19+
Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, Movability, RecordSpread,
20+
Statement,
2021
generics::{GenericParams, WherePredicate},
2122
},
2223
lang_item::LangItemTarget,
@@ -665,7 +666,7 @@ impl Printer<'_> {
665666
self.print_expr_in(prec, *expr);
666667
}
667668
}
668-
Expr::RecordLit { path, fields, spread, has_spread_syntax } => {
669+
Expr::RecordLit { path, fields, spread } => {
669670
match path {
670671
Some(path) => self.print_path(path),
671672
None => w!(self, "�"),
@@ -679,13 +680,17 @@ impl Printer<'_> {
679680
p.print_expr(field.expr);
680681
wln!(p, ",");
681682
}
682-
if let Some(spread) = spread {
683-
w!(p, "..");
684-
p.print_expr(*spread);
685-
wln!(p);
686-
} else if *has_spread_syntax {
687-
w!(p, "..");
688-
wln!(p);
683+
match spread {
684+
RecordSpread::None => {}
685+
RecordSpread::Empty => {
686+
w!(p, "..");
687+
wln!(p);
688+
}
689+
RecordSpread::Expr(spread_expr) => {
690+
w!(p, "..");
691+
p.print_expr(*spread_expr);
692+
wln!(p);
693+
}
689694
}
690695
});
691696
w!(self, "}}");

crates/hir-def/src/hir.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,13 @@ impl From<ast::LiteralKind> for Literal {
187187
}
188188
}
189189

190+
#[derive(Debug, Clone, Eq, PartialEq)]
191+
pub enum RecordSpread {
192+
None,
193+
Empty,
194+
Expr(ExprId),
195+
}
196+
190197
#[derive(Debug, Clone, Eq, PartialEq)]
191198
pub enum Expr {
192199
/// This is produced if the syntax tree does not have a required expression piece.
@@ -259,8 +266,7 @@ pub enum Expr {
259266
RecordLit {
260267
path: Option<Box<Path>>,
261268
fields: Box<[RecordLitField]>,
262-
spread: Option<ExprId>,
263-
has_spread_syntax: bool,
269+
spread: RecordSpread,
264270
},
265271
Field {
266272
expr: ExprId,

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

Lines changed: 27 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use crate::{
4141
pub(crate) use hir_def::{
4242
LocalFieldId, VariantId,
4343
expr_store::Body,
44-
hir::{Expr, ExprId, MatchArm, Pat, PatId, Statement},
44+
hir::{Expr, ExprId, MatchArm, Pat, PatId, RecordSpread, Statement},
4545
};
4646

4747
pub enum BodyValidationDiagnostic {
@@ -558,10 +558,8 @@ pub fn record_literal_missing_fields(
558558
id: ExprId,
559559
expr: &Expr,
560560
) -> Option<(VariantId, Vec<LocalFieldId>)> {
561-
let (fields, spread, has_spread_syntax) = match expr {
562-
Expr::RecordLit { fields, spread, has_spread_syntax, .. } => {
563-
(fields, spread, *has_spread_syntax)
564-
}
561+
let (fields, spread) = match expr {
562+
Expr::RecordLit { fields, spread, .. } => (fields, spread),
565563
_ => return None,
566564
};
567565

@@ -573,13 +571,17 @@ pub fn record_literal_missing_fields(
573571
let variant_data = variant_def.fields(db);
574572

575573
let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
574+
// don't suggest fields if:
575+
// - has ..expr
576+
// - has default value + ..
577+
// - already in code
576578
let missed_fields: Vec<LocalFieldId> = variant_data
577579
.fields()
578580
.iter()
579581
.filter_map(|(f, d)| {
580582
if specified_fields.contains(&d.name)
581-
|| spread.is_some()
582-
|| (d.has_default_value && has_spread_syntax)
583+
|| matches!(spread, RecordSpread::Expr(_))
584+
|| (d.has_default_value && matches!(spread, RecordSpread::Empty))
583585
{
584586
None
585587
} else {
@@ -599,10 +601,8 @@ pub fn record_literal_matched_fields(
599601
id: ExprId,
600602
expr: &Expr,
601603
) -> Option<(VariantId, Vec<LocalFieldId>)> {
602-
let (fields, spread, has_spread_syntax) = match expr {
603-
Expr::RecordLit { fields, spread, has_spread_syntax, .. } => {
604-
(fields, spread, *has_spread_syntax)
605-
}
604+
let (fields, _spread) = match expr {
605+
Expr::RecordLit { fields, spread, .. } => (fields, spread),
606606
_ => return None,
607607
};
608608

@@ -614,19 +614,12 @@ pub fn record_literal_matched_fields(
614614
let variant_data = variant_def.fields(db);
615615

616616
let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
617+
// suggest fields if:
618+
// - not in code
617619
let matched_fields: Vec<LocalFieldId> = variant_data
618620
.fields()
619621
.iter()
620-
.filter_map(|(f, d)| {
621-
if !specified_fields.contains(&d.name)
622-
&& (spread.is_some() || has_spread_syntax)
623-
&& !(d.has_default_value && has_spread_syntax)
624-
{
625-
Some(f)
626-
} else {
627-
None
628-
}
629-
})
622+
.filter_map(|(f, d)| (!specified_fields.contains(&d.name)).then_some(f))
630623
.collect();
631624
if matched_fields.is_empty() {
632625
return None;
@@ -640,7 +633,7 @@ pub fn record_pattern_missing_fields(
640633
id: PatId,
641634
pat: &Pat,
642635
) -> Option<(VariantId, Vec<LocalFieldId>)> {
643-
let (fields, ellipsis) = match pat {
636+
let (fields, _ellipsis) = match pat {
644637
Pat::Record { path: _, args, ellipsis } => (args, *ellipsis),
645638
_ => return None,
646639
};
@@ -653,14 +646,13 @@ pub fn record_pattern_missing_fields(
653646
let variant_data = variant_def.fields(db);
654647

655648
let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
649+
// suggest fields if:
650+
// - not in code
651+
// Note: ellipsis (..) is ignored - we still want to suggest all unspecified fields
656652
let missed_fields: Vec<LocalFieldId> = variant_data
657653
.fields()
658654
.iter()
659-
.filter_map(
660-
|(f, d)| {
661-
if specified_fields.contains(&d.name) || ellipsis { None } else { Some(f) }
662-
},
663-
)
655+
.filter_map(|(f, d)| if specified_fields.contains(&d.name) { None } else { Some(f) })
664656
.collect();
665657
if missed_fields.is_empty() {
666658
return None;
@@ -674,7 +666,7 @@ pub fn record_pattern_matched_fields(
674666
id: PatId,
675667
pat: &Pat,
676668
) -> Option<(VariantId, Vec<LocalFieldId>)> {
677-
let (fields, ellipsis) = match pat {
669+
let (fields, _ellipsis) = match pat {
678670
Pat::Record { path: _, args, ellipsis } => (args, *ellipsis),
679671
_ => return None,
680672
};
@@ -687,14 +679,13 @@ pub fn record_pattern_matched_fields(
687679
let variant_data = variant_def.fields(db);
688680

689681
let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
690-
let matched_fields: Vec<LocalFieldId> =
691-
variant_data
692-
.fields()
693-
.iter()
694-
.filter_map(|(f, d)| {
695-
if !specified_fields.contains(&d.name) && ellipsis { Some(f) } else { None }
696-
})
697-
.collect();
682+
// suggest fields if:
683+
// - not in code
684+
let matched_fields: Vec<LocalFieldId> = variant_data
685+
.fields()
686+
.iter()
687+
.filter_map(|(f, d)| if !specified_fields.contains(&d.name) { Some(f) } else { None })
688+
.collect();
698689
if matched_fields.is_empty() {
699690
return None;
700691
}

crates/hir-ty/src/infer/closure/analysis.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use hir_def::{
88
expr_store::path::Path,
99
hir::{
1010
Array, AsmOperand, BinaryOp, BindingId, CaptureBy, Expr, ExprId, ExprOrPatId, Pat, PatId,
11-
Statement, UnaryOp,
11+
RecordSpread, Statement, UnaryOp,
1212
},
1313
item_tree::FieldsShape,
1414
resolver::ValueNs,
@@ -627,7 +627,7 @@ impl<'db> InferenceContext<'_, 'db> {
627627
self.consume_expr(expr);
628628
}
629629
Expr::RecordLit { fields, spread, .. } => {
630-
if let &Some(expr) = spread {
630+
if let RecordSpread::Expr(expr) = *spread {
631631
self.consume_expr(expr);
632632
}
633633
self.consume_exprs(fields.iter().map(|it| it.expr));

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use hir_def::{
88
expr_store::path::{GenericArgs as HirGenericArgs, Path},
99
hir::{
1010
Array, AsmOperand, AsmOptions, BinaryOp, BindingAnnotation, Expr, ExprId, ExprOrPatId,
11-
LabelId, Literal, Pat, PatId, Statement, UnaryOp,
11+
LabelId, Literal, Pat, PatId, RecordSpread, Statement, UnaryOp,
1212
},
1313
resolver::ValueNs,
1414
};
@@ -657,8 +657,8 @@ impl<'db> InferenceContext<'_, 'db> {
657657
}
658658
}
659659
}
660-
if let Some(expr) = spread {
661-
self.infer_expr(*expr, &Expectation::has_type(ty), ExprIsRead::Yes);
660+
if let RecordSpread::Expr(expr) = *spread {
661+
self.infer_expr(expr, &Expectation::has_type(ty), ExprIsRead::Yes);
662662
}
663663
ty
664664
}

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
//! between `Deref` and `DerefMut` or `Index` and `IndexMut` or similar.
33
44
use hir_def::hir::{
5-
Array, AsmOperand, BinaryOp, BindingAnnotation, Expr, ExprId, Pat, PatId, Statement, UnaryOp,
5+
Array, AsmOperand, BinaryOp, BindingAnnotation, Expr, ExprId, Pat, PatId, RecordSpread,
6+
Statement, UnaryOp,
67
};
78
use rustc_ast_ir::Mutability;
89

@@ -133,7 +134,10 @@ impl<'db> InferenceContext<'_, 'db> {
133134
self.infer_mut_expr(*expr, Mutability::Not);
134135
}
135136
Expr::RecordLit { path: _, fields, spread, .. } => {
136-
self.infer_mut_not_expr_iter(fields.iter().map(|it| it.expr).chain(*spread))
137+
self.infer_mut_not_expr_iter(fields.iter().map(|it| it.expr));
138+
if let RecordSpread::Expr(expr) = *spread {
139+
self.infer_mut_not_expr_iter(std::iter::once(expr));
140+
}
137141
}
138142
&Expr::Index { base, index } => {
139143
if mutability == Mutability::Mut {

crates/hir-ty/src/mir/lower.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use hir_def::{
99
expr_store::{Body, ExpressionStore, HygieneId, path::Path},
1010
hir::{
1111
ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ExprId, LabelId, Literal, MatchArm,
12-
Pat, PatId, RecordFieldPat, RecordLitField,
12+
Pat, PatId, RecordFieldPat, RecordLitField, RecordSpread,
1313
},
1414
item_tree::FieldsShape,
1515
lang_item::LangItems,
@@ -868,15 +868,15 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
868868
Expr::Become { .. } => not_supported!("tail-calls"),
869869
Expr::Yield { .. } => not_supported!("yield"),
870870
Expr::RecordLit { fields, path, spread, .. } => {
871-
let spread_place = match spread {
872-
&Some(it) => {
871+
let spread_place = match *spread {
872+
RecordSpread::Expr(it) => {
873873
let Some((p, c)) = self.lower_expr_as_place(current, it, true)? else {
874874
return Ok(None);
875875
};
876876
current = c;
877877
Some(p)
878878
}
879-
None => None,
879+
RecordSpread::None | RecordSpread::Empty => None,
880880
};
881881
let variant_id =
882882
self.infer.variant_resolution_for_expr(expr_id).ok_or_else(|| match path {

0 commit comments

Comments
 (0)