diff --git a/src/librustc_hir/lang_items.rs b/src/librustc_hir/lang_items.rs index a503e3534e3..53f72804a84 100644 --- a/src/librustc_hir/lang_items.rs +++ b/src/librustc_hir/lang_items.rs @@ -194,6 +194,7 @@ language_item_table! { ShrAssignTraitLangItem, "shr_assign", shr_assign_trait, Target::Trait; IndexTraitLangItem, "index", index_trait, Target::Trait; IndexMutTraitLangItem, "index_mut", index_mut_trait, Target::Trait; + UnsafeCellTypeLangItem, "unsafe_cell", unsafe_cell_type, Target::Struct; VaListTypeLangItem, "va_list", va_list, Target::Struct; diff --git a/src/librustc_middle/hir/map/mod.rs b/src/librustc_middle/hir/map/mod.rs index de0373c1384..a3f8cd1ee36 100644 --- a/src/librustc_middle/hir/map/mod.rs +++ b/src/librustc_middle/hir/map/mod.rs @@ -390,11 +390,7 @@ impl<'hir> Map<'hir> { /// Given a `HirId`, returns the `BodyId` associated with it, /// if the node is a body owner, otherwise returns `None`. pub fn maybe_body_owned_by(&self, hir_id: HirId) -> Option { - if let Some(node) = self.find(hir_id) { - associated_body(node) - } else { - bug!("no entry for id `{}`", hir_id) - } + if let Some(node) = self.find(hir_id) { associated_body(node) } else { None } } /// Given a body owner's id, returns the `BodyId` associated with it. diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index b28f0001cd9..5e3b383ff25 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1791,6 +1791,19 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let body_hir_id = obligation.cause.body_id; let item_id = self.tcx.hir().get_parent_node(body_hir_id); + let mut is_future = false; + if let ty::Opaque(def_id, substs) = trait_ref.self_ty().kind { + let preds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs); + for p in preds.predicates { + if let Some(trait_ref) = p.to_opt_poly_trait_ref() { + if Some(trait_ref.def_id()) == self.tcx.lang_items().future_trait() { + is_future = true; + break; + } + } + } + } + if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(item_id) { let body = self.tcx.hir().body(body_id); if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind { @@ -1802,6 +1815,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { .next() .unwrap() .def_id; + debug!("trait_ref_self_ty: {:?}", trait_ref.self_ty()); // `::Output` let projection_ty = ty::ProjectionTy { // `T` @@ -1813,7 +1827,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { item_def_id, }; - //let cause = ObligationCause::misc(span, body_hir_id); let mut selcx = SelectionContext::new(self); let mut obligations = vec![]; @@ -1826,7 +1839,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &mut obligations, ); - debug!("suggest_await_befor_try: normalized_projection_type {:?}", normalized_ty); + debug!( + "suggest_await_befor_try: normalized_projection_type {:?}", + self.resolve_vars_if_possible(&normalized_ty) + ); let try_obligation = self.mk_obligation_for_def_id( trait_ref.def_id(), normalized_ty, @@ -1834,7 +1850,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligation.param_env, ); debug!("suggest_await_befor_try: try_trait_obligation {:?}", try_obligation); - if self.predicate_may_hold(&try_obligation) { + if self.predicate_may_hold(&try_obligation) && is_future { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { if snippet.ends_with('?') { err.span_suggestion( diff --git a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr index 61f2570b2ff..96158fc0e04 100644 --- a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr +++ b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr @@ -237,7 +237,10 @@ error[E0277]: the `?` operator can only be applied to values that implement `std --> $DIR/incorrect-syntax-suggestions.rs:16:19 | LL | let _ = await bar()?; - | ^^^^^^ the `?` operator cannot be applied to type `impl std::future::Future` + | ^^^^^^ + | | + | the `?` operator cannot be applied to type `impl std::future::Future` + | help: consider using `.await` here: `bar().await?` | = help: the trait `std::ops::Try` is not implemented for `impl std::future::Future` = note: required by `std::ops::Try::into_result` diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs index 0c6c5311997..04a9148ae24 100644 --- a/src/test/ui/async-await/issue-61076.rs +++ b/src/test/ui/async-await/issue-61076.rs @@ -5,7 +5,7 @@ async fn foo() -> Result<(), ()> { } async fn bar() -> Result<(), ()> { - foo()?; + foo()?; //~ ERROR the `?` operator can only be applied to values that implement `std::ops::Try` Ok(()) } diff --git a/src/test/ui/async-await/issue-61076.stderr b/src/test/ui/async-await/issue-61076.stderr new file mode 100644 index 00000000000..fb1eead04e6 --- /dev/null +++ b/src/test/ui/async-await/issue-61076.stderr @@ -0,0 +1,15 @@ +error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try` + --> $DIR/issue-61076.rs:8:5 + | +LL | foo()?; + | ^^^^^^ + | | + | the `?` operator cannot be applied to type `impl std::future::Future` + | help: consider using `.await` here: `foo().await?` + | + = help: the trait `std::ops::Try` is not implemented for `impl std::future::Future` + = note: required by `std::ops::Try::into_result` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`.