diff options
| author | bors <bors@rust-lang.org> | 2023-12-26 04:25:53 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-12-26 04:25:53 +0000 |
| commit | 1ab783112ab4e4807304dbd249b39771246013ef (patch) | |
| tree | 827d6051e0e3ffcaadd0d6c7369b71547319a525 /compiler/rustc_trait_selection/src | |
| parent | 2271c26e4a8e062bb00d709d0ccb5846e0c341b9 (diff) | |
| parent | ba912855cc1aff5f2b403411c8d890d3978abf9a (diff) | |
| download | rust-1ab783112ab4e4807304dbd249b39771246013ef.tar.gz rust-1ab783112ab4e4807304dbd249b39771246013ef.zip | |
Auto merge of #119258 - compiler-errors:closure-kind, r=eholk
Make closures carry their own ClosureKind Right now, we use the "`movability`" field of `hir::Closure` to distinguish a closure and a coroutine. This is paired together with the `CoroutineKind`, which is located not in the `hir::Closure`, but the `hir::Body`. This is strange and redundant. This PR introduces `ClosureKind` with two variants -- `Closure` and `Coroutine`, which is put into `hir::Closure`. The `CoroutineKind` is thus removed from `hir::Body`, and `Option<Movability>` no longer needs to be a stand-in for "is this a closure or a coroutine". r? eholk
Diffstat (limited to 'compiler/rustc_trait_selection/src')
3 files changed, 102 insertions, 137 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 13ac2e26e40..52f91d282f0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -8,7 +8,7 @@ use rustc_attr as attr; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{struct_span_err, ErrorGuaranteed}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt}; use rustc_parse_format::{ParseMode, Parser, Piece, Position}; @@ -32,7 +32,7 @@ pub trait TypeErrCtxtExt<'tcx> { ) -> Option<(DefId, GenericArgsRef<'tcx>)>; /*private*/ - fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str>; + fn describe_enclosure(&self, def_id: LocalDefId) -> Option<&'static str>; fn on_unimplemented_note( &self, @@ -101,43 +101,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { /// Used to set on_unimplemented's `ItemContext` /// to be the enclosing (async) block/function/closure - fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> { - let hir = self.tcx.hir(); - let node = self.tcx.opt_hir_node(hir_id)?; - match &node { - hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => { - self.describe_coroutine(*body_id).or_else(|| { - Some(match sig.header { - hir::FnHeader { asyncness: hir::IsAsync::Async(_), .. } => { - "an async function" - } - _ => "a function", - }) - }) + fn describe_enclosure(&self, def_id: LocalDefId) -> Option<&'static str> { + match self.tcx.opt_hir_node_by_def_id(def_id)? { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }) => Some("a function"), + hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) => { + Some("a trait method") + } + hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => { + Some("a method") } - hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)), - .. - }) => self.describe_coroutine(*body_id).or_else(|| Some("a trait method")), - hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(sig, body_id), - .. - }) => self.describe_coroutine(*body_id).or_else(|| { - Some(match sig.header { - hir::FnHeader { asyncness: hir::IsAsync::Async(_), .. } => "an async method", - _ => "a method", - }) - }), hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Closure(hir::Closure { body, movability, .. }), + kind: hir::ExprKind::Closure(hir::Closure { kind, .. }), .. - }) => self.describe_coroutine(*body).or_else(|| { - Some(if movability.is_some() { "an async closure" } else { "a closure" }) - }), - hir::Node::Expr(hir::Expr { .. }) => { - let parent_hid = hir.parent_id(hir_id); - if parent_hid != hir_id { self.describe_enclosure(parent_hid) } else { None } - } + }) => Some(self.describe_closure(*kind)), _ => None, } } @@ -156,12 +132,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): HIR is not present for RPITITs, // but I guess we could synthesize one here. We don't see any errors that rely on // that yet, though. - let enclosure = - if let Some(body_hir) = self.tcx.opt_local_def_id_to_hir_id(obligation.cause.body_id) { - self.describe_enclosure(body_hir).map(|s| s.to_owned()) - } else { - None - }; + let enclosure = self.describe_enclosure(obligation.cause.body_id).map(|t| t.to_owned()); flags.push((sym::ItemContext, enclosure)); match obligation.cause.code() { 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 e1f3c6d4f97..171b86d4f25 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2577,7 +2577,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let message = outer_coroutine .and_then(|coroutine_did| { Some(match self.tcx.coroutine_kind(coroutine_did).unwrap() { - CoroutineKind::Coroutine => format!("coroutine is not {trait_name}"), + CoroutineKind::Coroutine(_) => format!("coroutine is not {trait_name}"), CoroutineKind::Desugared( CoroutineDesugaring::Async, CoroutineSource::Fn, @@ -3169,7 +3169,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ObligationCauseCode::SizedCoroutineInterior(coroutine_def_id) => { let what = match self.tcx.coroutine_kind(coroutine_def_id) { None - | Some(hir::CoroutineKind::Coroutine) + | Some(hir::CoroutineKind::Coroutine(_)) | Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => { "yield" } @@ -3564,55 +3564,52 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, span: Span, ) { - if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) { - let body = self.tcx.hir().body(body_id); - if let Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) = - body.coroutine_kind - { - let future_trait = self.tcx.require_lang_item(LangItem::Future, None); + if let Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) = + self.tcx.coroutine_kind(obligation.cause.body_id) + { + let future_trait = self.tcx.require_lang_item(LangItem::Future, None); - let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); - let impls_future = self.type_implements_trait( - future_trait, - [self.tcx.instantiate_bound_regions_with_erased(self_ty)], - obligation.param_env, - ); - if !impls_future.must_apply_modulo_regions() { - return; - } + let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); + let impls_future = self.type_implements_trait( + future_trait, + [self.tcx.instantiate_bound_regions_with_erased(self_ty)], + 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 = trait_pred.map_bound(|trait_pred| { - Ty::new_projection( - self.tcx, - item_def_id, - // Future::Output has no args - [trait_pred.self_ty()], - ) - }); - let InferOk { value: projection_ty, .. } = - self.at(&obligation.cause, obligation.param_env).normalize(projection_ty); + let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0]; + // `<T as Future>::Output` + let projection_ty = trait_pred.map_bound(|trait_pred| { + Ty::new_projection( + self.tcx, + item_def_id, + // Future::Output has no args + [trait_pred.self_ty()], + ) + }); + let InferOk { value: projection_ty, .. } = + self.at(&obligation.cause, obligation.param_env).normalize(projection_ty); - debug!( - normalized_projection_type = ?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, projection_ty.skip_binder())), + debug!( + normalized_projection_type = ?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, projection_ty.skip_binder())), + ); + debug!(try_trait_obligation = ?try_obligation); + if self.predicate_may_hold(&try_obligation) + && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) + && snippet.ends_with('?') + { + err.span_suggestion_verbose( + span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(), + "consider `await`ing on the `Future`", + ".await", + Applicability::MaybeIncorrect, ); - debug!(try_trait_obligation = ?try_obligation); - if self.predicate_may_hold(&try_obligation) - && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) - && snippet.ends_with('?') - { - err.span_suggestion_verbose( - span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(), - "consider `await`ing on the `Future`", - ".await", - Applicability::MaybeIncorrect, - ); - } } } } @@ -4665,13 +4662,7 @@ impl<'v> Visitor<'v> for ReturnsVisitor<'v> { fn visit_body(&mut self, body: &'v hir::Body<'v>) { assert!(!self.in_block_tail); - if body.coroutine_kind().is_none() { - if let hir::ExprKind::Block(block, None) = body.value.kind { - if block.expr.is_some() { - self.in_block_tail = true; - } - } - } + self.in_block_tail = true; hir::intravisit::walk_body(self, body); } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 4b84aae70fd..d2598b0defe 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -1348,7 +1348,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> { ignoring_lifetimes: bool, ) -> Option<CandidateSimilarity>; - fn describe_coroutine(&self, body_id: hir::BodyId) -> Option<&'static str>; + fn describe_closure(&self, kind: hir::ClosureKind) -> &'static str; fn find_similar_impl_candidates( &self, @@ -1925,46 +1925,49 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } - fn describe_coroutine(&self, body_id: hir::BodyId) -> Option<&'static str> { - self.tcx.hir().body(body_id).coroutine_kind.map(|coroutine_source| match coroutine_source { - hir::CoroutineKind::Coroutine => "a coroutine", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Async, - hir::CoroutineSource::Block, - ) => "an async block", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Async, - hir::CoroutineSource::Fn, - ) => "an async function", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Async, - hir::CoroutineSource::Closure, - ) => "an async closure", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::AsyncGen, - hir::CoroutineSource::Block, - ) => "an async gen block", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::AsyncGen, - hir::CoroutineSource::Fn, - ) => "an async gen function", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::AsyncGen, - hir::CoroutineSource::Closure, - ) => "an async gen closure", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Gen, - hir::CoroutineSource::Block, - ) => "a gen block", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Gen, - hir::CoroutineSource::Fn, - ) => "a gen function", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Gen, - hir::CoroutineSource::Closure, - ) => "a gen closure", - }) + fn describe_closure(&self, kind: hir::ClosureKind) -> &'static str { + match kind { + hir::ClosureKind::Closure => "a closure", + hir::ClosureKind::Coroutine(kind) => match kind { + hir::CoroutineKind::Coroutine(_) => "a coroutine", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Block, + ) => "an async block", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Fn, + ) => "an async function", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Closure, + ) => "an async closure", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::AsyncGen, + hir::CoroutineSource::Block, + ) => "an async gen block", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::AsyncGen, + hir::CoroutineSource::Fn, + ) => "an async gen function", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::AsyncGen, + hir::CoroutineSource::Closure, + ) => "an async gen closure", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Gen, + hir::CoroutineSource::Block, + ) => "a gen block", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Gen, + hir::CoroutineSource::Fn, + ) => "a gen function", + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Gen, + hir::CoroutineSource::Closure, + ) => "a gen closure", + }, + } } fn find_similar_impl_candidates( |
