diff options
| author | Laurențiu Nicola <lnicola@dend.ro> | 2025-06-09 15:44:40 +0300 |
|---|---|---|
| committer | Laurențiu Nicola <lnicola@dend.ro> | 2025-06-09 15:44:40 +0300 |
| commit | 88223c56d9352a14bf4e91d706d68ca3a696bcdf (patch) | |
| tree | 1fa465adaaf07355079312d2e1aa3e8594acadc7 /compiler/rustc_mir_transform/src | |
| parent | cbe6fe86ef60ceedd46128df8f09da982f44191a (diff) | |
| parent | 7c10378e1fee5ddc6573b916aeb884ab10e0de17 (diff) | |
| download | rust-88223c56d9352a14bf4e91d706d68ca3a696bcdf.tar.gz rust-88223c56d9352a14bf4e91d706d68ca3a696bcdf.zip | |
Merge from rust-lang/rust
Diffstat (limited to 'compiler/rustc_mir_transform/src')
17 files changed, 215 insertions, 346 deletions
diff --git a/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs b/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs deleted file mode 100644 index daddb5dedbc..00000000000 --- a/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs +++ /dev/null @@ -1,77 +0,0 @@ -use rustc_middle::mir::visit::Visitor; -use rustc_middle::mir::{Body, Location, Operand, Terminator, TerminatorKind}; -use rustc_middle::ty::{AssocItem, AssocKind, TyCtxt}; -use rustc_session::lint::builtin::PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS; -use rustc_span::sym; - -use crate::errors; - -/// Check for transmutes that exhibit undefined behavior. -/// For example, transmuting pointers to integers in a const context. -pub(super) struct CheckUndefinedTransmutes; - -impl<'tcx> crate::MirLint<'tcx> for CheckUndefinedTransmutes { - fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { - let mut checker = UndefinedTransmutesChecker { body, tcx }; - checker.visit_body(body); - } -} - -struct UndefinedTransmutesChecker<'a, 'tcx> { - body: &'a Body<'tcx>, - tcx: TyCtxt<'tcx>, -} - -impl<'a, 'tcx> UndefinedTransmutesChecker<'a, 'tcx> { - // This functions checks two things: - // 1. `function` takes a raw pointer as input and returns an integer as output. - // 2. `function` is called from a const function or an associated constant. - // - // Why do we consider const functions and associated constants only? - // - // Generally, undefined behavior in const items are handled by the evaluator. - // But, const functions and associated constants are evaluated only when referenced. - // This can result in undefined behavior in a library going unnoticed until - // the function or constant is actually used. - // - // Therefore, we only consider const functions and associated constants here and leave - // other const items to be handled by the evaluator. - fn is_ptr_to_int_in_const(&self, function: &Operand<'tcx>) -> bool { - let def_id = self.body.source.def_id(); - - if self.tcx.is_const_fn(def_id) - || matches!( - self.tcx.opt_associated_item(def_id), - Some(AssocItem { kind: AssocKind::Const { .. }, .. }) - ) - { - let fn_sig = function.ty(self.body, self.tcx).fn_sig(self.tcx).skip_binder(); - if let [input] = fn_sig.inputs() { - return input.is_raw_ptr() && fn_sig.output().is_integral(); - } - } - false - } -} - -impl<'tcx> Visitor<'tcx> for UndefinedTransmutesChecker<'_, 'tcx> { - // Check each block's terminator for calls to pointer to integer transmutes - // in const functions or associated constants and emit a lint. - fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { - if let TerminatorKind::Call { func, .. } = &terminator.kind - && let Some((func_def_id, _)) = func.const_fn_def() - && self.tcx.is_intrinsic(func_def_id, sym::transmute) - && self.is_ptr_to_int_in_const(func) - && let Some(call_id) = self.body.source.def_id().as_local() - { - let hir_id = self.tcx.local_def_id_to_hir_id(call_id); - let span = self.body.source_info(location).span; - self.tcx.emit_node_span_lint( - PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS, - hir_id, - span, - errors::UndefinedTransmute, - ); - } - } -} diff --git a/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs b/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs deleted file mode 100644 index 8da17a056e3..00000000000 --- a/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs +++ /dev/null @@ -1,124 +0,0 @@ -use rustc_middle::mir::visit::Visitor; -use rustc_middle::mir::{Body, Location, Operand, Terminator, TerminatorKind}; -use rustc_middle::ty::*; -use rustc_session::lint::builtin::UNNECESSARY_TRANSMUTES; -use rustc_span::source_map::Spanned; -use rustc_span::{Span, sym}; - -use crate::errors::UnnecessaryTransmute as Error; - -/// Check for transmutes that overlap with stdlib methods. -/// For example, transmuting `[u8; 4]` to `u32`. -pub(super) struct CheckUnnecessaryTransmutes; - -impl<'tcx> crate::MirLint<'tcx> for CheckUnnecessaryTransmutes { - fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { - let mut checker = UnnecessaryTransmuteChecker { body, tcx }; - checker.visit_body(body); - } -} - -struct UnnecessaryTransmuteChecker<'a, 'tcx> { - body: &'a Body<'tcx>, - tcx: TyCtxt<'tcx>, -} - -impl<'a, 'tcx> UnnecessaryTransmuteChecker<'a, 'tcx> { - fn is_unnecessary_transmute( - &self, - function: &Operand<'tcx>, - arg: String, - span: Span, - ) -> Option<Error> { - let fn_sig = function.ty(self.body, self.tcx).fn_sig(self.tcx).skip_binder(); - let [input] = fn_sig.inputs() else { return None }; - - let err = |sugg| Error { span, sugg, help: None }; - - Some(match (input.kind(), fn_sig.output().kind()) { - // dont check the length; transmute does that for us. - // [u8; _] => primitive - (Array(t, _), Uint(_) | Float(_) | Int(_)) if *t.kind() == Uint(UintTy::U8) => Error { - sugg: format!("{}::from_ne_bytes({arg})", fn_sig.output()), - help: Some( - "there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order", - ), - span, - }, - // primitive => [u8; _] - (Uint(_) | Float(_) | Int(_), Array(t, _)) if *t.kind() == Uint(UintTy::U8) => Error { - sugg: format!("{input}::to_ne_bytes({arg})"), - help: Some( - "there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order", - ), - span, - }, - // char → u32 - (Char, Uint(UintTy::U32)) => err(format!("u32::from({arg})")), - // char (→ u32) → i32 - (Char, Int(IntTy::I32)) => err(format!("u32::from({arg}).cast_signed()")), - // u32 → char - (Uint(UintTy::U32), Char) => Error { - sugg: format!("char::from_u32_unchecked({arg})"), - help: Some("consider `char::from_u32(…).unwrap()`"), - span, - }, - // i32 → char - (Int(IntTy::I32), Char) => Error { - sugg: format!("char::from_u32_unchecked(i32::cast_unsigned({arg}))"), - help: Some("consider `char::from_u32(i32::cast_unsigned(…)).unwrap()`"), - span, - }, - // uNN → iNN - (Uint(ty), Int(_)) => err(format!("{}::cast_signed({arg})", ty.name_str())), - // iNN → uNN - (Int(ty), Uint(_)) => err(format!("{}::cast_unsigned({arg})", ty.name_str())), - // fNN → xsize - (Float(ty), Uint(UintTy::Usize)) => { - err(format!("{}::to_bits({arg}) as usize", ty.name_str())) - } - (Float(ty), Int(IntTy::Isize)) => { - err(format!("{}::to_bits({arg}) as isize", ty.name_str())) - } - // fNN (→ uNN) → iNN - (Float(ty), Int(..)) => err(format!("{}::to_bits({arg}).cast_signed()", ty.name_str())), - // fNN → uNN - (Float(ty), Uint(..)) => err(format!("{}::to_bits({arg})", ty.name_str())), - // xsize → fNN - (Uint(UintTy::Usize) | Int(IntTy::Isize), Float(ty)) => { - err(format!("{}::from_bits({arg} as _)", ty.name_str(),)) - } - // iNN (→ uNN) → fNN - (Int(int_ty), Float(ty)) => err(format!( - "{}::from_bits({}::cast_unsigned({arg}))", - ty.name_str(), - int_ty.name_str() - )), - // uNN → fNN - (Uint(_), Float(ty)) => err(format!("{}::from_bits({arg})", ty.name_str())), - // bool → { x8 } - (Bool, Int(..) | Uint(..)) => err(format!("({arg}) as {}", fn_sig.output())), - // u8 → bool - (Uint(_), Bool) => err(format!("({arg} == 1)")), - _ => return None, - }) - } -} - -impl<'tcx> Visitor<'tcx> for UnnecessaryTransmuteChecker<'_, 'tcx> { - // Check each block's terminator for calls to pointer to integer transmutes - // in const functions or associated constants and emit a lint. - fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { - if let TerminatorKind::Call { func, args, .. } = &terminator.kind - && let [Spanned { span: arg, .. }] = **args - && let Some((func_def_id, _)) = func.const_fn_def() - && self.tcx.is_intrinsic(func_def_id, sym::transmute) - && let span = self.body.source_info(location).span - && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(arg) - && let Some(lint) = self.is_unnecessary_transmute(func, snippet, span) - && let Some(hir_id) = terminator.source_info.scope.lint_root(&self.body.source_scopes) - { - self.tcx.emit_node_span_lint(UNNECESSARY_TRANSMUTES, hir_id, span, lint); - } - } -} diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index cddb2f84778..d5d0d56f528 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -225,7 +225,7 @@ impl<'tcx> TransformVisitor<'tcx> { CoroutineKind::Coroutine(_) => span_bug!(body.span, "`Coroutine`s cannot be fused"), // `gen` continues return `None` CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => { - let option_def_id = self.tcx.require_lang_item(LangItem::Option, None); + let option_def_id = self.tcx.require_lang_item(LangItem::Option, body.span); make_aggregate_adt( option_def_id, VariantIdx::ZERO, @@ -242,7 +242,7 @@ impl<'tcx> TransformVisitor<'tcx> { span: source_info.span, const_: Const::Unevaluated( UnevaluatedConst::new( - self.tcx.require_lang_item(LangItem::AsyncGenFinished, None), + self.tcx.require_lang_item(LangItem::AsyncGenFinished, body.span), self.tcx.mk_args(&[yield_ty.into()]), ), self.old_yield_ty, @@ -282,7 +282,7 @@ impl<'tcx> TransformVisitor<'tcx> { const ONE: VariantIdx = VariantIdx::from_usize(1); let rvalue = match self.coroutine_kind { CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => { - let poll_def_id = self.tcx.require_lang_item(LangItem::Poll, None); + let poll_def_id = self.tcx.require_lang_item(LangItem::Poll, source_info.span); let args = self.tcx.mk_args(&[self.old_ret_ty.into()]); let (variant_idx, operands) = if is_return { (ZERO, IndexVec::from_raw(vec![val])) // Poll::Ready(val) @@ -292,7 +292,7 @@ impl<'tcx> TransformVisitor<'tcx> { make_aggregate_adt(poll_def_id, variant_idx, args, operands) } CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => { - let option_def_id = self.tcx.require_lang_item(LangItem::Option, None); + let option_def_id = self.tcx.require_lang_item(LangItem::Option, source_info.span); let args = self.tcx.mk_args(&[self.old_yield_ty.into()]); let (variant_idx, operands) = if is_return { (ZERO, IndexVec::new()) // None @@ -310,7 +310,10 @@ impl<'tcx> TransformVisitor<'tcx> { span: source_info.span, const_: Const::Unevaluated( UnevaluatedConst::new( - self.tcx.require_lang_item(LangItem::AsyncGenFinished, None), + self.tcx.require_lang_item( + LangItem::AsyncGenFinished, + source_info.span, + ), self.tcx.mk_args(&[yield_ty.into()]), ), self.old_yield_ty, @@ -323,7 +326,7 @@ impl<'tcx> TransformVisitor<'tcx> { } CoroutineKind::Coroutine(_) => { let coroutine_state_def_id = - self.tcx.require_lang_item(LangItem::CoroutineState, None); + self.tcx.require_lang_item(LangItem::CoroutineState, source_info.span); let args = self.tcx.mk_args(&[self.old_yield_ty.into(), self.old_ret_ty.into()]); let variant_idx = if is_return { ONE // CoroutineState::Complete(val) @@ -496,7 +499,7 @@ fn make_coroutine_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Bo fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let ref_coroutine_ty = body.local_decls.raw[1].ty; - let pin_did = tcx.require_lang_item(LangItem::Pin, Some(body.span)); + let pin_did = tcx.require_lang_item(LangItem::Pin, body.span); let pin_adt_ref = tcx.adt_def(pin_did); let args = tcx.mk_args(&[ref_coroutine_ty.into()]); let pin_ref_coroutine_ty = Ty::new_adt(tcx, pin_adt_ref, args); @@ -557,7 +560,7 @@ fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> Ty // replace the type of the `resume` argument replace_resume_ty_local(tcx, body, CTX_ARG, context_mut_ref); - let get_context_def_id = tcx.require_lang_item(LangItem::GetContext, None); + let get_context_def_id = tcx.require_lang_item(LangItem::GetContext, body.span); for bb in body.basic_blocks.indices() { let bb_data = &body[bb]; @@ -618,7 +621,7 @@ fn replace_resume_ty_local<'tcx>( #[cfg(debug_assertions)] { if let ty::Adt(resume_ty_adt, _) = local_ty.kind() { - let expected_adt = tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, None)); + let expected_adt = tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, body.span)); assert_eq!(*resume_ty_adt, expected_adt); } else { panic!("expected `ResumeTy`, found `{:?}`", local_ty); @@ -1095,7 +1098,7 @@ fn insert_term_block<'tcx>(body: &mut Body<'tcx>, kind: TerminatorKind<'tcx>) -> fn return_poll_ready_assign<'tcx>(tcx: TyCtxt<'tcx>, source_info: SourceInfo) -> Statement<'tcx> { // Poll::Ready(()) - let poll_def_id = tcx.require_lang_item(LangItem::Poll, None); + let poll_def_id = tcx.require_lang_item(LangItem::Poll, source_info.span); let args = tcx.mk_args(&[tcx.types.unit.into()]); let val = Operand::Constant(Box::new(ConstOperand { span: source_info.span, @@ -1437,7 +1440,7 @@ fn check_field_tys_sized<'tcx>( ), param_env, field_ty.ty, - tcx.require_lang_item(hir::LangItem::Sized, Some(field_ty.source_info.span)), + tcx.require_lang_item(hir::LangItem::Sized, field_ty.source_info.span), ); } @@ -1473,14 +1476,14 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { let new_ret_ty = match coroutine_kind { CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => { // Compute Poll<return_ty> - let poll_did = tcx.require_lang_item(LangItem::Poll, None); + let poll_did = tcx.require_lang_item(LangItem::Poll, body.span); let poll_adt_ref = tcx.adt_def(poll_did); let poll_args = tcx.mk_args(&[old_ret_ty.into()]); Ty::new_adt(tcx, poll_adt_ref, poll_args) } CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => { // Compute Option<yield_ty> - let option_did = tcx.require_lang_item(LangItem::Option, None); + let option_did = tcx.require_lang_item(LangItem::Option, body.span); let option_adt_ref = tcx.adt_def(option_did); let option_args = tcx.mk_args(&[old_yield_ty.into()]); Ty::new_adt(tcx, option_adt_ref, option_args) @@ -1491,7 +1494,7 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { } CoroutineKind::Coroutine(_) => { // Compute CoroutineState<yield_ty, return_ty> - let state_did = tcx.require_lang_item(LangItem::CoroutineState, None); + let state_did = tcx.require_lang_item(LangItem::CoroutineState, body.span); let state_adt_ref = tcx.adt_def(state_did); let state_args = tcx.mk_args(&[old_yield_ty.into(), old_ret_ty.into()]); Ty::new_adt(tcx, state_adt_ref, state_args) diff --git a/compiler/rustc_mir_transform/src/coroutine/drop.rs b/compiler/rustc_mir_transform/src/coroutine/drop.rs index 6b266da5a69..6021e795d21 100644 --- a/compiler/rustc_mir_transform/src/coroutine/drop.rs +++ b/compiler/rustc_mir_transform/src/coroutine/drop.rs @@ -42,7 +42,7 @@ fn build_poll_call<'tcx>( context_ref_place: &Place<'tcx>, unwind: UnwindAction, ) -> BasicBlock { - let poll_fn = tcx.require_lang_item(LangItem::FuturePoll, None); + let poll_fn = tcx.require_lang_item(LangItem::FuturePoll, DUMMY_SP); let poll_fn = Ty::new_fn_def(tcx, poll_fn, [fut_ty]); let poll_fn = Operand::Constant(Box::new(ConstOperand { span: DUMMY_SP, @@ -77,11 +77,8 @@ fn build_pin_fut<'tcx>( let fut_ty = fut_place.ty(&body.local_decls, tcx).ty; let fut_ref_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, fut_ty); let fut_ref_place = Place::from(body.local_decls.push(LocalDecl::new(fut_ref_ty, span))); - let pin_fut_new_unchecked_fn = Ty::new_fn_def( - tcx, - tcx.require_lang_item(LangItem::PinNewUnchecked, Some(span)), - [fut_ref_ty], - ); + let pin_fut_new_unchecked_fn = + Ty::new_fn_def(tcx, tcx.require_lang_item(LangItem::PinNewUnchecked, span), [fut_ref_ty]); let fut_pin_ty = pin_fut_new_unchecked_fn.fn_sig(tcx).output().skip_binder(); let fut_pin_place = Place::from(body.local_decls.push(LocalDecl::new(fut_pin_ty, span))); let pin_fut_new_unchecked_fn = Operand::Constant(Box::new(ConstOperand { @@ -143,13 +140,15 @@ fn build_poll_switch<'tcx>( let Discr { val: poll_ready_discr, ty: poll_discr_ty } = poll_enum .discriminant_for_variant( tcx, - poll_enum_adt.variant_index_with_id(tcx.require_lang_item(LangItem::PollReady, None)), + poll_enum_adt + .variant_index_with_id(tcx.require_lang_item(LangItem::PollReady, DUMMY_SP)), ) .unwrap(); let poll_pending_discr = poll_enum .discriminant_for_variant( tcx, - poll_enum_adt.variant_index_with_id(tcx.require_lang_item(LangItem::PollPending, None)), + poll_enum_adt + .variant_index_with_id(tcx.require_lang_item(LangItem::PollPending, DUMMY_SP)), ) .unwrap() .val; @@ -316,16 +315,17 @@ pub(super) fn expand_async_drops<'tcx>( // pending => return rv (yield) // ready => *continue_bb|drop_bb* + let source_info = body[bb].terminator.as_ref().unwrap().source_info; + // Compute Poll<> (aka Poll with void return) - let poll_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Poll, None)); + let poll_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Poll, source_info.span)); let poll_enum = Ty::new_adt(tcx, poll_adt_ref, tcx.mk_args(&[tcx.types.unit.into()])); - let poll_decl = LocalDecl::new(poll_enum, body.span); + let poll_decl = LocalDecl::new(poll_enum, source_info.span); let poll_unit_place = Place::from(body.local_decls.push(poll_decl)); // First state-loop yield for mainline let context_ref_place = - Place::from(body.local_decls.push(LocalDecl::new(context_mut_ref, body.span))); - let source_info = body[bb].terminator.as_ref().unwrap().source_info; + Place::from(body.local_decls.push(LocalDecl::new(context_mut_ref, source_info.span))); let arg = Rvalue::Use(Operand::Move(Place::from(CTX_ARG))); body[bb].statements.push(Statement { source_info, @@ -353,8 +353,9 @@ pub(super) fn expand_async_drops<'tcx>( let mut dropline_context_ref: Option<Place<'_>> = None; let mut dropline_call_bb: Option<BasicBlock> = None; if !is_dropline_bb { - let context_ref_place2: Place<'_> = - Place::from(body.local_decls.push(LocalDecl::new(context_mut_ref, body.span))); + let context_ref_place2: Place<'_> = Place::from( + body.local_decls.push(LocalDecl::new(context_mut_ref, source_info.span)), + ); let drop_yield_block = insert_term_block(body, TerminatorKind::Unreachable); // `kind` replaced later to yield let drop_switch_block = build_poll_switch( tcx, @@ -382,12 +383,34 @@ pub(super) fn expand_async_drops<'tcx>( dropline_call_bb = Some(drop_call_bb); } - // value needed only for return-yields or gen-coroutines, so just const here - let value = Operand::Constant(Box::new(ConstOperand { - span: body.span, - user_ty: None, - const_: Const::from_bool(tcx, false), - })); + let value = + if matches!(coroutine_kind, CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) + { + // For AsyncGen we need `yield Poll<OptRet>::Pending` + let full_yield_ty = body.yield_ty().unwrap(); + let ty::Adt(_poll_adt, args) = *full_yield_ty.kind() else { bug!() }; + let ty::Adt(_option_adt, args) = *args.type_at(0).kind() else { bug!() }; + let yield_ty = args.type_at(0); + Operand::Constant(Box::new(ConstOperand { + span: source_info.span, + const_: Const::Unevaluated( + UnevaluatedConst::new( + tcx.require_lang_item(LangItem::AsyncGenPending, source_info.span), + tcx.mk_args(&[yield_ty.into()]), + ), + full_yield_ty, + ), + user_ty: None, + })) + } else { + // value needed only for return-yields or gen-coroutines, so just const here + Operand::Constant(Box::new(ConstOperand { + span: source_info.span, + user_ty: None, + const_: Const::from_bool(tcx, false), + })) + }; + use rustc_middle::mir::AssertKind::ResumedAfterDrop; let panic_bb = insert_panic_block(tcx, body, ResumedAfterDrop(coroutine_kind)); @@ -573,7 +596,7 @@ pub(super) fn create_coroutine_drop_shim<'tcx>( // Update the body's def to become the drop glue. let coroutine_instance = body.source.instance; - let drop_in_place = tcx.require_lang_item(LangItem::DropInPlace, None); + let drop_in_place = tcx.require_lang_item(LangItem::DropInPlace, body.span); let drop_instance = InstanceKind::DropGlue(drop_in_place, Some(coroutine_ty)); // Temporary change MirSource to coroutine's instance so that dump_mir produces more sensible @@ -644,7 +667,7 @@ pub(super) fn create_coroutine_drop_shim_async<'tcx>( } // Replace the return variable: Poll<RetT> to Poll<()> - let poll_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Poll, None)); + let poll_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Poll, body.span)); let poll_enum = Ty::new_adt(tcx, poll_adt_ref, tcx.mk_args(&[tcx.types.unit.into()])); body.local_decls[RETURN_PLACE] = LocalDecl::with_source_info(poll_enum, source_info); @@ -695,7 +718,7 @@ pub(super) fn create_coroutine_drop_shim_proxy_async<'tcx>( let source_info = SourceInfo::outermost(body.span); // Replace the return variable: Poll<RetT> to Poll<()> - let poll_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Poll, None)); + let poll_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Poll, body.span)); let poll_enum = Ty::new_adt(tcx, poll_adt_ref, tcx.mk_args(&[tcx.types.unit.into()])); body.local_decls[RETURN_PLACE] = LocalDecl::with_source_info(poll_enum, source_info); diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index ddeae093df5..ec76076020e 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -1,8 +1,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir; use rustc_middle::ty::TyCtxt; -use rustc_span::source_map::SourceMap; -use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span}; +use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span}; use tracing::instrument; use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph}; @@ -84,18 +83,8 @@ pub(super) fn extract_refined_covspans<'tcx>( // Discard any span that overlaps with a hole. discard_spans_overlapping_holes(&mut covspans, &holes); - // Discard spans that overlap in unwanted ways. + // Perform more refinement steps after holes have been dealt with. let mut covspans = remove_unwanted_overlapping_spans(covspans); - - // For all empty spans, either enlarge them to be non-empty, or discard them. - let source_map = tcx.sess.source_map(); - covspans.retain_mut(|covspan| { - let Some(span) = ensure_non_empty_span(source_map, covspan.span) else { return false }; - covspan.span = span; - true - }); - - // Merge covspans that can be merged. covspans.dedup_by(|b, a| a.merge_if_eligible(b)); code_mappings.extend(covspans.into_iter().map(|Covspan { span, bcb }| { @@ -241,26 +230,3 @@ fn compare_spans(a: Span, b: Span) -> std::cmp::Ordering { // - Both have the same start and span A extends further right .then_with(|| Ord::cmp(&a.hi(), &b.hi()).reverse()) } - -fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> { - if !span.is_empty() { - return Some(span); - } - - // The span is empty, so try to enlarge it to cover an adjacent '{' or '}'. - source_map - .span_to_source(span, |src, start, end| try { - // Adjusting span endpoints by `BytePos(1)` is normally a bug, - // but in this case we have specifically checked that the character - // we're skipping over is one of two specific ASCII characters, so - // adjusting by exactly 1 byte is correct. - if src.as_bytes().get(end).copied() == Some(b'{') { - Some(span.with_hi(span.hi() + BytePos(1))) - } else if start > 0 && src.as_bytes()[start - 1] == b'}' { - Some(span.with_lo(span.lo() - BytePos(1))) - } else { - None - } - }) - .ok()? -} diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 99b95e7312b..0cf8142a560 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -616,7 +616,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { place, operand, &mut |elem, op| match elem { - TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).discard_err(), + TrackElem::Field(idx) => self.ecx.project_field(op, idx).discard_err(), TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).discard_err(), TrackElem::Discriminant => { let variant = self.ecx.read_discriminant(op).discard_err()?; @@ -890,7 +890,8 @@ fn try_write_constant<'tcx>( ty::Tuple(elem_tys) => { for (i, elem) in elem_tys.iter().enumerate() { - let Some(field) = map.apply(place, TrackElem::Field(FieldIdx::from_usize(i))) else { + let i = FieldIdx::from_usize(i); + let Some(field) = map.apply(place, TrackElem::Field(i)) else { throw_machine_stop_str!("missing field in tuple") }; let field_dest = ecx.project_field(dest, i)?; @@ -928,7 +929,7 @@ fn try_write_constant<'tcx>( let Some(field) = map.apply(variant_place, TrackElem::Field(i)) else { throw_machine_stop_str!("missing field in ADT") }; - let field_dest = ecx.project_field(&variant_dest, i.as_usize())?; + let field_dest = ecx.project_field(&variant_dest, i)?; try_write_constant(ecx, &field_dest, field, ty, state, map)?; } ecx.write_discriminant(variant_idx, dest)?; diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index 73a58160a6a..3a5e2620b14 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -1,6 +1,7 @@ use std::{fmt, iter, mem}; use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; +use rustc_hir::def::DefKind; use rustc_hir::lang_items::LangItem; use rustc_index::Idx; use rustc_middle::mir::*; @@ -234,11 +235,8 @@ where let (fut_ty, drop_fn_def_id, trait_args) = if call_destructor_only { // Resolving obj.<AsyncDrop::drop>() - let trait_ref = ty::TraitRef::new( - tcx, - tcx.require_lang_item(LangItem::AsyncDrop, Some(span)), - [drop_ty], - ); + let trait_ref = + ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::AsyncDrop, span), [drop_ty]); let (drop_trait, trait_args) = match tcx.codegen_select_candidate( ty::TypingEnv::fully_monomorphized().as_query_input(trait_ref), ) { @@ -251,14 +249,47 @@ where span_bug!(span, "invalid `AsyncDrop` impl_source: {:?}", impl_source); } }; - let drop_fn_def_id = tcx.associated_item_def_ids(drop_trait)[0]; + // impl_item_refs may be empty if drop fn is not implemented in 'impl AsyncDrop for ...' + // (#140974). + // Such code will report error, so just generate sync drop here and return + let Some(drop_fn_def_id) = tcx + .associated_item_def_ids(drop_trait) + .first() + .and_then(|def_id| { + if tcx.def_kind(def_id) == DefKind::AssocFn + && tcx.check_args_compatible(*def_id, trait_args) + { + Some(def_id) + } else { + None + } + }) + .copied() + else { + tcx.dcx().span_delayed_bug( + self.elaborator.body().span, + "AsyncDrop type without correct `async fn drop(...)`.", + ); + self.elaborator.patch().patch_terminator( + pin_obj_bb, + TerminatorKind::Drop { + place, + target: succ, + unwind: unwind.into_action(), + replace: false, + drop: None, + async_fut: None, + }, + ); + return pin_obj_bb; + }; let drop_fn = Ty::new_fn_def(tcx, drop_fn_def_id, trait_args); let sig = drop_fn.fn_sig(tcx); let sig = tcx.instantiate_bound_regions_with_erased(sig); (sig.output(), drop_fn_def_id, trait_args) } else { // Resolving async_drop_in_place<T> function for drop_ty - let drop_fn_def_id = tcx.require_lang_item(LangItem::AsyncDropInPlace, Some(span)); + let drop_fn_def_id = tcx.require_lang_item(LangItem::AsyncDropInPlace, span); let trait_args = tcx.mk_args(&[drop_ty.into()]); let sig = tcx.fn_sig(drop_fn_def_id).instantiate(tcx, trait_args); let sig = tcx.instantiate_bound_regions_with_erased(sig); @@ -285,7 +316,7 @@ where // pin_obj_place preparation let pin_obj_new_unchecked_fn = Ty::new_fn_def( tcx, - tcx.require_lang_item(LangItem::PinNewUnchecked, Some(span)), + tcx.require_lang_item(LangItem::PinNewUnchecked, span), [GenericArg::from(obj_ref_ty)], ); let pin_obj_ty = pin_obj_new_unchecked_fn.fn_sig(tcx).output().no_bound_vars().unwrap(); @@ -318,15 +349,20 @@ where bug!(); }; let obj_ptr_ty = Ty::new_mut_ptr(tcx, drop_ty); - let obj_ptr_place = Place::from(self.new_temp(obj_ptr_ty)); let unwrap_ty = adt_def.non_enum_variant().fields[FieldIdx::ZERO].ty(tcx, adt_args); - let addr = Rvalue::RawPtr( - RawPtrKind::Mut, - pin_obj_place.project_deeper( - &[ProjectionElem::Field(FieldIdx::ZERO, unwrap_ty), ProjectionElem::Deref], - tcx, - ), - ); + let obj_ref_place = Place::from(self.new_temp(unwrap_ty)); + call_statements.push(self.assign( + obj_ref_place, + Rvalue::Use(Operand::Copy(tcx.mk_place_field( + pin_obj_place, + FieldIdx::ZERO, + unwrap_ty, + ))), + )); + + let obj_ptr_place = Place::from(self.new_temp(obj_ptr_ty)); + + let addr = Rvalue::RawPtr(RawPtrKind::Mut, tcx.mk_place_deref(obj_ref_place)); call_statements.push(self.assign(obj_ptr_place, addr)); obj_ptr_place }; @@ -898,7 +934,7 @@ where fn destructor_call_block_sync(&mut self, (succ, unwind): (BasicBlock, Unwind)) -> BasicBlock { debug!("destructor_call_block_sync({:?}, {:?})", self, succ); let tcx = self.tcx(); - let drop_trait = tcx.require_lang_item(LangItem::Drop, None); + let drop_trait = tcx.require_lang_item(LangItem::Drop, DUMMY_SP); let drop_fn = tcx.associated_item_def_ids(drop_trait)[0]; let ty = self.place_ty(self.place); @@ -1251,6 +1287,23 @@ where } ty::Slice(ety) => self.drop_loop_trio_for_slice(*ety), + ty::UnsafeBinder(_) => { + // Unsafe binders may elaborate drops if their inner type isn't copy. + // This is enforced in typeck, so this should never happen. + self.tcx().dcx().span_delayed_bug( + self.source_info.span, + "open drop for unsafe binder shouldn't be encountered", + ); + self.elaborator.patch().new_block(BasicBlockData { + statements: vec![], + terminator: Some(Terminator { + source_info: self.source_info, + kind: TerminatorKind::Unreachable, + }), + is_cleanup: self.unwind.is_cleanup(), + }) + } + _ => span_bug!(self.source_info.span, "open drop from non-ADT `{:?}`", ty), } } diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 5b03a4987ed..cffa0183fa7 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -158,33 +158,6 @@ pub(crate) struct MustNotSuspendReason { pub reason: String, } -pub(crate) struct UnnecessaryTransmute { - pub span: Span, - pub sugg: String, - pub help: Option<&'static str>, -} - -// Needed for def_path_str -impl<'a> LintDiagnostic<'a, ()> for UnnecessaryTransmute { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) { - diag.primary_message(fluent::mir_transform_unnecessary_transmute); - diag.span_suggestion( - self.span, - "replace this with", - self.sugg, - lint::Applicability::MachineApplicable, - ); - self.help.map(|help| diag.help(help)); - } -} - -#[derive(LintDiagnostic)] -#[diag(mir_transform_undefined_transmute)] -#[note] -#[note(mir_transform_note2)] -#[help] -pub(crate) struct UndefinedTransmute; - #[derive(Diagnostic)] #[diag(mir_transform_force_inline)] #[note] diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 209e818e9e3..92c30d239b5 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -438,8 +438,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { dest.clone() }; for (field_index, op) in fields.into_iter().enumerate() { - let field_dest = - self.ecx.project_field(&variant_dest, field_index).discard_err()?; + let field_dest = self + .ecx + .project_field(&variant_dest, FieldIdx::from_usize(field_index)) + .discard_err()?; self.ecx.copy_op(op, &field_dest).discard_err()?; } self.ecx @@ -638,6 +640,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { place: PlaceRef<'tcx>, value: VnIndex, proj: PlaceElem<'tcx>, + from_non_ssa_index: &mut bool, ) -> Option<VnIndex> { let proj = match proj { ProjectionElem::Deref => { @@ -682,6 +685,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } ProjectionElem::Index(idx) => { if let Value::Repeat(inner, _) = self.get(value) { + *from_non_ssa_index |= self.locals[idx].is_none(); return Some(*inner); } let idx = self.locals[idx]?; @@ -774,6 +778,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // Invariant: `value` holds the value up-to the `index`th projection excluded. let mut value = self.locals[place.local]?; + let mut from_non_ssa_index = false; for (index, proj) in place.projection.iter().enumerate() { if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value) && let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer) @@ -791,7 +796,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } let base = PlaceRef { local: place.local, projection: &place.projection[..index] }; - value = self.project(base, value, proj)?; + value = self.project(base, value, proj, &mut from_non_ssa_index)?; } if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value) @@ -804,6 +809,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } if let Some(new_local) = self.try_as_local(value, location) { place_ref = PlaceRef { local: new_local, projection: &[] }; + } else if from_non_ssa_index { + // If access to non-SSA locals is unavoidable, bail out. + return None; } if place_ref.local != place.local || place_ref.projection.len() < place.projection.len() { @@ -1577,7 +1585,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // We needed to check the variant to avoid trying to read the tag // field from an enum where no fields have variants, since that tag // field isn't in the `Aggregate` from which we're getting values. - Some((FieldIdx::from_usize(field_idx), field_layout.ty)) + Some((field_idx, field_layout.ty)) } else if let ty::Adt(adt, args) = ty.kind() && adt.is_struct() && adt.repr().transparent() diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 31b361ec1a9..48db536c122 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -388,7 +388,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { lhs, constant, &mut |elem, op| match elem { - TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).discard_err(), + TrackElem::Field(idx) => self.ecx.project_field(op, idx).discard_err(), TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).discard_err(), TrackElem::Discriminant => { let variant = self.ecx.read_discriminant(op).discard_err()?; diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 47cb478fe33..1a91d6bd7da 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -241,6 +241,7 @@ impl EnumSizeOpt { data, tcx.data_layout.ptr_sized_integer().align(&tcx.data_layout).abi, Mutability::Not, + (), ); let alloc = tcx.reserve_and_set_memory_alloc(tcx.mk_const_alloc(alloc)); Some((*adt_def, num_discrs, *alloc_cache.entry(ty).or_insert(alloc))) diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 10dbb3437dc..572ad585c8c 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -7,10 +7,7 @@ #![feature(file_buffered)] #![feature(if_let_guard)] #![feature(impl_trait_in_assoc_type)] -#![feature(map_try_insert)] -#![feature(never_type)] #![feature(try_blocks)] -#![feature(vec_deque_pop_if)] #![feature(yeet_expr)] // tidy-alphabetical-end @@ -123,8 +120,6 @@ declare_passes! { mod check_const_item_mutation : CheckConstItemMutation; mod check_null : CheckNull; mod check_packed_ref : CheckPackedRef; - mod check_undefined_transmutes : CheckUndefinedTransmutes; - mod check_unnecessary_transmutes: CheckUnnecessaryTransmutes; // This pass is public to allow external drivers to perform MIR cleanup pub mod cleanup_post_borrowck : CleanupPostBorrowck; @@ -390,8 +385,6 @@ fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> { &Lint(check_packed_ref::CheckPackedRef), &Lint(check_const_item_mutation::CheckConstItemMutation), &Lint(function_item_references::FunctionItemReferences), - &Lint(check_undefined_transmutes::CheckUndefinedTransmutes), - &Lint(check_unnecessary_transmutes::CheckUnnecessaryTransmutes), // What we need to do constant evaluation. &simplify::SimplifyCfg::Initial, &Lint(sanity_check::SanityCheck), diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 9c21bcfc0d2..52f4c39c09b 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -262,6 +262,52 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { }); terminator.kind = TerminatorKind::Goto { target }; } + sym::slice_get_unchecked => { + let target = target.unwrap(); + let Ok([ptrish, index]) = take_array(args) else { + span_bug!( + terminator.source_info.span, + "Wrong number of arguments for {intrinsic:?}", + ); + }; + + let place = ptrish.node.place().unwrap(); + assert!(!place.is_indirect()); + let updated_place = place.project_deeper( + &[ + ProjectionElem::Deref, + ProjectionElem::Index( + index.node.place().unwrap().as_local().unwrap(), + ), + ], + tcx, + ); + + let ret_ty = generic_args.type_at(0); + let rvalue = match *ret_ty.kind() { + ty::RawPtr(_, Mutability::Not) => { + Rvalue::RawPtr(RawPtrKind::Const, updated_place) + } + ty::RawPtr(_, Mutability::Mut) => { + Rvalue::RawPtr(RawPtrKind::Mut, updated_place) + } + ty::Ref(region, _, Mutability::Not) => { + Rvalue::Ref(region, BorrowKind::Shared, updated_place) + } + ty::Ref(region, _, Mutability::Mut) => Rvalue::Ref( + region, + BorrowKind::Mut { kind: MutBorrowKind::Default }, + updated_place, + ), + _ => bug!("Unknown return type {ret_ty:?}"), + }; + + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new((*destination, rvalue))), + }); + terminator.kind = TerminatorKind::Goto { target }; + } sym::transmute | sym::transmute_unchecked => { let dst_ty = destination.ty(local_decls, tcx).ty; let Ok([arg]) = take_array(args) else { diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 8c0c3096899..5e511f1a418 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -284,12 +284,14 @@ fn can_cast( let v = match src_layout.ty.kind() { ty::Uint(_) => from_scalar.to_uint(src_layout.size), ty::Int(_) => from_scalar.to_int(src_layout.size) as u128, - _ => unreachable!("invalid int"), + // We can also transform the values of other integer representations (such as char), + // although this may not be practical in real-world scenarios. + _ => return false, }; let size = match *cast_ty.kind() { ty::Int(t) => Integer::from_int_ty(&tcx, t).size(), ty::Uint(t) => Integer::from_uint_ty(&tcx, t).size(), - _ => unreachable!("invalid int"), + _ => return false, }; let v = size.truncate(v); let cast_scalar = ScalarInt::try_from_uint(v, size).unwrap(); diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 9688ac8ed2e..6d45bbc6e16 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -98,7 +98,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< build_call_shim(tcx, instance, None, CallKind::Direct(def_id)) } ty::InstanceKind::ClosureOnceShim { call_once: _, track_caller: _ } => { - let fn_mut = tcx.require_lang_item(LangItem::FnMut, None); + let fn_mut = tcx.require_lang_item(LangItem::FnMut, DUMMY_SP); let call_mut = tcx .associated_items(fn_mut) .in_definition_order() diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index 7976b65aae7..fd7b7362cd9 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -6,7 +6,7 @@ use rustc_middle::mir::{ BasicBlock, BasicBlockData, Body, Local, LocalDecl, MirSource, Operand, Place, Rvalue, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, }; -use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt}; +use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt, TypeVisitableExt}; use super::*; use crate::patch::MirPatch; @@ -64,7 +64,7 @@ pub(super) fn build_async_drop_shim<'tcx>( let needs_async_drop = drop_ty.needs_async_drop(tcx, typing_env); let needs_sync_drop = !needs_async_drop && drop_ty.needs_drop(tcx, typing_env); - let resume_adt = tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, None)); + let resume_adt = tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, DUMMY_SP)); let resume_ty = Ty::new_adt(tcx, resume_adt, ty::List::empty()); let fn_sig = ty::Binder::dummy(tcx.mk_fn_sig( @@ -121,9 +121,10 @@ pub(super) fn build_async_drop_shim<'tcx>( parent_args.as_coroutine().resume_ty(), ))); body.phase = MirPhase::Runtime(RuntimePhase::Initial); - if !needs_async_drop { + if !needs_async_drop || drop_ty.references_error() { // Returning noop body for types without `need async drop` - // (or sync Drop in case of !`need async drop` && `need drop`) + // (or sync Drop in case of !`need async drop` && `need drop`). + // And also for error types. return body; } @@ -219,7 +220,7 @@ fn build_adrop_for_coroutine_shim<'tcx>( body.source.instance = instance; body.phase = MirPhase::Runtime(RuntimePhase::Initial); body.var_debug_info.clear(); - let pin_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, Some(span))); + let pin_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, span)); let args = tcx.mk_args(&[proxy_ref.into()]); let pin_proxy_ref = Ty::new_adt(tcx, pin_adt_ref, args); @@ -307,10 +308,10 @@ fn build_adrop_for_adrop_shim<'tcx>( let cor_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, impl_ty); // ret_ty = `Poll<()>` - let poll_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Poll, None)); + let poll_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Poll, span)); let ret_ty = Ty::new_adt(tcx, poll_adt_ref, tcx.mk_args(&[tcx.types.unit.into()])); // env_ty = `Pin<&mut proxy_ty>` - let pin_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, None)); + let pin_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, span)); let env_ty = Ty::new_adt(tcx, pin_adt_ref, tcx.mk_args(&[proxy_ref.into()])); // sig = `fn (Pin<&mut proxy_ty>, &mut Context) -> Poll<()>` let sig = tcx.mk_fn_sig( @@ -375,7 +376,7 @@ fn build_adrop_for_adrop_shim<'tcx>( let cor_pin_ty = Ty::new_adt(tcx, pin_adt_ref, tcx.mk_args(&[cor_ref.into()])); let cor_pin_place = Place::from(locals.push(LocalDecl::new(cor_pin_ty, span))); - let pin_fn = tcx.require_lang_item(LangItem::PinNewUnchecked, Some(span)); + let pin_fn = tcx.require_lang_item(LangItem::PinNewUnchecked, span); // call Pin<FutTy>::new_unchecked(&mut impl_cor) blocks.push(BasicBlockData { statements, @@ -395,7 +396,7 @@ fn build_adrop_for_adrop_shim<'tcx>( }); // When dropping async drop coroutine, we continue its execution: // we call impl::poll (impl_layout, ctx) - let poll_fn = tcx.require_lang_item(LangItem::FuturePoll, None); + let poll_fn = tcx.require_lang_item(LangItem::FuturePoll, span); let resume_ctx = Place::from(Local::new(2)); blocks.push(BasicBlockData { statements: vec![], diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index c8aa7588d03..fd91508cc11 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1253,7 +1253,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { self.tcx, self.tcx.require_lang_item( LangItem::CoerceUnsized, - Some(self.body.source_info(location).span), + self.body.source_info(location).span, ), [op_ty, *target_type], )) { |
