diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 32fce1043d01..502edb4ac6b2 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -648,28 +648,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { trait_ref.to_predicate(), post_message) )); - let parent_node = self.tcx.hir().get_parent_node(obligation.cause.body_id); - let node = self.tcx.hir().find(parent_node); - if let Some(hir::Node::Item(hir::Item { - node: hir::ItemKind::Fn(decl, _, _, body_id), - .. - })) = node { - let body = self.tcx.hir().body(*body_id); - if let hir::ExprKind::Block(blk, _) = &body.value.node { - if decl.output.span().overlaps(span) && blk.expr.is_none() && - "()" == &trait_ref.self_ty().to_string() - { - // FIXME(estebank): When encountering a method with a trait - // bound not satisfied in the return type with a body that has - // no return, suggest removal of semicolon on last statement. - // Once that is added, close #54771. - if let Some(ref stmt) = blk.stmts.last() { - let sp = self.tcx.sess.source_map().end_point(stmt.span); - err.span_label(sp, "consider removing this semicolon"); - } - } - } - } let explanation = if obligation.cause.code == ObligationCauseCode::MainFunctionType { "consider using `()`, or a `Result`".to_owned() @@ -695,6 +673,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err); self.suggest_remove_reference(&obligation, &mut err, &trait_ref); + self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref); // Try to report a help message if !trait_ref.has_infer_types() && @@ -923,9 +902,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a /// suggestion to borrow the initializer in order to use have a slice instead. - fn suggest_borrow_on_unsized_slice(&self, - code: &ObligationCauseCode<'tcx>, - err: &mut DiagnosticBuilder<'tcx>) { + fn suggest_borrow_on_unsized_slice( + &self, + code: &ObligationCauseCode<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + ) { if let &ObligationCauseCode::VariableType(node_id) = code { let parent_node = self.tcx.hir().get_parent_node(node_id); if let Some(Node::Local(ref local)) = self.tcx.hir().find(parent_node) { @@ -947,10 +928,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`, /// suggest removing these references until we reach a type that implements the trait. - fn suggest_remove_reference(&self, - obligation: &PredicateObligation<'tcx>, - err: &mut DiagnosticBuilder<'tcx>, - trait_ref: &ty::Binder>) { + fn suggest_remove_reference( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + trait_ref: &ty::Binder>, + ) { let trait_ref = trait_ref.skip_binder(); let span = obligation.cause.span; @@ -992,6 +975,40 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } + fn suggest_semicolon_removal( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + span: Span, + trait_ref: &ty::Binder>, + ) { + let hir = self.tcx.hir(); + let parent_node = hir.get_parent_node( + hir.hir_to_node_id(obligation.cause.body_id), + ); + let node = hir.find(parent_node); + if let Some(hir::Node::Item(hir::Item { + node: hir::ItemKind::Fn(decl, _, _, body_id), + .. + })) = node { + let body = hir.body(*body_id); + if let hir::ExprKind::Block(blk, _) = &body.value.node { + if decl.output.span().overlaps(span) && blk.expr.is_none() && + "()" == &trait_ref.self_ty().to_string() + { + // FIXME(estebank): When encountering a method with a trait + // bound not satisfied in the return type with a body that has + // no return, suggest removal of semicolon on last statement. + // Once that is added, close #54771. + if let Some(ref stmt) = blk.stmts.last() { + let sp = self.tcx.sess.source_map().end_point(stmt.span); + err.span_label(sp, "consider removing this semicolon"); + } + } + } + } + } + /// Given some node representing a fn-like thing in the HIR map, /// returns a span and `ArgKind` information that describes the /// arguments it expects. This can be supplied to