|
1 | 1 | use super::{
|
2 | 2 | EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation,
|
| 3 | + SelectionContext, |
3 | 4 | };
|
4 | 5 |
|
5 | 6 | use crate::infer::InferCtxt;
|
| 7 | +use crate::traits::normalize_projection_type; |
6 | 8 |
|
7 | 9 | use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style};
|
8 | 10 | use rustc_hir as hir;
|
@@ -150,6 +152,15 @@ pub trait InferCtxtExt<'tcx> {
|
150 | 152 | T: fmt::Display;
|
151 | 153 |
|
152 | 154 | fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>);
|
| 155 | + |
| 156 | + /// Suggest to await before try: future? => future.await? |
| 157 | + fn suggest_await_befor_try( |
| 158 | + &self, |
| 159 | + err: &mut DiagnosticBuilder<'_>, |
| 160 | + obligation: &PredicateObligation<'tcx>, |
| 161 | + ty: Ty<'tcx>, |
| 162 | + span: Span, |
| 163 | + ); |
153 | 164 | }
|
154 | 165 |
|
155 | 166 | fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) {
|
@@ -1765,6 +1776,75 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
1765 | 1776 | suggested_limit, self.tcx.crate_name,
|
1766 | 1777 | ));
|
1767 | 1778 | }
|
| 1779 | + |
| 1780 | + fn suggest_await_befor_try( |
| 1781 | + &self, |
| 1782 | + err: &mut DiagnosticBuilder<'_>, |
| 1783 | + obligation: &PredicateObligation<'tcx>, |
| 1784 | + ty: Ty<'tcx>, |
| 1785 | + span: Span, |
| 1786 | + ) { |
| 1787 | + debug!("suggest_await_befor_try: obligation={:?}, span={:?}", obligation, span); |
| 1788 | + let body_hir_id = obligation.cause.body_id; |
| 1789 | + let item_id = self.tcx.hir().get_parent_node(body_hir_id); |
| 1790 | + if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(item_id) { |
| 1791 | + let body = self.tcx.hir().body(body_id); |
| 1792 | + if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind { |
| 1793 | + // Check for `Future` implementations by constructing a predicate to |
| 1794 | + // prove: `<T as Future>::Output == U` |
| 1795 | + let future_trait = self.tcx.lang_items().future_trait().unwrap(); |
| 1796 | + let item_def_id = self |
| 1797 | + .tcx |
| 1798 | + .associated_items(future_trait) |
| 1799 | + .in_definition_order() |
| 1800 | + .next() |
| 1801 | + .unwrap() |
| 1802 | + .def_id; |
| 1803 | + // `<T as Future>::Output` |
| 1804 | + let projection_ty = ty::ProjectionTy { |
| 1805 | + // `T` |
| 1806 | + substs: self |
| 1807 | + .tcx |
| 1808 | + .mk_substs_trait(ty, self.fresh_substs_for_item(span, item_def_id)), |
| 1809 | + // `Future::Output` |
| 1810 | + item_def_id, |
| 1811 | + }; |
| 1812 | + |
| 1813 | + let cause = ObligationCause::misc(span, body_hir_id); |
| 1814 | + let mut selcx = SelectionContext::new(self); |
| 1815 | + |
| 1816 | + let mut obligations = vec![]; |
| 1817 | + let normalized_ty = normalize_projection_type( |
| 1818 | + &mut selcx, |
| 1819 | + obligation.param_env, |
| 1820 | + projection_ty, |
| 1821 | + obligation.cause.clone(), |
| 1822 | + 0, |
| 1823 | + &mut obligations, |
| 1824 | + ); |
| 1825 | + |
| 1826 | + debug!("suggest_await_befor_try: normalized_projection_type {:?}", normalized_ty); |
| 1827 | + let try_trait_ref_id = self.tcx.lang_items().try_trait().unwrap(); |
| 1828 | + if let Some(try_trait_ref) = self.tcx.impl_trait_ref(try_trait_ref_id) { |
| 1829 | + let try_predicate = try_trait_ref.without_const().to_predicate(); |
| 1830 | + let try_obligation = |
| 1831 | + Obligation::new(cause, obligation.param_env, try_predicate); |
| 1832 | + debug!("suggest_await_befor_try: try_trait_obligation {:?}", try_obligation); |
| 1833 | + if self.predicate_may_hold(&try_obligation) { |
| 1834 | + debug!("try_obligation holds"); |
| 1835 | + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { |
| 1836 | + err.span_suggestion( |
| 1837 | + span, |
| 1838 | + "consider using `.await` here", |
| 1839 | + format!("{}.await", snippet), |
| 1840 | + Applicability::MaybeIncorrect, |
| 1841 | + ); |
| 1842 | + } |
| 1843 | + } |
| 1844 | + } |
| 1845 | + } |
| 1846 | + } |
| 1847 | + } |
1768 | 1848 | }
|
1769 | 1849 |
|
1770 | 1850 | /// Collect all the returned expressions within the input expression.
|
|
0 commit comments