Address more nits

This commit is contained in:
Michael Goulet 2022-07-21 16:12:57 +00:00
parent cd89978d86
commit 3eef023da0
3 changed files with 34 additions and 40 deletions

View File

@ -955,7 +955,7 @@ pub struct Block<'hir> {
} }
impl<'hir> Block<'hir> { impl<'hir> Block<'hir> {
pub fn peel_blocks(&self) -> &Block<'hir> { pub fn innermost_block(&self) -> &Block<'hir> {
let mut block = self; let mut block = self;
while let Some(Expr { kind: ExprKind::Block(inner_block, _), .. }) = block.expr { while let Some(Expr { kind: ExprKind::Block(inner_block, _), .. }) = block.expr {
block = inner_block; block = inner_block;

View File

@ -758,22 +758,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
second_ty: Ty<'tcx>, second_ty: Ty<'tcx>,
second_span: Span, second_span: Span,
) { ) {
let semicolon = let remove_semicolon =
if let Some(first_id) = first_id [(first_id, second_ty), (second_id, first_ty)].into_iter().find_map(|(id, ty)| {
&& let hir::Node::Block(blk) = self.tcx.hir().get(first_id) let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None };
&& let Some(remove_semicolon) = self.could_remove_semicolon(blk, second_ty) self.could_remove_semicolon(blk, ty)
{ });
Some(remove_semicolon) match remove_semicolon {
} else if let Some(second_id) = second_id Some((sp, StatementAsExpression::NeedsBoxing)) => {
&& let hir::Node::Block(blk) = self.tcx.hir().get(second_id)
&& let Some(remove_semicolon) = self.could_remove_semicolon(blk, first_ty)
{
Some(remove_semicolon)
} else {
None
};
if let Some((sp, boxed)) = semicolon {
if matches!(boxed, StatementAsExpression::NeedsBoxing) {
err.multipart_suggestion( err.multipart_suggestion(
"consider removing this semicolon and boxing the expressions", "consider removing this semicolon and boxing the expressions",
vec![ vec![
@ -785,7 +776,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
], ],
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
} else { }
Some((sp, StatementAsExpression::CorrectType)) => {
err.span_suggestion_short( err.span_suggestion_short(
sp, sp,
"consider removing this semicolon", "consider removing this semicolon",
@ -793,20 +785,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
} }
} else { None => {
let suggested = for (id, ty) in [(first_id, second_ty), (second_id, first_ty)] {
if let Some(first_id) = first_id if let Some(id) = id
&& let hir::Node::Block(blk) = self.tcx.hir().get(first_id) && let hir::Node::Block(blk) = self.tcx.hir().get(id)
{ && self.consider_returning_binding(blk, ty, err)
self.consider_returning_binding(blk, second_ty, err) {
} else { break;
false }
}; }
if !suggested
&& let Some(second_id) = second_id
&& let hir::Node::Block(blk) = self.tcx.hir().get(second_id)
{
self.consider_returning_binding(blk, first_ty, err);
} }
} }
} }
@ -2884,8 +2871,10 @@ impl TyCategory {
} }
impl<'tcx> InferCtxt<'_, 'tcx> { impl<'tcx> InferCtxt<'_, 'tcx> {
/// Given a [`hir::Block`], get the span of its last expression or
/// statement, peeling off any inner blocks.
pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span { pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
let block = block.peel_blocks(); let block = block.innermost_block();
if let Some(expr) = &block.expr { if let Some(expr) = &block.expr {
expr.span expr.span
} else if let Some(stmt) = block.stmts.last() { } else if let Some(stmt) = block.stmts.last() {
@ -2897,27 +2886,30 @@ impl<'tcx> InferCtxt<'_, 'tcx> {
} }
} }
/// Given a [`hir::HirId`] for a block, get the span of its last expression
/// or statement, peeling off any inner blocks.
pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span { pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
match self.tcx.hir().get(hir_id) { match self.tcx.hir().get(hir_id) {
hir::Node::Block(blk) => self.find_block_span(blk), hir::Node::Block(blk) => self.find_block_span(blk),
// The parser was in a weird state if either of these happen... // The parser was in a weird state if either of these happen, but
// it's better not to panic.
hir::Node::Expr(e) => e.span, hir::Node::Expr(e) => e.span,
_ => rustc_span::DUMMY_SP, _ => rustc_span::DUMMY_SP,
} }
} }
/// Be helpful when the user wrote `{... expr; }` and taking the `;` off
/// is enough to fix the error.
pub fn could_remove_semicolon( pub fn could_remove_semicolon(
&self, &self,
blk: &'tcx hir::Block<'tcx>, blk: &'tcx hir::Block<'tcx>,
expected_ty: Ty<'tcx>, expected_ty: Ty<'tcx>,
) -> Option<(Span, StatementAsExpression)> { ) -> Option<(Span, StatementAsExpression)> {
let blk = blk.peel_blocks(); let blk = blk.innermost_block();
// Do not suggest if we have a tail expr. // Do not suggest if we have a tail expr.
if blk.expr.is_some() { if blk.expr.is_some() {
return None; return None;
} }
// Be helpful when the user wrote `{... expr;}` and
// taking the `;` off is enough to fix the error.
let last_stmt = blk.stmts.last()?; let last_stmt = blk.stmts.last()?;
let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else { let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else {
return None; return None;
@ -2987,13 +2979,15 @@ impl<'tcx> InferCtxt<'_, 'tcx> {
Some((span, needs_box)) Some((span, needs_box))
} }
/// Suggest returning a local binding with a compatible type if the block
/// has no return expression.
pub fn consider_returning_binding( pub fn consider_returning_binding(
&self, &self,
blk: &'tcx hir::Block<'tcx>, blk: &'tcx hir::Block<'tcx>,
expected_ty: Ty<'tcx>, expected_ty: Ty<'tcx>,
err: &mut Diagnostic, err: &mut Diagnostic,
) -> bool { ) -> bool {
let blk = blk.peel_blocks(); let blk = blk.innermost_block();
// Do not suggest if we have a tail expr. // Do not suggest if we have a tail expr.
if blk.expr.is_some() { if blk.expr.is_some() {
return false; return false;

View File

@ -325,7 +325,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}; };
let (error_sp, else_id) = if let ExprKind::Block(block, _) = &else_expr.kind { let (error_sp, else_id) = if let ExprKind::Block(block, _) = &else_expr.kind {
let block = block.peel_blocks(); let block = block.innermost_block();
// Avoid overlapping spans that aren't as readable: // Avoid overlapping spans that aren't as readable:
// ``` // ```
@ -366,7 +366,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}; };
let then_id = if let ExprKind::Block(block, _) = &then_expr.kind { let then_id = if let ExprKind::Block(block, _) = &then_expr.kind {
let block = block.peel_blocks(); let block = block.innermost_block();
// Exclude overlapping spans // Exclude overlapping spans
if block.expr.is_none() && block.stmts.is_empty() { if block.expr.is_none() && block.stmts.is_empty() {
outer_span = None; outer_span = None;