about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-06-06 08:37:01 +0200
committerGitHub <noreply@github.com>2022-06-06 08:37:01 +0200
commitdf86d04977aeda80c9e599cf6ce197b46a0dea2f (patch)
tree320bcffe3994867279ddeb5e971946f41aae2c72
parentf2b3808920bdb8803acc04a8946e1d99edaf7514 (diff)
parentd268b34da48373a54a3f4666b3b83277ad8f9db3 (diff)
downloadrust-df86d04977aeda80c9e599cf6ce197b46a0dea2f.tar.gz
rust-df86d04977aeda80c9e599cf6ce197b46a0dea2f.zip
Rollup merge of #97721 - compiler-errors:issue-97704, r=jackh726
Do `suggest_await_before_try` with infer variables in self, and clean up binders

Fixes #97704

Also cleans up binders in this fn, since everything is a `Poly*` and we really shouldn't have stray escaping late-bound regions everywhere. That's why the function changed so much. This isn't necessary, so I can revert if necessary.
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs48
-rw-r--r--src/test/ui/suggestions/issue-97704.fixed19
-rw-r--r--src/test/ui/suggestions/issue-97704.rs19
-rw-r--r--src/test/ui/suggestions/issue-97704.stderr15
4 files changed, 71 insertions, 30 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index fd0732f51d5..185f500808f 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -5,7 +5,7 @@ use super::{
 
 use crate::autoderef::Autoderef;
 use crate::infer::InferCtxt;
-use crate::traits::normalize_projection_type;
+use crate::traits::normalize_to;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -2706,55 +2706,43 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
 
                 let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
-
-                // Do not check on infer_types to avoid panic in evaluate_obligation.
-                if self_ty.has_infer_types() {
-                    return;
-                }
-                let self_ty = self.tcx.erase_regions(self_ty);
-
                 let impls_future = self.type_implements_trait(
                     future_trait,
-                    self_ty.skip_binder(),
+                    self.tcx.erase_late_bound_regions(self_ty),
                     ty::List::empty(),
                     obligation.param_env,
                 );
+                if !impls_future.must_apply_modulo_regions() {
+                    return;
+                }
 
                 let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
                 // `<T as Future>::Output`
-                let projection_ty = ty::ProjectionTy {
-                    // `T`
-                    substs: self.tcx.mk_substs_trait(
-                        trait_pred.self_ty().skip_binder(),
-                        &self.fresh_substs_for_item(span, item_def_id)[1..],
-                    ),
-                    // `Future::Output`
-                    item_def_id,
-                };
-
-                let mut selcx = SelectionContext::new(self);
-
-                let mut obligations = vec![];
-                let normalized_ty = normalize_projection_type(
-                    &mut selcx,
+                let projection_ty = trait_pred.map_bound(|trait_pred| {
+                    self.tcx.mk_projection(
+                        item_def_id,
+                        // Future::Output has no substs
+                        self.tcx.mk_substs_trait(trait_pred.self_ty(), &[]),
+                    )
+                });
+                let projection_ty = normalize_to(
+                    &mut SelectionContext::new(self),
                     obligation.param_env,
-                    projection_ty,
                     obligation.cause.clone(),
-                    0,
-                    &mut obligations,
+                    projection_ty,
+                    &mut vec![],
                 );
 
                 debug!(
                     "suggest_await_before_try: normalized_projection_type {:?}",
-                    self.resolve_vars_if_possible(normalized_ty)
+                    self.resolve_vars_if_possible(projection_ty)
                 );
                 let try_obligation = self.mk_trait_obligation_with_new_self_ty(
                     obligation.param_env,
-                    trait_pred.map_bound(|trait_pred| (trait_pred, normalized_ty.ty().unwrap())),
+                    trait_pred.map_bound(|trait_pred| (trait_pred, projection_ty.skip_binder())),
                 );
                 debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation);
                 if self.predicate_may_hold(&try_obligation)
-                    && impls_future.must_apply_modulo_regions()
                     && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
                     && snippet.ends_with('?')
                 {
diff --git a/src/test/ui/suggestions/issue-97704.fixed b/src/test/ui/suggestions/issue-97704.fixed
new file mode 100644
index 00000000000..c42bdfff5f9
--- /dev/null
+++ b/src/test/ui/suggestions/issue-97704.fixed
@@ -0,0 +1,19 @@
+// edition:2021
+// run-rustfix
+
+#![allow(unused)]
+
+use std::future::Future;
+
+async fn foo() -> Result<(), i32> {
+    func(async { Ok::<_, i32>(()) }).await?;
+    //~^ ERROR the `?` operator can only be applied to values that implement `Try`
+
+    Ok(())
+}
+
+async fn func<T>(fut: impl Future<Output = T>) -> T {
+    fut.await
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/issue-97704.rs b/src/test/ui/suggestions/issue-97704.rs
new file mode 100644
index 00000000000..5dfee6cac60
--- /dev/null
+++ b/src/test/ui/suggestions/issue-97704.rs
@@ -0,0 +1,19 @@
+// edition:2021
+// run-rustfix
+
+#![allow(unused)]
+
+use std::future::Future;
+
+async fn foo() -> Result<(), i32> {
+    func(async { Ok::<_, i32>(()) })?;
+    //~^ ERROR the `?` operator can only be applied to values that implement `Try`
+
+    Ok(())
+}
+
+async fn func<T>(fut: impl Future<Output = T>) -> T {
+    fut.await
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/issue-97704.stderr b/src/test/ui/suggestions/issue-97704.stderr
new file mode 100644
index 00000000000..ca017be45ac
--- /dev/null
+++ b/src/test/ui/suggestions/issue-97704.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the `?` operator can only be applied to values that implement `Try`
+  --> $DIR/issue-97704.rs:9:5
+   |
+LL |     func(async { Ok::<_, i32>(()) })?;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future<Output = Result<(), i32>>`
+   |
+   = help: the trait `Try` is not implemented for `impl Future<Output = Result<(), i32>>`
+help: consider `await`ing on the `Future`
+   |
+LL |     func(async { Ok::<_, i32>(()) }).await?;
+   |                                     ++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.