diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index c4834c8040871..fd6fa67c7c3f6 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -12,13 +12,18 @@ pub trait Sized {} #[lang = "unsize"] pub trait Unsize {} -#[lang = "coerce_unsized"] -pub trait CoerceUnsized {} +#[lang = "unsafe_coerce_unsized"] +pub trait UnsafeCoerceUnsized {} -impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} -impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} -impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} -impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} +#[lang = "coerce_unsized"] +pub unsafe trait CoerceUnsized: UnsafeCoerceUnsized {} + +impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> UnsafeCoerceUnsized<&'a U> for &'b T {} +unsafe impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} +impl<'a, T: ?Sized + Unsize, U: ?Sized> UnsafeCoerceUnsized<&'a mut U> for &'a mut T {} +unsafe impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} +impl, U: ?Sized> UnsafeCoerceUnsized<*const U> for *const T {} +impl, U: ?Sized> UnsafeCoerceUnsized<*mut U> for *mut T {} #[lang = "dispatch_from_dyn"] pub trait DispatchFromDyn {} diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 55000ae7e59d4..d2022b5e35427 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -165,108 +165,109 @@ where } language_item_table! { -// Variant name, Name, Method name, Target; - Bool, sym::bool, bool_impl, Target::Impl; - Char, sym::char, char_impl, Target::Impl; - Str, sym::str, str_impl, Target::Impl; - Array, sym::array, array_impl, Target::Impl; - Slice, sym::slice, slice_impl, Target::Impl; - SliceU8, sym::slice_u8, slice_u8_impl, Target::Impl; - StrAlloc, sym::str_alloc, str_alloc_impl, Target::Impl; - SliceAlloc, sym::slice_alloc, slice_alloc_impl, Target::Impl; - SliceU8Alloc, sym::slice_u8_alloc, slice_u8_alloc_impl, Target::Impl; - ConstPtr, sym::const_ptr, const_ptr_impl, Target::Impl; - MutPtr, sym::mut_ptr, mut_ptr_impl, Target::Impl; - ConstSlicePtr, sym::const_slice_ptr, const_slice_ptr_impl, Target::Impl; - MutSlicePtr, sym::mut_slice_ptr, mut_slice_ptr_impl, Target::Impl; - I8, sym::i8, i8_impl, Target::Impl; - I16, sym::i16, i16_impl, Target::Impl; - I32, sym::i32, i32_impl, Target::Impl; - I64, sym::i64, i64_impl, Target::Impl; - I128, sym::i128, i128_impl, Target::Impl; - Isize, sym::isize, isize_impl, Target::Impl; - U8, sym::u8, u8_impl, Target::Impl; - U16, sym::u16, u16_impl, Target::Impl; - U32, sym::u32, u32_impl, Target::Impl; - U64, sym::u64, u64_impl, Target::Impl; - U128, sym::u128, u128_impl, Target::Impl; - Usize, sym::usize, usize_impl, Target::Impl; - F32, sym::f32, f32_impl, Target::Impl; - F64, sym::f64, f64_impl, Target::Impl; - F32Runtime, sym::f32_runtime, f32_runtime_impl, Target::Impl; - F64Runtime, sym::f64_runtime, f64_runtime_impl, Target::Impl; - - Sized, sym::sized, sized_trait, Target::Trait; - Unsize, sym::unsize, unsize_trait, Target::Trait; +// Variant name, Name, Method name, Target; + Bool, sym::bool, bool_impl, Target::Impl; + Char, sym::char, char_impl, Target::Impl; + Str, sym::str, str_impl, Target::Impl; + Array, sym::array, array_impl, Target::Impl; + Slice, sym::slice, slice_impl, Target::Impl; + SliceU8, sym::slice_u8, slice_u8_impl, Target::Impl; + StrAlloc, sym::str_alloc, str_alloc_impl, Target::Impl; + SliceAlloc, sym::slice_alloc, slice_alloc_impl, Target::Impl; + SliceU8Alloc, sym::slice_u8_alloc, slice_u8_alloc_impl, Target::Impl; + ConstPtr, sym::const_ptr, const_ptr_impl, Target::Impl; + MutPtr, sym::mut_ptr, mut_ptr_impl, Target::Impl; + ConstSlicePtr, sym::const_slice_ptr, const_slice_ptr_impl, Target::Impl; + MutSlicePtr, sym::mut_slice_ptr, mut_slice_ptr_impl, Target::Impl; + I8, sym::i8, i8_impl, Target::Impl; + I16, sym::i16, i16_impl, Target::Impl; + I32, sym::i32, i32_impl, Target::Impl; + I64, sym::i64, i64_impl, Target::Impl; + I128, sym::i128, i128_impl, Target::Impl; + Isize, sym::isize, isize_impl, Target::Impl; + U8, sym::u8, u8_impl, Target::Impl; + U16, sym::u16, u16_impl, Target::Impl; + U32, sym::u32, u32_impl, Target::Impl; + U64, sym::u64, u64_impl, Target::Impl; + U128, sym::u128, u128_impl, Target::Impl; + Usize, sym::usize, usize_impl, Target::Impl; + F32, sym::f32, f32_impl, Target::Impl; + F64, sym::f64, f64_impl, Target::Impl; + F32Runtime, sym::f32_runtime, f32_runtime_impl, Target::Impl; + F64Runtime, sym::f64_runtime, f64_runtime_impl, Target::Impl; + + Sized, sym::sized, sized_trait, Target::Trait; + Unsize, sym::unsize, unsize_trait, Target::Trait; /// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ"). - StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait; + StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait; /// Trait injected by `#[derive(Eq)]`, (i.e. "Total EQ"; no, I will not apologize). - StructuralTeq, sym::structural_teq, structural_teq_trait, Target::Trait; - Copy, sym::copy, copy_trait, Target::Trait; - Clone, sym::clone, clone_trait, Target::Trait; - Sync, sym::sync, sync_trait, Target::Trait; - DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait; + StructuralTeq, sym::structural_teq, structural_teq_trait, Target::Trait; + Copy, sym::copy, copy_trait, Target::Trait; + Clone, sym::clone, clone_trait, Target::Trait; + Sync, sym::sync, sync_trait, Target::Trait; + DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait; /// The associated item of the [`DiscriminantKind`] trait. - Discriminant, sym::discriminant_type, discriminant_type, Target::AssocTy; - - PointeeTrait, sym::pointee_trait, pointee_trait, Target::Trait; - Metadata, sym::metadata_type, metadata_type, Target::AssocTy; - DynMetadata, sym::dyn_metadata, dyn_metadata, Target::Struct; - - Freeze, sym::freeze, freeze_trait, Target::Trait; - - Drop, sym::drop, drop_trait, Target::Trait; - - CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, Target::Trait; - DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait; - - Add(Op), sym::add, add_trait, Target::Trait; - Sub(Op), sym::sub, sub_trait, Target::Trait; - Mul(Op), sym::mul, mul_trait, Target::Trait; - Div(Op), sym::div, div_trait, Target::Trait; - Rem(Op), sym::rem, rem_trait, Target::Trait; - Neg(Op), sym::neg, neg_trait, Target::Trait; - Not(Op), sym::not, not_trait, Target::Trait; - BitXor(Op), sym::bitxor, bitxor_trait, Target::Trait; - BitAnd(Op), sym::bitand, bitand_trait, Target::Trait; - BitOr(Op), sym::bitor, bitor_trait, Target::Trait; - Shl(Op), sym::shl, shl_trait, Target::Trait; - Shr(Op), sym::shr, shr_trait, Target::Trait; - AddAssign(Op), sym::add_assign, add_assign_trait, Target::Trait; - SubAssign(Op), sym::sub_assign, sub_assign_trait, Target::Trait; - MulAssign(Op), sym::mul_assign, mul_assign_trait, Target::Trait; - DivAssign(Op), sym::div_assign, div_assign_trait, Target::Trait; - RemAssign(Op), sym::rem_assign, rem_assign_trait, Target::Trait; - BitXorAssign(Op), sym::bitxor_assign, bitxor_assign_trait, Target::Trait; - BitAndAssign(Op), sym::bitand_assign, bitand_assign_trait, Target::Trait; - BitOrAssign(Op), sym::bitor_assign, bitor_assign_trait, Target::Trait; - ShlAssign(Op), sym::shl_assign, shl_assign_trait, Target::Trait; - ShrAssign(Op), sym::shr_assign, shr_assign_trait, Target::Trait; - Index(Op), sym::index, index_trait, Target::Trait; - IndexMut(Op), sym::index_mut, index_mut_trait, Target::Trait; - - UnsafeCell, sym::unsafe_cell, unsafe_cell_type, Target::Struct; - VaList, sym::va_list, va_list, Target::Struct; - - Deref, sym::deref, deref_trait, Target::Trait; - DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait; - DerefTarget, sym::deref_target, deref_target, Target::AssocTy; - Receiver, sym::receiver, receiver_trait, Target::Trait; - - Fn, kw::Fn, fn_trait, Target::Trait; - FnMut, sym::fn_mut, fn_mut_trait, Target::Trait; - FnOnce, sym::fn_once, fn_once_trait, Target::Trait; - - FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy; - - Future, sym::future_trait, future_trait, Target::Trait; - GeneratorState, sym::generator_state, gen_state, Target::Enum; - Generator, sym::generator, gen_trait, Target::Trait; - Unpin, sym::unpin, unpin_trait, Target::Trait; - Pin, sym::pin, pin_type, Target::Struct; - - PartialEq, sym::eq, eq_trait, Target::Trait; - PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait; + Discriminant, sym::discriminant_type, discriminant_type, Target::AssocTy; + + PointeeTrait, sym::pointee_trait, pointee_trait, Target::Trait; + Metadata, sym::metadata_type, metadata_type, Target::AssocTy; + DynMetadata, sym::dyn_metadata, dyn_metadata, Target::Struct; + + Freeze, sym::freeze, freeze_trait, Target::Trait; + + Drop, sym::drop, drop_trait, Target::Trait; + + UnsafeCoerceUnsized, sym::unsafe_coerce_unsized, unsafe_coerce_unsized_trait, Target::Trait; + CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, Target::Trait; + DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait; + + Add(Op), sym::add, add_trait, Target::Trait; + Sub(Op), sym::sub, sub_trait, Target::Trait; + Mul(Op), sym::mul, mul_trait, Target::Trait; + Div(Op), sym::div, div_trait, Target::Trait; + Rem(Op), sym::rem, rem_trait, Target::Trait; + Neg(Op), sym::neg, neg_trait, Target::Trait; + Not(Op), sym::not, not_trait, Target::Trait; + BitXor(Op), sym::bitxor, bitxor_trait, Target::Trait; + BitAnd(Op), sym::bitand, bitand_trait, Target::Trait; + BitOr(Op), sym::bitor, bitor_trait, Target::Trait; + Shl(Op), sym::shl, shl_trait, Target::Trait; + Shr(Op), sym::shr, shr_trait, Target::Trait; + AddAssign(Op), sym::add_assign, add_assign_trait, Target::Trait; + SubAssign(Op), sym::sub_assign, sub_assign_trait, Target::Trait; + MulAssign(Op), sym::mul_assign, mul_assign_trait, Target::Trait; + DivAssign(Op), sym::div_assign, div_assign_trait, Target::Trait; + RemAssign(Op), sym::rem_assign, rem_assign_trait, Target::Trait; + BitXorAssign(Op), sym::bitxor_assign, bitxor_assign_trait, Target::Trait; + BitAndAssign(Op), sym::bitand_assign, bitand_assign_trait, Target::Trait; + BitOrAssign(Op), sym::bitor_assign, bitor_assign_trait, Target::Trait; + ShlAssign(Op), sym::shl_assign, shl_assign_trait, Target::Trait; + ShrAssign(Op), sym::shr_assign, shr_assign_trait, Target::Trait; + Index(Op), sym::index, index_trait, Target::Trait; + IndexMut(Op), sym::index_mut, index_mut_trait, Target::Trait; + + UnsafeCell, sym::unsafe_cell, unsafe_cell_type, Target::Struct; + VaList, sym::va_list, va_list, Target::Struct; + + Deref, sym::deref, deref_trait, Target::Trait; + DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait; + DerefTarget, sym::deref_target, deref_target, Target::AssocTy; + Receiver, sym::receiver, receiver_trait, Target::Trait; + + Fn, kw::Fn, fn_trait, Target::Trait; + FnMut, sym::fn_mut, fn_mut_trait, Target::Trait; + FnOnce, sym::fn_once, fn_once_trait, Target::Trait; + + FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy; + + Future, sym::future_trait, future_trait, Target::Trait; + GeneratorState, sym::generator_state, gen_state, Target::Enum; + Generator, sym::generator, gen_trait, Target::Trait; + Unpin, sym::unpin, unpin_trait, Target::Trait; + Pin, sym::pin, pin_type, Target::Struct; + + PartialEq, sym::eq, eq_trait, Target::Trait; + PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait; // A number of panic-related lang items. The `panic` item corresponds to divide-by-zero and // various panic cases with `match`. The `panic_bounds_check` item is for indexing arrays. @@ -275,80 +276,80 @@ language_item_table! { // in the sense that a crate is not required to have it defined to use it, but a final product // is required to define it somewhere. Additionally, there are restrictions on crates that use // a weak lang item, but do not have it defined. - Panic, sym::panic, panic_fn, Target::Fn; - PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn; - PanicStr, sym::panic_str, panic_str, Target::Fn; - ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn; - PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn; - PanicInfo, sym::panic_info, panic_info, Target::Struct; - PanicLocation, sym::panic_location, panic_location, Target::Struct; - PanicImpl, sym::panic_impl, panic_impl, Target::Fn; + Panic, sym::panic, panic_fn, Target::Fn; + PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn; + PanicStr, sym::panic_str, panic_str, Target::Fn; + ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn; + PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn; + PanicInfo, sym::panic_info, panic_info, Target::Struct; + PanicLocation, sym::panic_location, panic_location, Target::Struct; + PanicImpl, sym::panic_impl, panic_impl, Target::Fn; /// libstd panic entry point. Necessary for const eval to be able to catch it - BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn; - BeginPanicFmt, sym::begin_panic_fmt, begin_panic_fmt, Target::Fn; + BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn; + BeginPanicFmt, sym::begin_panic_fmt, begin_panic_fmt, Target::Fn; - ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn; - BoxFree, sym::box_free, box_free_fn, Target::Fn; - DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn; - Oom, sym::oom, oom, Target::Fn; - AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct; + ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn; + BoxFree, sym::box_free, box_free_fn, Target::Fn; + DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn; + Oom, sym::oom, oom, Target::Fn; + AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct; - Start, sym::start, start_fn, Target::Fn; + Start, sym::start, start_fn, Target::Fn; - EhPersonality, sym::eh_personality, eh_personality, Target::Fn; - EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static; + EhPersonality, sym::eh_personality, eh_personality, Target::Fn; + EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static; - OwnedBox, sym::owned_box, owned_box, Target::Struct; + OwnedBox, sym::owned_box, owned_box, Target::Struct; - PhantomData, sym::phantom_data, phantom_data, Target::Struct; + PhantomData, sym::phantom_data, phantom_data, Target::Struct; - ManuallyDrop, sym::manually_drop, manually_drop, Target::Struct; + ManuallyDrop, sym::manually_drop, manually_drop, Target::Struct; - MaybeUninit, sym::maybe_uninit, maybe_uninit, Target::Union; + MaybeUninit, sym::maybe_uninit, maybe_uninit, Target::Union; /// Align offset for stride != 1; must not panic. - AlignOffset, sym::align_offset, align_offset_fn, Target::Fn; + AlignOffset, sym::align_offset, align_offset_fn, Target::Fn; - Termination, sym::termination, termination, Target::Trait; + Termination, sym::termination, termination, Target::Trait; - Try, sym::Try, try_trait, Target::Trait; + Try, sym::Try, try_trait, Target::Trait; - SliceLen, sym::slice_len_fn, slice_len_fn, Target::Method(MethodKind::Inherent); + SliceLen, sym::slice_len_fn, slice_len_fn, Target::Method(MethodKind::Inherent); // Language items from AST lowering - TryTraitFromResidual, sym::from_residual, from_residual_fn, Target::Method(MethodKind::Trait { body: false }); - TryTraitFromOutput, sym::from_output, from_output_fn, Target::Method(MethodKind::Trait { body: false }); - TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }); + TryTraitFromResidual, sym::from_residual, from_residual_fn, Target::Method(MethodKind::Trait { body: false }); + TryTraitFromOutput, sym::from_output, from_output_fn, Target::Method(MethodKind::Trait { body: false }); + TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }); - PollReady, sym::Ready, poll_ready_variant, Target::Variant; - PollPending, sym::Pending, poll_pending_variant, Target::Variant; + PollReady, sym::Ready, poll_ready_variant, Target::Variant; + PollPending, sym::Pending, poll_pending_variant, Target::Variant; - FromGenerator, sym::from_generator, from_generator_fn, Target::Fn; - GetContext, sym::get_context, get_context_fn, Target::Fn; + FromGenerator, sym::from_generator, from_generator_fn, Target::Fn; + GetContext, sym::get_context, get_context_fn, Target::Fn; - FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }); + FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }); - FromFrom, sym::from, from_fn, Target::Method(MethodKind::Trait { body: false }); + FromFrom, sym::from, from_fn, Target::Method(MethodKind::Trait { body: false }); - OptionSome, sym::Some, option_some_variant, Target::Variant; - OptionNone, sym::None, option_none_variant, Target::Variant; + OptionSome, sym::Some, option_some_variant, Target::Variant; + OptionNone, sym::None, option_none_variant, Target::Variant; - ResultOk, sym::Ok, result_ok_variant, Target::Variant; - ResultErr, sym::Err, result_err_variant, Target::Variant; + ResultOk, sym::Ok, result_ok_variant, Target::Variant; + ResultErr, sym::Err, result_err_variant, Target::Variant; - ControlFlowContinue, sym::Continue, cf_continue_variant, Target::Variant; - ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant; + ControlFlowContinue, sym::Continue, cf_continue_variant, Target::Variant; + ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant; - IntoIterIntoIter, sym::into_iter, into_iter_fn, Target::Method(MethodKind::Trait { body: false }); - IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false}); + IntoIterIntoIter, sym::into_iter, into_iter_fn, Target::Method(MethodKind::Trait { body: false }); + IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false}); - PinNewUnchecked, sym::new_unchecked, new_unchecked_fn, Target::Method(MethodKind::Inherent); + PinNewUnchecked, sym::new_unchecked, new_unchecked_fn, Target::Method(MethodKind::Inherent); - RangeFrom, sym::RangeFrom, range_from_struct, Target::Struct; - RangeFull, sym::RangeFull, range_full_struct, Target::Struct; - RangeInclusiveStruct, sym::RangeInclusive, range_inclusive_struct, Target::Struct; - RangeInclusiveNew, sym::range_inclusive_new, range_inclusive_new_method, Target::Method(MethodKind::Inherent); - Range, sym::Range, range_struct, Target::Struct; - RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct; - RangeTo, sym::RangeTo, range_to_struct, Target::Struct; + RangeFrom, sym::RangeFrom, range_from_struct, Target::Struct; + RangeFull, sym::RangeFull, range_full_struct, Target::Struct; + RangeInclusiveStruct, sym::RangeInclusive, range_inclusive_struct, Target::Struct; + RangeInclusiveNew, sym::range_inclusive_new, range_inclusive_new_method, Target::Method(MethodKind::Inherent); + Range, sym::Range, range_struct, Target::Struct; + RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct; + RangeTo, sym::RangeTo, range_to_struct, Target::Struct; } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index d9bbb03129975..677032b2112c0 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1437,10 +1437,10 @@ impl EncodeContext<'a, 'tcx> { None }; - // if this is an impl of `CoerceUnsized`, create its + // if this is an impl of `UnsafeCoerceUnsized`, create its // "unsized info", else just store None let coerce_unsized_info = trait_ref.and_then(|t| { - if Some(t.def_id) == self.tcx.lang_items().coerce_unsized_trait() { + if Some(t.def_id) == self.tcx.lang_items().unsafe_coerce_unsized_trait() { Some(self.tcx.at(item.span).coerce_unsized_info(def_id)) } else { None diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 4fb737f463a86..93caef4986d11 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -41,6 +41,7 @@ pub enum UnsafetyViolationDetails { MutationOfLayoutConstrainedField, BorrowOfLayoutConstrainedField, CallToFunctionWith, + UnsafeCoerceUnsized, } impl UnsafetyViolationDetails { @@ -102,6 +103,11 @@ impl UnsafetyViolationDetails { "call to function with `#[target_feature]`", "can only be called if the required target features are available", ), + UnsafeCoerceUnsized => ( + "performing unsizing coercion", + "unsizing coercion performed on a type that did not implement `CoerceUnsized` \ + will cause undefined behavior if data is invalid", + ), } } } diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index 35bb6ef6c2d6e..5859d57496252 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -2109,8 +2109,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { CastKind::Pointer(PointerCast::Unsize) => { let &ty = ty; let trait_ref = ty::TraitRef { - def_id: tcx - .require_lang_item(LangItem::CoerceUnsized, Some(self.last_span)), + def_id: tcx.require_lang_item( + LangItem::UnsafeCoerceUnsized, + Some(self.last_span), + ), substs: tcx.mk_substs_trait(op.ty(body, tcx), &[ty.into()]), }; diff --git a/compiler/rustc_mir/src/monomorphize/mod.rs b/compiler/rustc_mir/src/monomorphize/mod.rs index 57d2723cf9cfd..77822ec590d49 100644 --- a/compiler/rustc_mir/src/monomorphize/mod.rs +++ b/compiler/rustc_mir/src/monomorphize/mod.rs @@ -14,7 +14,7 @@ fn custom_coerce_unsize_info<'tcx>( source_ty: Ty<'tcx>, target_ty: Ty<'tcx>, ) -> CustomCoerceUnsized { - let def_id = tcx.require_lang_item(LangItem::CoerceUnsized, None); + let def_id = tcx.require_lang_item(LangItem::UnsafeCoerceUnsized, None); let trait_ref = ty::Binder::dummy(ty::TraitRef { def_id, diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir/src/transform/check_unsafety.rs index 1ff9bd1572108..75500c0952ee9 100644 --- a/compiler/rustc_mir/src/transform/check_unsafety.rs +++ b/compiler/rustc_mir/src/transform/check_unsafety.rs @@ -4,13 +4,17 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::hir_id::HirId; use rustc_hir::intravisit; +use rustc_hir::LangItem; use rustc_hir::Node; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::Level; +use rustc_trait_selection::traits::{SelectionContext, SelectionError}; use std::ops::Bound; @@ -132,6 +136,42 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.register_violations(&violations, &unsafe_blocks); } }, + Rvalue::Cast(kind, source, target_ty) => { + if let CastKind::Pointer(ty::adjustment::PointerCast::Unsize) = kind { + let tcx = self.tcx; + let source_ty = source.ty(self.body, tcx); + let def_id = tcx.require_lang_item(LangItem::CoerceUnsized, None); + let trait_ref = ty::Binder::dummy(ty::TraitRef { + def_id, + substs: tcx.mk_substs_trait(source_ty, &[(*target_ty).into()]), + }); + + let trait_ref = tcx.erase_regions(trait_ref); + let param_env = self.param_env; + tcx.infer_ctxt().enter(|infcx| { + let mut selcx = SelectionContext::new(&infcx); + + let obligation_cause = ObligationCause::dummy(); + let obligation = Obligation::new( + obligation_cause, + param_env, + trait_ref.to_poly_trait_predicate(), + ); + match selcx.select(&obligation) { + Ok(None) | Err(SelectionError::Unimplemented) => { + self.require_unsafe( + UnsafetyViolationKind::General, + UnsafetyViolationDetails::UnsafeCoerceUnsized, + ); + } + Ok(Some(_)) => {} + Err(e) => { + bug!("Encountered error `{:?}` selecting `{:?}` during unsafety checking", e, trait_ref); + } + } + }); + } + } _ => {} } self.super_rvalue(rvalue, location); diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 3a88d1932a80a..132be51da4c92 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -225,6 +225,7 @@ impl LanguageItemCollector<'tcx> { // Miscellaneous | LangItem::Unsize + | LangItem::UnsafeCoerceUnsized | LangItem::CoerceUnsized | LangItem::DispatchFromDyn | LangItem::Fn diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index f788eb7d2126e..d3aca0b6791e6 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1361,6 +1361,7 @@ symbols! { unrestricted_attribute_tokens, unsafe_block_in_unsafe_fn, unsafe_cell, + unsafe_coerce_unsized, unsafe_no_drop_flag, unsize, unsized_fn_params, diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 8c97e606c569f..18ff5fb53890a 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -139,7 +139,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t Some(chalk_solve::rust_ir::WellKnownTrait::Unsize) } else if lang_items.unpin_trait() == Some(def_id) { Some(chalk_solve::rust_ir::WellKnownTrait::Unpin) - } else if lang_items.coerce_unsized_trait() == Some(def_id) { + } else if lang_items.unsafe_coerce_unsized_trait() == Some(def_id) { + // FIXME: Rename to UnsafeCoerceUnsized Some(chalk_solve::rust_ir::WellKnownTrait::CoerceUnsized) } else { None @@ -566,7 +567,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t FnOnce => lang_items.fn_once_trait(), Unsize => lang_items.unsize_trait(), Unpin => lang_items.unpin_trait(), - CoerceUnsized => lang_items.coerce_unsized_trait(), + // FIXME: Should actually be UnsafeCoerceUnsized here. + CoerceUnsized => lang_items.unsafe_coerce_unsized_trait(), DiscriminantKind => lang_items.discriminant_kind_trait(), }; def_id.map(chalk_ir::TraitId) diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 0b4df8e6d3cdd..55d38aae9a872 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -507,20 +507,20 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { debug!("coerce_unsized: resolved source={:?} target={:?}", source, target); // These 'if' statements require some explanation. - // The `CoerceUnsized` trait is special - it is only - // possible to write `impl CoerceUnsized for A` where + // The `UnsafeCoerceUnsized` trait is special - it is only + // possible to write `impl UnsafeCoerceUnsized for A` where // A and B have 'matching' fields. This rules out the following // two types of blanket impls: // - // `impl CoerceUnsized for SomeType` - // `impl CoerceUnsized for T` + // `impl UnsafeCoerceUnsized for SomeType` + // `impl UnsafeCoerceUnsized for T` // - // Both of these trigger a special `CoerceUnsized`-related error (E0376) + // Both of these trigger a special `UnsafeCoerceUnsized`-related error (E0376) // // We can take advantage of this fact to avoid performing unnecessary work. // If either `source` or `target` is a type variable, then any applicable impl - // would need to be generic over the self-type (`impl CoerceUnsized for T`) - // or generic over the `CoerceUnsized` type parameter (`impl CoerceUnsized for + // would need to be generic over the self-type (`impl UnsafeCoerceUnsized for T`) + // or generic over the `UnsafeCoerceUnsized` type parameter (`impl UnsafeCoerceUnsized for // SomeType`). // // However, these are exactly the kinds of impls which are forbidden by @@ -536,12 +536,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { return Err(TypeError::Mismatch); } - let traits = - (self.tcx.lang_items().unsize_trait(), self.tcx.lang_items().coerce_unsized_trait()); - let (unsize_did, coerce_unsized_did) = if let (Some(u), Some(cu)) = traits { + let traits = ( + self.tcx.lang_items().unsize_trait(), + self.tcx.lang_items().unsafe_coerce_unsized_trait(), + ); + let (unsize_did, unsafe_coerce_unsized_did) = if let (Some(u), Some(cu)) = traits { (u, cu) } else { - debug!("missing Unsize or CoerceUnsized traits"); + debug!("missing Unsize or UnsafeCoerceUnsized traits"); return Err(TypeError::Mismatch); }; @@ -550,7 +552,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // we can't unify [T] with U. But to properly support DST, we need to allow // that, at which point we will need extra checks on the target here. - // Handle reborrows before selecting `Source: CoerceUnsized`. + // Handle reborrows before selecting `Source: UnsafeCoerceUnsized`. let reborrow = match (source.kind(), target.kind()) { (&ty::Ref(_, ty_a, mutbl_a), &ty::Ref(_, _, mutbl_b)) => { coerce_mutbls(mutbl_a, mutbl_b)?; @@ -592,7 +594,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let coerce_source = reborrow.as_ref().map_or(source, |&(_, ref r)| r.target); // Setup either a subtyping or a LUB relationship between - // the `CoerceUnsized` target type and the expected type. + // the `UnsafeCoerceUnsized` target type and the expected type. // We only have the latter, so we use an inference variable // for the former and let type inference do the rest. let origin = TypeVariableOrigin { @@ -610,7 +612,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let mut selcx = traits::SelectionContext::new(self); - // Create an obligation for `Source: CoerceUnsized`. + // Create an obligation for `Source: UnsafeCoerceUnsized`. let cause = ObligationCause::new( self.cause.span, self.body_id, @@ -628,7 +630,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.tcx, self.fcx.param_env, cause, - coerce_unsized_did, + unsafe_coerce_unsized_did, 0, coerce_source, &[coerce_target.into()] @@ -637,10 +639,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let mut has_unsized_tuple_coercion = false; let mut has_trait_upcasting_coercion = false; - // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid + // Keep resolving `UnsafeCoerceUnsized` and `Unsize` predicates to avoid // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where // inference might unify those two inner type variables later. - let traits = [coerce_unsized_did, unsize_did]; + let traits = [unsafe_coerce_unsized_did, unsize_did]; while !queue.is_empty() { let obligation = queue.remove(0); debug!("coerce_unsized resolve step: {:?}", obligation); diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs index 8cae61e8c22f6..81b6dd5c38ddd 100644 --- a/compiler/rustc_typeck/src/coherence/builtin.rs +++ b/compiler/rustc_typeck/src/coherence/builtin.rs @@ -23,7 +23,10 @@ pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) { Checker { tcx, trait_def_id } .check(lang_items.drop_trait(), visit_implementation_of_drop) .check(lang_items.copy_trait(), visit_implementation_of_copy) - .check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized) + .check( + lang_items.unsafe_coerce_unsized_trait(), + visit_implementation_of_unsafe_coerce_unsized, + ) .check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn); } @@ -109,8 +112,8 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { } } -fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) { - debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did); +fn visit_implementation_of_unsafe_coerce_unsized(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) { + debug!("visit_implementation_of_unsafe_coerce_unsized: impl_did={:?}", impl_did); // Just compute this for the side-effects, in particular reporting // errors; other parts of the code may demand it for the info of @@ -294,7 +297,8 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did.expect_local()); let span = tcx.hir().span(impl_hir_id); - let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)); + let unsafe_coerce_unsized_trait = + tcx.require_lang_item(LangItem::UnsafeCoerceUnsized, Some(span)); let unsize_trait = tcx.lang_items().require(LangItem::Unsize).unwrap_or_else(|err| { tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err)); @@ -302,7 +306,7 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI let source = tcx.type_of(impl_did); let trait_ref = tcx.impl_trait_ref(impl_did).unwrap(); - assert_eq!(trait_ref.def_id, coerce_unsized_trait); + assert_eq!(trait_ref.def_id, unsafe_coerce_unsized_trait); let target = trait_ref.substs.type_at(1); debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target); @@ -434,7 +438,7 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI } // Collect up all fields that were significantly changed - // i.e., those that contain T in coerce_unsized T -> U + // i.e., those that contain T in unsafe_coerce_unsized T -> U Some((i, a, b)) }) .collect::>(); @@ -444,7 +448,7 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI tcx.sess, span, E0374, - "the trait `CoerceUnsized` may only be implemented \ + "the trait `UnsafeCoerceUnsized` may only be implemented \ for a coercion between structures with one field \ being coerced, none found" ) @@ -465,11 +469,11 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI span, E0375, "implementing the trait \ - `CoerceUnsized` requires multiple \ + `UnsafeCoerceUnsized` requires multiple \ coercions" ) .note( - "`CoerceUnsized` may only be implemented for \ + "`UnsafeCoerceUnsized` may only be implemented for \ a coercion between structures with one field being coerced", ) .note(&format!( @@ -490,7 +494,7 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI let (i, a, b) = diff_fields[0]; let kind = ty::adjustment::CustomCoerceUnsized::Struct(i); - (a, b, coerce_unsized_trait, Some(kind)) + (a, b, unsafe_coerce_unsized_trait, Some(kind)) } _ => { @@ -498,7 +502,7 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI tcx.sess, span, E0376, - "the trait `CoerceUnsized` may only be implemented \ + "the trait `UnsafeCoerceUnsized` may only be implemented \ for a coercion between structures" ) .emit(); diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 722168523763a..d506ea9947e16 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -146,6 +146,7 @@ use core::marker::{Unpin, Unsize}; use core::mem; use core::ops::{ CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Generator, GeneratorState, Receiver, + UnsafeCoerceUnsized, }; use core::pin::Pin; use core::ptr::{self, Unique}; @@ -1652,7 +1653,10 @@ impl + ?Sized, A: Allocator> Fn for Box { } #[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized, A: Allocator> CoerceUnsized> for Box {} +impl, U: ?Sized, A: Allocator> UnsafeCoerceUnsized> for Box {} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl, U: ?Sized, A: Allocator> CoerceUnsized> for Box {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] impl, U: ?Sized> DispatchFromDyn> for Box {} diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 8f6a2ec9ebd1f..9fb5c921b1f1d 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -492,6 +492,7 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { } } +#[cfg_attr(bootstrap, allow(unused_unsafe))] impl<'a, K, V, Type> NodeRef, K, V, Type> { /// # Safety /// - The node has more than `idx` initialized elements. @@ -503,8 +504,8 @@ impl<'a, K, V, Type> NodeRef, K, V, Type> { let keys = unsafe { ptr::addr_of!((*leaf).keys) }; let vals = unsafe { ptr::addr_of_mut!((*leaf).vals) }; // We must coerce to unsized array pointers because of Rust issue #74679. - let keys: *const [_] = keys; - let vals: *mut [_] = vals; + let keys: *const [_] = unsafe { keys }; + let vals: *mut [_] = unsafe { vals }; let key = unsafe { (&*keys.get_unchecked(idx)).assume_init_ref() }; let val = unsafe { (&mut *vals.get_unchecked_mut(idx)).assume_init_mut() }; (key, val) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 0b3079fa59db6..ded2ca048f11b 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -261,7 +261,7 @@ use core::marker::{self, PhantomData, Unpin, Unsize}; #[cfg(not(no_global_oom_handling))] use core::mem::size_of_val; use core::mem::{self, align_of_val_raw, forget}; -use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; +use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver, UnsafeCoerceUnsized}; use core::panic::{RefUnwindSafe, UnwindSafe}; #[cfg(not(no_global_oom_handling))] use core::pin::Pin; @@ -319,7 +319,10 @@ impl !marker::Sync for Rc {} impl UnwindSafe for Rc {} #[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized> for Rc {} +impl, U: ?Sized> UnsafeCoerceUnsized> for Rc {} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl, U: ?Sized> CoerceUnsized> for Rc {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] impl, U: ?Sized> DispatchFromDyn> for Rc {} @@ -2026,7 +2029,10 @@ impl !marker::Send for Weak {} impl !marker::Sync for Weak {} #[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized> for Weak {} +impl, U: ?Sized> UnsafeCoerceUnsized> for Weak {} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl, U: ?Sized> CoerceUnsized> for Weak {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] impl, U: ?Sized> DispatchFromDyn> for Weak {} diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 3183a6db410b8..4714c25c0fba1 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -18,7 +18,7 @@ use core::marker::{PhantomData, Unpin, Unsize}; #[cfg(not(no_global_oom_handling))] use core::mem::size_of_val; use core::mem::{self, align_of_val_raw}; -use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; +use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver, UnsafeCoerceUnsized}; use core::panic::{RefUnwindSafe, UnwindSafe}; use core::pin::Pin; use core::ptr::{self, NonNull}; @@ -245,7 +245,10 @@ unsafe impl Sync for Arc {} impl UnwindSafe for Arc {} #[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized> for Arc {} +impl, U: ?Sized> UnsafeCoerceUnsized> for Arc {} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl, U: ?Sized> CoerceUnsized> for Arc {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] impl, U: ?Sized> DispatchFromDyn> for Arc {} @@ -297,7 +300,9 @@ unsafe impl Send for Weak {} unsafe impl Sync for Weak {} #[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized> for Weak {} +impl, U: ?Sized> UnsafeCoerceUnsized> for Weak {} +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl, U: ?Sized> CoerceUnsized> for Weak {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] impl, U: ?Sized> DispatchFromDyn> for Weak {} diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index f0c934edf3977..923795574bf0c 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -196,7 +196,7 @@ use crate::cmp::Ordering; use crate::fmt::{self, Debug, Display}; use crate::marker::Unsize; use crate::mem; -use crate::ops::{CoerceUnsized, Deref, DerefMut}; +use crate::ops::{CoerceUnsized, Deref, DerefMut, UnsafeCoerceUnsized}; use crate::ptr; /// A mutable memory location. @@ -553,7 +553,10 @@ impl Cell { } #[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U> CoerceUnsized> for Cell {} +impl, U> UnsafeCoerceUnsized> for Cell {} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl, U> CoerceUnsized> for Cell {} impl Cell<[T]> { /// Returns a `&[Cell]` from a `&Cell<[T]>` @@ -1223,7 +1226,10 @@ impl From for RefCell { } #[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U> CoerceUnsized> for RefCell {} +impl, U> UnsafeCoerceUnsized> for RefCell {} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl, U> CoerceUnsized> for RefCell {} struct BorrowRef<'b> { borrow: &'b Cell, @@ -1441,7 +1447,10 @@ impl<'b, T: ?Sized> Ref<'b, T> { } #[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'b, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for Ref<'b, T> {} +impl<'b, T: ?Sized + Unsize, U: ?Sized> UnsafeCoerceUnsized> for Ref<'b, T> {} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl<'b, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for Ref<'b, T> {} #[stable(feature = "std_guard_impls", since = "1.20.0")] impl fmt::Display for Ref<'_, T> { @@ -1683,7 +1692,10 @@ impl DerefMut for RefMut<'_, T> { } #[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'b, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for RefMut<'b, T> {} +impl<'b, T: ?Sized + Unsize, U: ?Sized> UnsafeCoerceUnsized> for RefMut<'b, T> {} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl<'b, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for RefMut<'b, T> {} #[stable(feature = "std_guard_impls", since = "1.20.0")] impl fmt::Display for RefMut<'_, T> { @@ -1953,7 +1965,10 @@ impl From for UnsafeCell { } #[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U> CoerceUnsized> for UnsafeCell {} +impl, U> UnsafeCoerceUnsized> for UnsafeCell {} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl, U> CoerceUnsized> for UnsafeCell {} #[allow(unused)] fn assert_coerce_unsized(a: UnsafeCell<&i32>, b: Cell<&i32>, c: RefCell<&i32>) { diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 333f81ce4cfc4..46c52bb92a803 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -111,12 +111,13 @@ pub trait Sized { /// - `T` is not part of the type of any other fields /// - `Bar: Unsize>`, if the last field of `Foo` has type `Bar` /// -/// `Unsize` is used along with [`ops::CoerceUnsized`] to allow +/// `Unsize` is used along with [`ops::CoerceUnsized`] and [`ops::UnsafeCoerceUnsized`] to allow /// "user-defined" containers such as [`Rc`] to contain dynamically-sized /// types. See the [DST coercion RFC][RFC982] and [the nomicon entry on coercion][nomicon-coerce] /// for more details. /// /// [`ops::CoerceUnsized`]: crate::ops::CoerceUnsized +/// [`ops::UnsafeCoerceUnsized`]: crate::ops::UnsafeCoerceUnsized /// [`Rc`]: ../../std/rc/struct.Rc.html /// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md /// [nomicon-coerce]: ../../nomicon/coercions.html diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 85e04740d96a4..ee6eb7d8073ce 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -194,7 +194,7 @@ pub(crate) use self::try_trait::Try as TryV2; pub use self::generator::{Generator, GeneratorState}; #[unstable(feature = "coerce_unsized", issue = "27732")] -pub use self::unsize::CoerceUnsized; +pub use self::unsize::{CoerceUnsized, UnsafeCoerceUnsized}; #[unstable(feature = "dispatch_from_dyn", issue = "none")] pub use self::unsize::DispatchFromDyn; diff --git a/library/core/src/ops/unsize.rs b/library/core/src/ops/unsize.rs index 483362023b22c..c4124796cca9f 100644 --- a/library/core/src/ops/unsize.rs +++ b/library/core/src/ops/unsize.rs @@ -32,41 +32,78 @@ use crate::marker::Unsize; /// [unsize]: crate::marker::Unsize /// [nomicon-coerce]: ../../nomicon/coercions.html #[unstable(feature = "coerce_unsized", issue = "27732")] +#[cfg_attr(not(bootstrap), lang = "unsafe_coerce_unsized")] +pub trait UnsafeCoerceUnsized { + // Empty. +} + +/// Trait that indicates that this is a pointer or a wrapper for one, +/// where unsizing can be performed on the pointee. +/// +/// See the [DST coercion RFC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce] +/// for more details. +/// +/// When this trait is implemented in addition to [`UnsafeCoerceUnsized`](unsafe-coerce-unsized), +/// performing this unsizing doesn't need to happen inside an unsafe block. +/// +/// [dst-coerce]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md +/// [nomicon-coerce]: ../../nomicon/coercions.html +/// [unsafe-coerce-unsized]: crate::ops::UnsafeCoerceUnsized +#[unstable(feature = "coerce_unsized", issue = "27732")] #[lang = "coerce_unsized"] -pub trait CoerceUnsized { +pub unsafe trait CoerceUnsized: UnsafeCoerceUnsized { // Empty. } // &mut T -> &mut U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} +impl<'a, T: ?Sized + Unsize, U: ?Sized> UnsafeCoerceUnsized<&'a mut U> for &'a mut T {} +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} // &mut T -> &U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {} +impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> UnsafeCoerceUnsized<&'a U> for &'b mut T {} +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {} // &mut T -> *mut U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {} +impl<'a, T: ?Sized + Unsize, U: ?Sized> UnsafeCoerceUnsized<*mut U> for &'a mut T {} +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {} // &mut T -> *const U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {} +impl<'a, T: ?Sized + Unsize, U: ?Sized> UnsafeCoerceUnsized<*const U> for &'a mut T {} +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {} // &T -> &U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} +impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> UnsafeCoerceUnsized<&'a U> for &'b T {} +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} // &T -> *const U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a T {} - +impl<'a, T: ?Sized + Unsize, U: ?Sized> UnsafeCoerceUnsized<*const U> for &'a T {} +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a T {} // *mut T -> *mut U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} +impl, U: ?Sized> UnsafeCoerceUnsized<*mut U> for *mut T {} +#[cfg(bootstrap)] +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} // *mut T -> *const U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} - +impl, U: ?Sized> UnsafeCoerceUnsized<*const U> for *mut T {} +#[cfg(bootstrap)] +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} // *const T -> *const U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} +impl, U: ?Sized> UnsafeCoerceUnsized<*const U> for *const T {} +#[cfg(bootstrap)] +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} /// This is used for object safety, to check that a method's receiver type can be dispatched on. /// diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 6a1a84bafa330..42f3ac29fde8d 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -385,7 +385,7 @@ use crate::cmp::{self, PartialEq, PartialOrd}; use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::marker::{Sized, Unpin}; -use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver}; +use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver, UnsafeCoerceUnsized}; /// A pinned pointer. /// @@ -893,13 +893,16 @@ impl fmt::Pointer for Pin

{ } } -// Note: this means that any impl of `CoerceUnsized` that allows coercing from +// Note: this means that any impl of `UnsafeCoerceUnsized` that allows coercing from // a type that impls `Deref` to a type that impls // `Deref` is unsound. Any such impl would probably be unsound // for other reasons, though, so we just need to take care not to allow such // impls to land in std. #[stable(feature = "pin", since = "1.33.0")] -impl CoerceUnsized> for Pin

where P: CoerceUnsized {} +impl UnsafeCoerceUnsized> for Pin

where P: UnsafeCoerceUnsized {} + +#[stable(feature = "pin", since = "1.33.0")] +unsafe impl CoerceUnsized> for Pin

where P: CoerceUnsized {} #[stable(feature = "pin", since = "1.33.0")] impl DispatchFromDyn> for Pin

where P: DispatchFromDyn {} diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 87c8674af0dc5..b7b7943d4cd9b 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -4,7 +4,7 @@ use crate::fmt; use crate::hash; use crate::marker::Unsize; use crate::mem::{self, MaybeUninit}; -use crate::ops::{CoerceUnsized, DispatchFromDyn}; +use crate::ops::{DispatchFromDyn, UnsafeCoerceUnsized}; use crate::ptr::Unique; use crate::slice::{self, SliceIndex}; @@ -630,7 +630,14 @@ impl Clone for NonNull { impl Copy for NonNull {} #[unstable(feature = "coerce_unsized", issue = "27732")] -impl CoerceUnsized> for NonNull where T: Unsize {} +impl UnsafeCoerceUnsized> for NonNull where T: Unsize {} + +#[cfg(bootstrap)] +#[unstable(feature = "coerce_unsized", issue = "27732")] +unsafe impl crate::ops::CoerceUnsized> for NonNull where + T: Unsize +{ +} #[unstable(feature = "dispatch_from_dyn", issue = "none")] impl DispatchFromDyn> for NonNull where T: Unsize {} diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index cd6afdccc29d7..3420a03743471 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -2,7 +2,7 @@ use crate::convert::From; use crate::fmt; use crate::marker::{PhantomData, Unsize}; use crate::mem; -use crate::ops::{CoerceUnsized, DispatchFromDyn}; +use crate::ops::{DispatchFromDyn, UnsafeCoerceUnsized}; /// A wrapper around a raw non-null `*mut T` that indicates that the possessor /// of this wrapper owns the referent. Useful for building abstractions like @@ -152,7 +152,14 @@ impl Clone for Unique { impl Copy for Unique {} #[unstable(feature = "ptr_internals", issue = "none")] -impl CoerceUnsized> for Unique where T: Unsize {} +impl UnsafeCoerceUnsized> for Unique where T: Unsize {} + +#[cfg(bootstrap)] +#[unstable(feature = "ptr_internals", issue = "none")] +unsafe impl crate::ops::CoerceUnsized> for Unique where + T: Unsize +{ +} #[unstable(feature = "ptr_internals", issue = "none")] impl DispatchFromDyn> for Unique where T: Unsize {} diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 7de70091becf4..1e81725fd3cf6 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -503,8 +503,9 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { struct StrPanicPayload(&'static str); unsafe impl BoxMeUp for StrPanicPayload { + #[cfg_attr(bootstrap, allow(unused_unsafe))] fn take_box(&mut self) -> *mut (dyn Any + Send) { - Box::into_raw(Box::new(self.0)) + unsafe { Box::into_raw(Box::new(self.0)) } } fn get(&mut self) -> &(dyn Any + Send) { @@ -555,6 +556,7 @@ pub fn begin_panic(msg: M) -> ! { } unsafe impl BoxMeUp for PanicPayload { + #[cfg_attr(bootstrap, allow(unused_unsafe))] fn take_box(&mut self) -> *mut (dyn Any + Send) { // Note that this should be the only allocation performed in this code path. Currently // this means that panic!() on OOM will invoke this code path, but then again we're not @@ -565,7 +567,7 @@ pub fn begin_panic(msg: M) -> ! { Some(a) => Box::new(a) as Box, None => process::abort(), }; - Box::into_raw(data) + unsafe { Box::into_raw(data) } } fn get(&mut self) -> &(dyn Any + Send) { @@ -650,8 +652,9 @@ pub fn rust_panic_without_hook(payload: Box) -> ! { struct RewrapBox(Box); unsafe impl BoxMeUp for RewrapBox { + #[cfg_attr(bootstrap, allow(unused_unsafe))] fn take_box(&mut self) -> *mut (dyn Any + Send) { - Box::into_raw(mem::replace(&mut self.0, Box::new(()))) + unsafe { Box::into_raw(mem::replace(&mut self.0, Box::new(()))) } } fn get(&mut self) -> &(dyn Any + Send) { diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs index 9fdb1b4584479..9d1263555e450 100644 --- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs @@ -2,7 +2,7 @@ use crate::cell::UnsafeCell; use crate::mem; -use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut}; +use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut, UnsafeCoerceUnsized}; use crate::ptr::{self, NonNull}; use crate::slice; use crate::slice::SliceIndex; @@ -565,7 +565,10 @@ where } #[unstable(feature = "sgx_platform", issue = "56975")] -impl, U> CoerceUnsized> for UserRef {} +impl, U> UnsafeCoerceUnsized> for UserRef {} + +#[unstable(feature = "sgx_platform", issue = "56975")] +unsafe impl, U> CoerceUnsized> for UserRef {} #[unstable(feature = "sgx_platform", issue = "56975")] impl Index for UserRef<[T]>