Skip to content

Commit

Permalink
Rollup merge of #99350 - compiler-errors:issue-99240, r=fee1-dead
Browse files Browse the repository at this point in the history
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?
  • Loading branch information
JohnTitor authored Jul 17, 2022
2 parents 796bc7c + 7a45a60 commit cc35c78
Show file tree
Hide file tree
Showing 20 changed files with 136 additions and 52 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@ pub fn path_to_string(segment: &hir::Path<'_>) -> String {
to_string(NO_ANN, |s| s.print_path(segment, false))
}

pub fn qpath_to_string(segment: &hir::QPath<'_>) -> String {
to_string(NO_ANN, |s| s.print_qpath(segment, false))
}

pub fn fn_to_string(
decl: &hir::FnDecl<'_>,
header: hir::FnHeader,
Expand Down
35 changes: 20 additions & 15 deletions compiler/rustc_typeck/src/check/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::type_error_struct;

use rustc_errors::{struct_span_err, Applicability, Diagnostic};
use rustc_hir as hir;
use rustc_hir::def::{Namespace, Res};
use rustc_hir::def::{self, Namespace, Res};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_infer::{
infer,
Expand Down Expand Up @@ -390,17 +390,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(fn_sig, Some(def_id))
}
ty::FnPtr(sig) => (sig, None),
ref t => {
_ => {
let mut unit_variant = None;
let mut removal_span = call_expr.span;
if let ty::Adt(adt_def, ..) = t
&& adt_def.is_enum()
&& let hir::ExprKind::Call(expr, _) = call_expr.kind
if let hir::ExprKind::Path(qpath) = &callee_expr.kind
&& let Res::Def(def::DefKind::Ctor(kind, def::CtorKind::Const), _)
= self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
// Only suggest removing parens if there are no arguments
&& arg_exprs.is_empty()
{
removal_span =
expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
let descr = match kind {
def::CtorOf::Struct => "struct",
def::CtorOf::Variant => "enum variant",
};
let removal_span =
callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
unit_variant =
self.tcx.sess.source_map().span_to_snippet(expr.span).ok();
Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(qpath)));
}

let callee_ty = self.resolve_vars_if_possible(callee_ty);
Expand All @@ -410,8 +415,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
callee_ty,
E0618,
"expected function, found {}",
match unit_variant {
Some(ref path) => format!("enum variant `{path}`"),
match &unit_variant {
Some((_, kind, path)) => format!("{kind} `{path}`"),
None => format!("`{callee_ty}`"),
}
);
Expand All @@ -423,11 +428,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
callee_expr.span,
);

if let Some(ref path) = unit_variant {
if let Some((removal_span, kind, path)) = &unit_variant {
err.span_suggestion_verbose(
removal_span,
*removal_span,
&format!(
"`{path}` is a unit variant, you need to write it without the parentheses",
"`{path}` is a unit {kind}, and does not take parentheses to be constructed",
),
"",
Applicability::MachineApplicable,
Expand Down Expand Up @@ -470,7 +475,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(span) = self.tcx.hir().res_span(def) {
let callee_ty = callee_ty.to_string();
let label = match (unit_variant, inner_callee_path) {
(Some(path), _) => Some(format!("`{path}` defined here")),
(Some((_, kind, path)), _) => Some(format!("{kind} `{path}` defined here")),
(_, Some(hir::QPath::Resolved(_, path))) => self
.tcx
.sess
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
tcx.ty_error()
}
Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) => {
report_unexpected_variant_res(tcx, res, expr.span);
report_unexpected_variant_res(tcx, res, qpath, expr.span);
tcx.ty_error()
}
_ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
Expand Down
9 changes: 3 additions & 6 deletions compiler/rustc_typeck/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -863,17 +863,14 @@ fn bad_non_zero_sized_fields<'tcx>(
err.emit();
}

fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span) {
fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<'_>, span: Span) {
struct_span_err!(
tcx.sess,
span,
E0533,
"expected unit struct, unit variant or constant, found {}{}",
"expected unit struct, unit variant or constant, found {} `{}`",
res.descr(),
tcx.sess
.source_map()
.span_to_snippet(span)
.map_or_else(|_| String::new(), |s| format!(" `{s}`",)),
rustc_hir_pretty::qpath_to_string(qpath),
)
.emit();
}
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_typeck/src/check/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, def_bm, ti)
}
PatKind::Path(_) => self.check_pat_path(pat, path_res.unwrap(), expected, ti),
PatKind::Path(ref qpath) => {
self.check_pat_path(pat, qpath, path_res.unwrap(), expected, ti)
}
PatKind::Struct(ref qpath, fields, has_rest_pat) => {
self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, def_bm, ti)
}
Expand Down Expand Up @@ -800,6 +802,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn check_pat_path<'b>(
&self,
pat: &Pat<'_>,
qpath: &hir::QPath<'_>,
path_resolution: (Res, Option<Ty<'tcx>>, &'b [hir::PathSegment<'b>]),
expected: Ty<'tcx>,
ti: TopInfo<'tcx>,
Expand All @@ -814,7 +817,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return tcx.ty_error();
}
Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fictive | CtorKind::Fn), _) => {
report_unexpected_variant_res(tcx, res, pat.span);
report_unexpected_variant_res(tcx, res, qpath, pat.span);
return tcx.ty_error();
}
Res::SelfCtor(..)
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/empty/empty-struct-unit-expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ enum E {
}

fn main() {
let e2 = Empty2(); //~ ERROR expected function, found `Empty2`
let e2 = Empty2(); //~ ERROR expected function, found struct `Empty2`
let e4 = E::Empty4();
//~^ ERROR expected function, found enum variant `E::Empty4` [E0618]
let xe2 = XEmpty2(); //~ ERROR expected function, found `empty_struct::XEmpty2`
let xe2 = XEmpty2(); //~ ERROR expected function, found struct `XEmpty2`
let xe4 = XE::XEmpty4();
//~^ ERROR expected function, found enum variant `XE::XEmpty4` [E0618]
}
24 changes: 18 additions & 6 deletions src/test/ui/empty/empty-struct-unit-expr.stderr
Original file line number Diff line number Diff line change
@@ -1,38 +1,50 @@
error[E0618]: expected function, found `Empty2`
error[E0618]: expected function, found struct `Empty2`
--> $DIR/empty-struct-unit-expr.rs:15:14
|
LL | struct Empty2;
| ------------- `Empty2` defined here
| ------------- struct `Empty2` defined here
...
LL | let e2 = Empty2();
| ^^^^^^--
| |
| call expression requires function
|
help: `Empty2` is a unit struct, and does not take parentheses to be constructed
|
LL - let e2 = Empty2();
LL + let e2 = Empty2;
|

error[E0618]: expected function, found enum variant `E::Empty4`
--> $DIR/empty-struct-unit-expr.rs:16:14
|
LL | Empty4
| ------ `E::Empty4` defined here
| ------ enum variant `E::Empty4` defined here
...
LL | let e4 = E::Empty4();
| ^^^^^^^^^--
| |
| call expression requires function
|
help: `E::Empty4` is a unit variant, you need to write it without the parentheses
help: `E::Empty4` is a unit enum variant, and does not take parentheses to be constructed
|
LL - let e4 = E::Empty4();
LL + let e4 = E::Empty4;
|

error[E0618]: expected function, found `empty_struct::XEmpty2`
error[E0618]: expected function, found struct `XEmpty2`
--> $DIR/empty-struct-unit-expr.rs:18:15
|
LL | let xe2 = XEmpty2();
| ^^^^^^^--
| |
| call expression requires function
|
help: `XEmpty2` is a unit struct, and does not take parentheses to be constructed
|
LL - let xe2 = XEmpty2();
LL + let xe2 = XEmpty2;
|

error[E0618]: expected function, found enum variant `XE::XEmpty4`
--> $DIR/empty-struct-unit-expr.rs:19:15
Expand All @@ -42,7 +54,7 @@ LL | let xe4 = XE::XEmpty4();
| |
| call expression requires function
|
help: `XE::XEmpty4` is a unit variant, you need to write it without the parentheses
help: `XE::XEmpty4` is a unit enum variant, and does not take parentheses to be constructed
|
LL - let xe4 = XE::XEmpty4();
LL + let xe4 = XE::XEmpty4;
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/error-codes/E0618.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ error[E0618]: expected function, found enum variant `X::Entry`
--> $DIR/E0618.rs:6:5
|
LL | Entry,
| ----- `X::Entry` defined here
| ----- enum variant `X::Entry` defined here
...
LL | X::Entry();
| ^^^^^^^^--
| |
| call expression requires function
|
help: `X::Entry` is a unit variant, you need to write it without the parentheses
help: `X::Entry` is a unit enum variant, and does not take parentheses to be constructed
|
LL - X::Entry();
LL + X::Entry;
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-20714.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
struct G;

fn main() {
let g = G(); //~ ERROR: expected function, found `G`
let g = G(); //~ ERROR: expected function, found struct `G`
}
10 changes: 8 additions & 2 deletions src/test/ui/issues/issue-20714.stderr
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
error[E0618]: expected function, found `G`
error[E0618]: expected function, found struct `G`
--> $DIR/issue-20714.rs:4:13
|
LL | struct G;
| -------- `G` defined here
| -------- struct `G` defined here
...
LL | let g = G();
| ^--
| |
| call expression requires function
|
help: `G` is a unit struct, and does not take parentheses to be constructed
|
LL - let g = G();
LL + let g = G;
|

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-21701.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ struct Bar;

pub fn some_func() {
let f = Bar();
//~^ ERROR: expected function, found `Bar`
//~^ ERROR: expected function, found struct `Bar`
}

fn main() {
Expand Down
10 changes: 8 additions & 2 deletions src/test/ui/issues/issue-21701.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@ LL | let y = t();
| |
| call expression requires function

error[E0618]: expected function, found `Bar`
error[E0618]: expected function, found struct `Bar`
--> $DIR/issue-21701.rs:9:13
|
LL | struct Bar;
| ---------- `Bar` defined here
| ---------- struct `Bar` defined here
...
LL | let f = Bar();
| ^^^--
| |
| call expression requires function
|
help: `Bar` is a unit struct, and does not take parentheses to be constructed
|
LL - let f = Bar();
LL + let f = Bar;
|

error: aborting due to 2 previous errors

Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/methods/method-path-in-pattern.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ error[E0533]: expected unit struct, unit variant or constant, found associated f
LL | Foo::bar => {}
| ^^^^^^^^

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

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

error[E0533]: expected unit struct, unit variant or constant, found associated function `<Foo>::bar`
error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
--> $DIR/method-path-in-pattern.rs:28:12
|
LL | if let <Foo>::bar = 0u32 {}
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/qualified/qualified-path-params.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0533]: expected unit struct, unit variant or constant, found associated function `<S as Tr>::A::f::<u8>`
error[E0533]: expected unit struct, unit variant or constant, found associated function `<<S as Tr>::A>::f<u8>`
--> $DIR/qualified-path-params.rs:20:9
|
LL | <S as Tr>::A::f::<u8> => {}
Expand Down
12 changes: 6 additions & 6 deletions src/test/ui/resolve/privacy-enum-ctor.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -336,14 +336,14 @@ error[E0618]: expected function, found enum variant `Z::Unit`
--> $DIR/privacy-enum-ctor.rs:31:17
|
LL | Unit,
| ---- `Z::Unit` defined here
| ---- enum variant `Z::Unit` defined here
...
LL | let _ = Z::Unit();
| ^^^^^^^--
| |
| call expression requires function
|
help: `Z::Unit` is a unit variant, you need to write it without the parentheses
help: `Z::Unit` is a unit enum variant, and does not take parentheses to be constructed
|
LL - let _ = Z::Unit();
LL + let _ = Z::Unit;
Expand Down Expand Up @@ -371,14 +371,14 @@ error[E0618]: expected function, found enum variant `m::E::Unit`
--> $DIR/privacy-enum-ctor.rs:47:16
|
LL | Unit,
| ---- `m::E::Unit` defined here
| ---- enum variant `m::E::Unit` defined here
...
LL | let _: E = m::E::Unit();
| ^^^^^^^^^^--
| |
| call expression requires function
|
help: `m::E::Unit` is a unit variant, you need to write it without the parentheses
help: `m::E::Unit` is a unit enum variant, and does not take parentheses to be constructed
|
LL - let _: E = m::E::Unit();
LL + let _: E = m::E::Unit;
Expand Down Expand Up @@ -406,14 +406,14 @@ error[E0618]: expected function, found enum variant `E::Unit`
--> $DIR/privacy-enum-ctor.rs:55:16
|
LL | Unit,
| ---- `E::Unit` defined here
| ---- enum variant `E::Unit` defined here
...
LL | let _: E = E::Unit();
| ^^^^^^^--
| |
| call expression requires function
|
help: `E::Unit` is a unit variant, you need to write it without the parentheses
help: `E::Unit` is a unit enum variant, and does not take parentheses to be constructed
|
LL - let _: E = E::Unit();
LL + let _: E = E::Unit;
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/suggestions/issue-99240-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
enum Enum {
Unit,
}
type Alias = Enum;

fn main() {
Alias::
Unit();
//~^^ ERROR expected function, found enum variant `Alias::Unit`
}
Loading

0 comments on commit cc35c78

Please sign in to comment.