@@ -1681,41 +1681,81 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
1681
1681
// the struct literal syntax at all, as that will cause a subsequent error.
1682
1682
let fields = this.r.field_idents(def_id);
1683
1683
let has_fields = fields.as_ref().is_some_and(|f| !f.is_empty());
1684
- let (fields, applicability) = match fields {
1685
- Some(fields) => {
1686
- let fields = if let Some(old_fields) = old_fields {
1687
- fields
1688
- .iter()
1689
- .enumerate()
1690
- .map(|(idx, new)| (new, old_fields.get(idx)))
1691
- .map(|(new, old)| {
1692
- if let Some(Some(old)) = old
1693
- && new.as_str() != old
1694
- {
1695
- format!("{new}: {old}")
1696
- } else {
1697
- new.to_string()
1698
- }
1699
- })
1700
- .collect::<Vec<String>>()
1701
- } else {
1702
- fields
1703
- .iter()
1704
- .map(|f| format!("{f}{tail}"))
1705
- .collect::<Vec<String>>()
1706
- };
1707
-
1708
- (fields.join(", "), applicability)
1709
- }
1710
- None => ("/* fields */".to_string(), Applicability::HasPlaceholders),
1711
- };
1712
- let pad = if has_fields { " " } else { "" };
1713
- err.span_suggestion(
1684
+
1685
+ if let PathSource::Expr(Some(Expr {
1686
+ kind: ExprKind::Call(path, args),
1714
1687
span,
1715
- format!("use struct {descr} syntax instead"),
1716
- format!("{path_str} {{{pad}{fields}{pad}}}"),
1717
- applicability,
1718
- );
1688
+ ..
1689
+ })) = source
1690
+ && !args.is_empty()
1691
+ && let Some(fields) = &fields
1692
+ && args.len() == fields.len()
1693
+ // Make sure we have same number of args as fields
1694
+ {
1695
+ let path_span = path.span;
1696
+ let mut parts = Vec::new();
1697
+
1698
+ // Start with the opening brace
1699
+ parts.push((
1700
+ path_span.shrink_to_hi().until(args[0].span),
1701
+ "{".to_owned(),
1702
+ ));
1703
+
1704
+ for (field, arg) in fields.iter().zip(args.iter()) {
1705
+ // Add the field name before the argument
1706
+ parts.push((arg.span.shrink_to_lo(), format!("{}: ", field)));
1707
+ }
1708
+
1709
+ // Add the closing brace
1710
+ parts.push((
1711
+ args.last().unwrap().span.shrink_to_hi().until(span.shrink_to_hi()),
1712
+ "}".to_owned(),
1713
+ ));
1714
+
1715
+ err.multipart_suggestion_verbose(
1716
+ format!("use struct {descr} syntax instead of calling"),
1717
+ parts,
1718
+ applicability,
1719
+ );
1720
+ } else {
1721
+ let (fields, applicability) = match fields {
1722
+ Some(fields) => {
1723
+ let fields = if let Some(old_fields) = old_fields {
1724
+ fields
1725
+ .iter()
1726
+ .enumerate()
1727
+ .map(|(idx, new)| (new, old_fields.get(idx)))
1728
+ .map(|(new, old)| {
1729
+ if let Some(Some(old)) = old
1730
+ && new.as_str() != old
1731
+ {
1732
+ format!("{new}: {old}")
1733
+ } else {
1734
+ new.to_string()
1735
+ }
1736
+ })
1737
+ .collect::<Vec<String>>()
1738
+ } else {
1739
+ fields
1740
+ .iter()
1741
+ .map(|f| format!("{f}{tail}"))
1742
+ .collect::<Vec<String>>()
1743
+ };
1744
+
1745
+ (fields.join(", "), applicability)
1746
+ }
1747
+ None => {
1748
+ ("/* fields */".to_string(), Applicability::HasPlaceholders)
1749
+ }
1750
+ };
1751
+ let pad = if has_fields { " " } else { "" };
1752
+ err.span_suggestion(
1753
+ span,
1754
+ format!("use struct {descr} syntax instead"),
1755
+ format!("{path_str} {{{pad}{fields}{pad}}}"),
1756
+ applicability,
1757
+ );
1758
+ }
1719
1759
}
1720
1760
if let PathSource::Expr(Some(Expr {
1721
1761
kind: ExprKind::Call(path, args),
0 commit comments