Skip to content

Commit cc35c78

Browse files
authored
Rollup merge of #99350 - compiler-errors:issue-99240, r=fee1-dead
Be more precise when suggesting removal of parens on unit ctor * Fixes #99240 by only suggesting to remove parens on path exprs, not arbitrary expressions with enum type * Generalizes by suggesting removal of parens on unit struct, too, because why not?
2 parents 796bc7c + 7a45a60 commit cc35c78

20 files changed

+136
-52
lines changed

compiler/rustc_hir_pretty/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,10 @@ pub fn path_to_string(segment: &hir::Path<'_>) -> String {
211211
to_string(NO_ANN, |s| s.print_path(segment, false))
212212
}
213213

214+
pub fn qpath_to_string(segment: &hir::QPath<'_>) -> String {
215+
to_string(NO_ANN, |s| s.print_qpath(segment, false))
216+
}
217+
214218
pub fn fn_to_string(
215219
decl: &hir::FnDecl<'_>,
216220
header: hir::FnHeader,

compiler/rustc_typeck/src/check/callee.rs

+20-15
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::type_error_struct;
44

55
use rustc_errors::{struct_span_err, Applicability, Diagnostic};
66
use rustc_hir as hir;
7-
use rustc_hir::def::{Namespace, Res};
7+
use rustc_hir::def::{self, Namespace, Res};
88
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
99
use rustc_infer::{
1010
infer,
@@ -390,17 +390,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
390390
(fn_sig, Some(def_id))
391391
}
392392
ty::FnPtr(sig) => (sig, None),
393-
ref t => {
393+
_ => {
394394
let mut unit_variant = None;
395-
let mut removal_span = call_expr.span;
396-
if let ty::Adt(adt_def, ..) = t
397-
&& adt_def.is_enum()
398-
&& let hir::ExprKind::Call(expr, _) = call_expr.kind
395+
if let hir::ExprKind::Path(qpath) = &callee_expr.kind
396+
&& let Res::Def(def::DefKind::Ctor(kind, def::CtorKind::Const), _)
397+
= self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
398+
// Only suggest removing parens if there are no arguments
399+
&& arg_exprs.is_empty()
399400
{
400-
removal_span =
401-
expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
401+
let descr = match kind {
402+
def::CtorOf::Struct => "struct",
403+
def::CtorOf::Variant => "enum variant",
404+
};
405+
let removal_span =
406+
callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
402407
unit_variant =
403-
self.tcx.sess.source_map().span_to_snippet(expr.span).ok();
408+
Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(qpath)));
404409
}
405410

406411
let callee_ty = self.resolve_vars_if_possible(callee_ty);
@@ -410,8 +415,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
410415
callee_ty,
411416
E0618,
412417
"expected function, found {}",
413-
match unit_variant {
414-
Some(ref path) => format!("enum variant `{path}`"),
418+
match &unit_variant {
419+
Some((_, kind, path)) => format!("{kind} `{path}`"),
415420
None => format!("`{callee_ty}`"),
416421
}
417422
);
@@ -423,11 +428,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
423428
callee_expr.span,
424429
);
425430

426-
if let Some(ref path) = unit_variant {
431+
if let Some((removal_span, kind, path)) = &unit_variant {
427432
err.span_suggestion_verbose(
428-
removal_span,
433+
*removal_span,
429434
&format!(
430-
"`{path}` is a unit variant, you need to write it without the parentheses",
435+
"`{path}` is a unit {kind}, and does not take parentheses to be constructed",
431436
),
432437
"",
433438
Applicability::MachineApplicable,
@@ -470,7 +475,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
470475
if let Some(span) = self.tcx.hir().res_span(def) {
471476
let callee_ty = callee_ty.to_string();
472477
let label = match (unit_variant, inner_callee_path) {
473-
(Some(path), _) => Some(format!("`{path}` defined here")),
478+
(Some((_, kind, path)), _) => Some(format!("{kind} `{path}` defined here")),
474479
(_, Some(hir::QPath::Resolved(_, path))) => self
475480
.tcx
476481
.sess

compiler/rustc_typeck/src/check/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
531531
tcx.ty_error()
532532
}
533533
Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) => {
534-
report_unexpected_variant_res(tcx, res, expr.span);
534+
report_unexpected_variant_res(tcx, res, qpath, expr.span);
535535
tcx.ty_error()
536536
}
537537
_ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,

compiler/rustc_typeck/src/check/mod.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -863,17 +863,14 @@ fn bad_non_zero_sized_fields<'tcx>(
863863
err.emit();
864864
}
865865

866-
fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span) {
866+
fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<'_>, span: Span) {
867867
struct_span_err!(
868868
tcx.sess,
869869
span,
870870
E0533,
871-
"expected unit struct, unit variant or constant, found {}{}",
871+
"expected unit struct, unit variant or constant, found {} `{}`",
872872
res.descr(),
873-
tcx.sess
874-
.source_map()
875-
.span_to_snippet(span)
876-
.map_or_else(|_| String::new(), |s| format!(" `{s}`",)),
873+
rustc_hir_pretty::qpath_to_string(qpath),
877874
)
878875
.emit();
879876
}

compiler/rustc_typeck/src/check/pat.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
183183
PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
184184
self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, def_bm, ti)
185185
}
186-
PatKind::Path(_) => self.check_pat_path(pat, path_res.unwrap(), expected, ti),
186+
PatKind::Path(ref qpath) => {
187+
self.check_pat_path(pat, qpath, path_res.unwrap(), expected, ti)
188+
}
187189
PatKind::Struct(ref qpath, fields, has_rest_pat) => {
188190
self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, def_bm, ti)
189191
}
@@ -800,6 +802,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
800802
fn check_pat_path<'b>(
801803
&self,
802804
pat: &Pat<'_>,
805+
qpath: &hir::QPath<'_>,
803806
path_resolution: (Res, Option<Ty<'tcx>>, &'b [hir::PathSegment<'b>]),
804807
expected: Ty<'tcx>,
805808
ti: TopInfo<'tcx>,
@@ -814,7 +817,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
814817
return tcx.ty_error();
815818
}
816819
Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fictive | CtorKind::Fn), _) => {
817-
report_unexpected_variant_res(tcx, res, pat.span);
820+
report_unexpected_variant_res(tcx, res, qpath, pat.span);
818821
return tcx.ty_error();
819822
}
820823
Res::SelfCtor(..)

src/test/ui/empty/empty-struct-unit-expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ enum E {
1212
}
1313

1414
fn main() {
15-
let e2 = Empty2(); //~ ERROR expected function, found `Empty2`
15+
let e2 = Empty2(); //~ ERROR expected function, found struct `Empty2`
1616
let e4 = E::Empty4();
1717
//~^ ERROR expected function, found enum variant `E::Empty4` [E0618]
18-
let xe2 = XEmpty2(); //~ ERROR expected function, found `empty_struct::XEmpty2`
18+
let xe2 = XEmpty2(); //~ ERROR expected function, found struct `XEmpty2`
1919
let xe4 = XE::XEmpty4();
2020
//~^ ERROR expected function, found enum variant `XE::XEmpty4` [E0618]
2121
}

src/test/ui/empty/empty-struct-unit-expr.stderr

+18-6
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,50 @@
1-
error[E0618]: expected function, found `Empty2`
1+
error[E0618]: expected function, found struct `Empty2`
22
--> $DIR/empty-struct-unit-expr.rs:15:14
33
|
44
LL | struct Empty2;
5-
| ------------- `Empty2` defined here
5+
| ------------- struct `Empty2` defined here
66
...
77
LL | let e2 = Empty2();
88
| ^^^^^^--
99
| |
1010
| call expression requires function
11+
|
12+
help: `Empty2` is a unit struct, and does not take parentheses to be constructed
13+
|
14+
LL - let e2 = Empty2();
15+
LL + let e2 = Empty2;
16+
|
1117

1218
error[E0618]: expected function, found enum variant `E::Empty4`
1319
--> $DIR/empty-struct-unit-expr.rs:16:14
1420
|
1521
LL | Empty4
16-
| ------ `E::Empty4` defined here
22+
| ------ enum variant `E::Empty4` defined here
1723
...
1824
LL | let e4 = E::Empty4();
1925
| ^^^^^^^^^--
2026
| |
2127
| call expression requires function
2228
|
23-
help: `E::Empty4` is a unit variant, you need to write it without the parentheses
29+
help: `E::Empty4` is a unit enum variant, and does not take parentheses to be constructed
2430
|
2531
LL - let e4 = E::Empty4();
2632
LL + let e4 = E::Empty4;
2733
|
2834

29-
error[E0618]: expected function, found `empty_struct::XEmpty2`
35+
error[E0618]: expected function, found struct `XEmpty2`
3036
--> $DIR/empty-struct-unit-expr.rs:18:15
3137
|
3238
LL | let xe2 = XEmpty2();
3339
| ^^^^^^^--
3440
| |
3541
| call expression requires function
42+
|
43+
help: `XEmpty2` is a unit struct, and does not take parentheses to be constructed
44+
|
45+
LL - let xe2 = XEmpty2();
46+
LL + let xe2 = XEmpty2;
47+
|
3648

3749
error[E0618]: expected function, found enum variant `XE::XEmpty4`
3850
--> $DIR/empty-struct-unit-expr.rs:19:15
@@ -42,7 +54,7 @@ LL | let xe4 = XE::XEmpty4();
4254
| |
4355
| call expression requires function
4456
|
45-
help: `XE::XEmpty4` is a unit variant, you need to write it without the parentheses
57+
help: `XE::XEmpty4` is a unit enum variant, and does not take parentheses to be constructed
4658
|
4759
LL - let xe4 = XE::XEmpty4();
4860
LL + let xe4 = XE::XEmpty4;

src/test/ui/error-codes/E0618.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ error[E0618]: expected function, found enum variant `X::Entry`
22
--> $DIR/E0618.rs:6:5
33
|
44
LL | Entry,
5-
| ----- `X::Entry` defined here
5+
| ----- enum variant `X::Entry` defined here
66
...
77
LL | X::Entry();
88
| ^^^^^^^^--
99
| |
1010
| call expression requires function
1111
|
12-
help: `X::Entry` is a unit variant, you need to write it without the parentheses
12+
help: `X::Entry` is a unit enum variant, and does not take parentheses to be constructed
1313
|
1414
LL - X::Entry();
1515
LL + X::Entry;

src/test/ui/issues/issue-20714.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
struct G;
22

33
fn main() {
4-
let g = G(); //~ ERROR: expected function, found `G`
4+
let g = G(); //~ ERROR: expected function, found struct `G`
55
}

src/test/ui/issues/issue-20714.stderr

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1-
error[E0618]: expected function, found `G`
1+
error[E0618]: expected function, found struct `G`
22
--> $DIR/issue-20714.rs:4:13
33
|
44
LL | struct G;
5-
| -------- `G` defined here
5+
| -------- struct `G` defined here
66
...
77
LL | let g = G();
88
| ^--
99
| |
1010
| call expression requires function
11+
|
12+
help: `G` is a unit struct, and does not take parentheses to be constructed
13+
|
14+
LL - let g = G();
15+
LL + let g = G;
16+
|
1117

1218
error: aborting due to previous error
1319

src/test/ui/issues/issue-21701.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ struct Bar;
77

88
pub fn some_func() {
99
let f = Bar();
10-
//~^ ERROR: expected function, found `Bar`
10+
//~^ ERROR: expected function, found struct `Bar`
1111
}
1212

1313
fn main() {

src/test/ui/issues/issue-21701.stderr

+8-2
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,22 @@ LL | let y = t();
88
| |
99
| call expression requires function
1010

11-
error[E0618]: expected function, found `Bar`
11+
error[E0618]: expected function, found struct `Bar`
1212
--> $DIR/issue-21701.rs:9:13
1313
|
1414
LL | struct Bar;
15-
| ---------- `Bar` defined here
15+
| ---------- struct `Bar` defined here
1616
...
1717
LL | let f = Bar();
1818
| ^^^--
1919
| |
2020
| call expression requires function
21+
|
22+
help: `Bar` is a unit struct, and does not take parentheses to be constructed
23+
|
24+
LL - let f = Bar();
25+
LL + let f = Bar;
26+
|
2127

2228
error: aborting due to 2 previous errors
2329

src/test/ui/methods/method-path-in-pattern.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ error[E0533]: expected unit struct, unit variant or constant, found associated f
44
LL | Foo::bar => {}
55
| ^^^^^^^^
66

7-
error[E0533]: expected unit struct, unit variant or constant, found associated function `<Foo>::bar`
7+
error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
88
--> $DIR/method-path-in-pattern.rs:19:9
99
|
1010
LL | <Foo>::bar => {}
1111
| ^^^^^^^^^^
1212

13-
error[E0533]: expected unit struct, unit variant or constant, found associated function `<Foo>::trait_bar`
13+
error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::trait_bar`
1414
--> $DIR/method-path-in-pattern.rs:23:9
1515
|
1616
LL | <Foo>::trait_bar => {}
@@ -22,7 +22,7 @@ error[E0533]: expected unit struct, unit variant or constant, found associated f
2222
LL | if let Foo::bar = 0u32 {}
2323
| ^^^^^^^^
2424

25-
error[E0533]: expected unit struct, unit variant or constant, found associated function `<Foo>::bar`
25+
error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
2626
--> $DIR/method-path-in-pattern.rs:28:12
2727
|
2828
LL | if let <Foo>::bar = 0u32 {}

src/test/ui/qualified/qualified-path-params.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0533]: expected unit struct, unit variant or constant, found associated function `<S as Tr>::A::f::<u8>`
1+
error[E0533]: expected unit struct, unit variant or constant, found associated function `<<S as Tr>::A>::f<u8>`
22
--> $DIR/qualified-path-params.rs:20:9
33
|
44
LL | <S as Tr>::A::f::<u8> => {}

src/test/ui/resolve/privacy-enum-ctor.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -336,14 +336,14 @@ error[E0618]: expected function, found enum variant `Z::Unit`
336336
--> $DIR/privacy-enum-ctor.rs:31:17
337337
|
338338
LL | Unit,
339-
| ---- `Z::Unit` defined here
339+
| ---- enum variant `Z::Unit` defined here
340340
...
341341
LL | let _ = Z::Unit();
342342
| ^^^^^^^--
343343
| |
344344
| call expression requires function
345345
|
346-
help: `Z::Unit` is a unit variant, you need to write it without the parentheses
346+
help: `Z::Unit` is a unit enum variant, and does not take parentheses to be constructed
347347
|
348348
LL - let _ = Z::Unit();
349349
LL + let _ = Z::Unit;
@@ -371,14 +371,14 @@ error[E0618]: expected function, found enum variant `m::E::Unit`
371371
--> $DIR/privacy-enum-ctor.rs:47:16
372372
|
373373
LL | Unit,
374-
| ---- `m::E::Unit` defined here
374+
| ---- enum variant `m::E::Unit` defined here
375375
...
376376
LL | let _: E = m::E::Unit();
377377
| ^^^^^^^^^^--
378378
| |
379379
| call expression requires function
380380
|
381-
help: `m::E::Unit` is a unit variant, you need to write it without the parentheses
381+
help: `m::E::Unit` is a unit enum variant, and does not take parentheses to be constructed
382382
|
383383
LL - let _: E = m::E::Unit();
384384
LL + let _: E = m::E::Unit;
@@ -406,14 +406,14 @@ error[E0618]: expected function, found enum variant `E::Unit`
406406
--> $DIR/privacy-enum-ctor.rs:55:16
407407
|
408408
LL | Unit,
409-
| ---- `E::Unit` defined here
409+
| ---- enum variant `E::Unit` defined here
410410
...
411411
LL | let _: E = E::Unit();
412412
| ^^^^^^^--
413413
| |
414414
| call expression requires function
415415
|
416-
help: `E::Unit` is a unit variant, you need to write it without the parentheses
416+
help: `E::Unit` is a unit enum variant, and does not take parentheses to be constructed
417417
|
418418
LL - let _: E = E::Unit();
419419
LL + let _: E = E::Unit;
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
enum Enum {
2+
Unit,
3+
}
4+
type Alias = Enum;
5+
6+
fn main() {
7+
Alias::
8+
Unit();
9+
//~^^ ERROR expected function, found enum variant `Alias::Unit`
10+
}

0 commit comments

Comments
 (0)