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]; // `::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(fut: impl Future) -> 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(fut: impl Future) -> 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>` + | + = help: the trait `Try` is not implemented for `impl Future>` +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`.