diff options
| author | León Orell Valerian Liehr <me@fmease.dev> | 2024-04-23 17:25:16 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-04-23 17:25:16 +0200 |
| commit | e15d6f9d8580b5f54376c2c48bd5ecf8ba0b5ce7 (patch) | |
| tree | 1fa63bd3dbb0e1ddef8f3ccc9c9f170dcbcc2bc7 /compiler/rustc_mir_transform/src | |
| parent | 2d7d4800548e3b8ad3133b909aa9020954567640 (diff) | |
| parent | a8c9a0bd8167c99557c9d475631c844775883336 (diff) | |
| download | rust-e15d6f9d8580b5f54376c2c48bd5ecf8ba0b5ce7.tar.gz rust-e15d6f9d8580b5f54376c2c48bd5ecf8ba0b5ce7.zip | |
Rollup merge of #123993 - compiler-errors:coroutine-obl, r=lcnr
Do `check_coroutine_obligations` once per typeck root We only need to do `check_coroutine_obligations` once per typeck root, especially since the new solver can't really (easily) associate which obligations correspond to which coroutines. This requires us to move the checks for sized coroutine fields into `mir_coroutine_witnesses`, but that's fine imo. r? lcnr
Diffstat (limited to 'compiler/rustc_mir_transform/src')
| -rw-r--r-- | compiler/rustc_mir_transform/src/coroutine.rs | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index e2a911f0dc7..b745d97567d 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -80,6 +80,10 @@ use rustc_span::symbol::sym; use rustc_span::Span; use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_target::spec::PanicStrategy; +use rustc_trait_selection::infer::TyCtxtInferExt as _; +use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; +use rustc_trait_selection::traits::ObligationCtxt; +use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode}; use std::{iter, ops}; pub struct StateTransform; @@ -1584,10 +1588,46 @@ pub(crate) fn mir_coroutine_witnesses<'tcx>( let (_, coroutine_layout, _) = compute_layout(liveness_info, body); check_suspend_tys(tcx, &coroutine_layout, body); + check_field_tys_sized(tcx, &coroutine_layout, def_id); Some(coroutine_layout) } +fn check_field_tys_sized<'tcx>( + tcx: TyCtxt<'tcx>, + coroutine_layout: &CoroutineLayout<'tcx>, + def_id: LocalDefId, +) { + // No need to check if unsized_locals/unsized_fn_params is disabled, + // since we will error during typeck. + if !tcx.features().unsized_locals && !tcx.features().unsized_fn_params { + return; + } + + let infcx = tcx.infer_ctxt().ignoring_regions().build(); + let param_env = tcx.param_env(def_id); + + let ocx = ObligationCtxt::new(&infcx); + for field_ty in &coroutine_layout.field_tys { + ocx.register_bound( + ObligationCause::new( + field_ty.source_info.span, + def_id, + ObligationCauseCode::SizedCoroutineInterior(def_id), + ), + param_env, + field_ty.ty, + tcx.require_lang_item(hir::LangItem::Sized, Some(field_ty.source_info.span)), + ); + } + + let errors = ocx.select_all_or_error(); + debug!(?errors); + if !errors.is_empty() { + infcx.err_ctxt().report_fulfillment_errors(errors); + } +} + impl<'tcx> MirPass<'tcx> for StateTransform { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let Some(old_yield_ty) = body.yield_ty() else { |
