Address #44173 for type check errors.
self.note_need_for_fn_pointer(err, expected, expr_ty);
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
self.check_for_range_as_method_call(err, expr, expr_ty, expected);
+ self.check_for_binding_assigned_block_without_tail_expression(err, expr, expr_ty, expected);
}
/// Requires that the two types unify, and prints an error message if
Applicability::MachineApplicable,
);
}
+
+ /// Identify when the type error is because `()` is found in a binding that was assigned a
+ /// block without a tail expression.
+ fn check_for_binding_assigned_block_without_tail_expression(
+ &self,
+ err: &mut Diagnostic,
+ expr: &hir::Expr<'_>,
+ checked_ty: Ty<'tcx>,
+ expected_ty: Ty<'tcx>,
+ ) {
+ if !checked_ty.is_unit() {
+ return;
+ }
+ let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else { return; };
+ let hir::def::Res::Local(hir_id) = path.res else { return; };
+ let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(hir_id) else {
+ return;
+ };
+ let Some(hir::Node::Local(hir::Local {
+ ty: None,
+ init: Some(init),
+ ..
+ })) = self.tcx.hir().find_parent(pat.hir_id) else { return; };
+ let hir::ExprKind::Block(block, None) = init.kind else { return; };
+ if block.expr.is_some() {
+ return;
+ }
+ let [.., stmt] = block.stmts else {
+ err.span_help(block.span, "this empty block is missing a tail expression");
+ return;
+ };
+ let hir::StmtKind::Semi(tail_expr) = stmt.kind else { return; };
+ let Some(ty) = self.node_ty_opt(tail_expr.hir_id) else { return; };
+ if self.can_eq(self.param_env, expected_ty, ty).is_ok() {
+ err.span_suggestion_verbose(
+ stmt.span.with_lo(tail_expr.span.hi()),
+ "remove this semicolon",
+ "",
+ Applicability::MachineApplicable,
+ );
+ } else {
+ err.span_help(block.span, "this block is missing a tail expression");
+ }
+ }
}
--- /dev/null
+fn main() {
+ let x = {
+ println!("foo");
+ 42;
+ };
+ let y = {};
+ let z = {
+ "hi";
+ };
+ println!("{}", x); //~ ERROR E0277
+ println!("{}", y); //~ ERROR E0277
+ println!("{}", z); //~ ERROR E0277
+ let _: i32 = x; //~ ERROR E0308
+ let _: i32 = y; //~ ERROR E0308
+ let _: i32 = z; //~ ERROR E0308
+}
--- /dev/null
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+ --> $DIR/binding-assigned-block-without-tail-expression.rs:10:20
+ |
+LL | println!("{}", x);
+ | ^ `()` cannot be formatted with the default formatter
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `()`
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+ --> $DIR/binding-assigned-block-without-tail-expression.rs:11:20
+ |
+LL | println!("{}", y);
+ | ^ `()` cannot be formatted with the default formatter
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `()`
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+ --> $DIR/binding-assigned-block-without-tail-expression.rs:12:20
+ |
+LL | println!("{}", z);
+ | ^ `()` cannot be formatted with the default formatter
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `()`
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> $DIR/binding-assigned-block-without-tail-expression.rs:13:18
+ |
+LL | let _: i32 = x;
+ | --- ^ expected `i32`, found `()`
+ | |
+ | expected due to this
+ |
+help: remove this semicolon
+ |
+LL - 42;
+LL + 42
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/binding-assigned-block-without-tail-expression.rs:14:18
+ |
+LL | let _: i32 = y;
+ | --- ^ expected `i32`, found `()`
+ | |
+ | expected due to this
+ |
+help: this empty block is missing a tail expression
+ --> $DIR/binding-assigned-block-without-tail-expression.rs:6:13
+ |
+LL | let y = {};
+ | ^^
+
+error[E0308]: mismatched types
+ --> $DIR/binding-assigned-block-without-tail-expression.rs:15:18
+ |
+LL | let _: i32 = z;
+ | --- ^ expected `i32`, found `()`
+ | |
+ | expected due to this
+ |
+help: this block is missing a tail expression
+ --> $DIR/binding-assigned-block-without-tail-expression.rs:7:13
+ |
+LL | let z = {
+ | _____________^
+LL | | "hi";
+LL | | };
+ | |_____^
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.