Auto merge of #135402 - matthiaskrgr:rollup-cz7hs13, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #129259 (Add inherent versions of MaybeUninit methods for slices) - #135374 (Suggest typo fix when trait path expression is typo'ed) - #135377 (Make MIR cleanup for functions with impossible predicates into a real MIR pass) - #135378 (Remove a bunch of diagnostic stashing that doesn't do anything) - #135397 (compiletest: add erroneous variant to `string_enum`s conversions error) - #135398 (add more crash tests) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7bb9888953
53 changed files with 988 additions and 677 deletions
|
|
@ -78,7 +78,7 @@ impl<T> ArenaChunk<T> {
|
|||
// been initialized.
|
||||
unsafe {
|
||||
let slice = self.storage.as_mut();
|
||||
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut slice[..len]));
|
||||
slice[..len].assume_init_drop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,7 +152,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
let (Ok(e) | Err(e)) = prev
|
||||
.build_mismatch_error(
|
||||
&OpaqueHiddenType { ty, span: concrete_type.span },
|
||||
opaque_type_key.def_id,
|
||||
infcx.tcx,
|
||||
)
|
||||
.map(|d| d.emit());
|
||||
|
|
|
|||
|
|
@ -566,9 +566,7 @@ pub enum StashKey {
|
|||
/// FRU syntax
|
||||
MaybeFruTypo,
|
||||
CallAssocMethod,
|
||||
TraitMissingMethod,
|
||||
AssociatedTypeSuggestion,
|
||||
OpaqueHiddenTypeMismatch,
|
||||
MaybeForgetReturn,
|
||||
/// Query cycle detected, stashing in favor of a better error.
|
||||
Cycle,
|
||||
|
|
|
|||
|
|
@ -575,7 +575,7 @@ fn sanity_check_found_hidden_type<'tcx>(
|
|||
} else {
|
||||
let span = tcx.def_span(key.def_id);
|
||||
let other = ty::OpaqueHiddenType { ty: hidden_ty, span };
|
||||
Err(ty.build_mismatch_error(&other, key.def_id, tcx)?.emit())
|
||||
Err(ty.build_mismatch_error(&other, tcx)?.emit())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use rustc_errors::StashKey;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
|
|
@ -45,7 +44,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
|
|||
if !hidden.ty.references_error() {
|
||||
for concrete_type in locator.typeck_types {
|
||||
if concrete_type.ty != tcx.erase_regions(hidden.ty) {
|
||||
if let Ok(d) = hidden.build_mismatch_error(&concrete_type, def_id, tcx) {
|
||||
if let Ok(d) = hidden.build_mismatch_error(&concrete_type, tcx) {
|
||||
d.emit();
|
||||
}
|
||||
}
|
||||
|
|
@ -121,7 +120,7 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
|
|||
if !hidden.ty.references_error() {
|
||||
for concrete_type in locator.typeck_types {
|
||||
if concrete_type.ty != tcx.erase_regions(hidden.ty) {
|
||||
if let Ok(d) = hidden.build_mismatch_error(&concrete_type, def_id, tcx) {
|
||||
if let Ok(d) = hidden.build_mismatch_error(&concrete_type, tcx) {
|
||||
d.emit();
|
||||
}
|
||||
}
|
||||
|
|
@ -285,9 +284,8 @@ impl TaitConstraintLocator<'_> {
|
|||
debug!(?concrete_type, "found constraint");
|
||||
if let Some(prev) = &mut self.found {
|
||||
if concrete_type.ty != prev.ty {
|
||||
let (Ok(guar) | Err(guar)) = prev
|
||||
.build_mismatch_error(&concrete_type, self.def_id, self.tcx)
|
||||
.map(|d| d.emit());
|
||||
let (Ok(guar) | Err(guar)) =
|
||||
prev.build_mismatch_error(&concrete_type, self.tcx).map(|d| d.emit());
|
||||
prev.ty = Ty::new_error(self.tcx, guar);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -361,11 +359,8 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
|
|||
);
|
||||
if let Some(prev) = &mut hir_opaque_ty {
|
||||
if concrete_type.ty != prev.ty {
|
||||
if let Ok(d) = prev.build_mismatch_error(&concrete_type, def_id, tcx) {
|
||||
d.stash(
|
||||
tcx.def_span(opaque_type_key.def_id),
|
||||
StashKey::OpaqueHiddenTypeMismatch,
|
||||
);
|
||||
if let Ok(d) = prev.build_mismatch_error(&concrete_type, tcx) {
|
||||
d.emit();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -435,9 +430,7 @@ impl RpitConstraintChecker<'_> {
|
|||
debug!(?concrete_type, "found constraint");
|
||||
|
||||
if concrete_type.ty != self.found.ty {
|
||||
if let Ok(d) =
|
||||
self.found.build_mismatch_error(&concrete_type, self.def_id, self.tcx)
|
||||
{
|
||||
if let Ok(d) = self.found.build_mismatch_error(&concrete_type, self.tcx) {
|
||||
d.emit();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ use rustc_ast::TraitObjectSyntax;
|
|||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Diag, EmissionGuarantee, ErrorGuaranteed, StashKey, Suggestions};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def::{DefKind, Namespace, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_lint_defs::Applicability;
|
||||
use rustc_lint_defs::builtin::BARE_TRAIT_OBJECTS;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
|
||||
|
||||
use super::HirTyLowerer;
|
||||
|
|
@ -86,7 +88,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
// Check if the impl trait that we are considering is an impl of a local trait.
|
||||
self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag);
|
||||
self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag);
|
||||
// In case there is an associate type with the same name
|
||||
self.maybe_suggest_typoed_method(
|
||||
self_ty,
|
||||
poly_trait_ref.trait_ref.trait_def_id(),
|
||||
&mut diag,
|
||||
);
|
||||
// In case there is an associated type with the same name
|
||||
// Add the suggestion to this error
|
||||
if let Some(mut sugg) =
|
||||
tcx.dcx().steal_non_err(self_ty.span, StashKey::AssociatedTypeSuggestion)
|
||||
|
|
@ -96,7 +103,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
s1.append(s2);
|
||||
sugg.cancel();
|
||||
}
|
||||
diag.stash(self_ty.span, StashKey::TraitMissingMethod)
|
||||
Some(diag.emit())
|
||||
} else {
|
||||
tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| {
|
||||
lint.primary_message("trait objects without an explicit `dyn` are deprecated");
|
||||
|
|
@ -343,4 +350,44 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn maybe_suggest_typoed_method(
|
||||
&self,
|
||||
self_ty: &hir::Ty<'_>,
|
||||
trait_def_id: Option<DefId>,
|
||||
diag: &mut Diag<'_>,
|
||||
) {
|
||||
let tcx = self.tcx();
|
||||
let Some(trait_def_id) = trait_def_id else {
|
||||
return;
|
||||
};
|
||||
let hir::Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Path(hir::QPath::TypeRelative(path_ty, segment)),
|
||||
..
|
||||
}) = tcx.parent_hir_node(self_ty.hir_id)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if path_ty.hir_id != self_ty.hir_id {
|
||||
return;
|
||||
}
|
||||
let names: Vec<_> = tcx
|
||||
.associated_items(trait_def_id)
|
||||
.in_definition_order()
|
||||
.filter(|assoc| assoc.kind.namespace() == Namespace::ValueNS)
|
||||
.map(|cand| cand.name)
|
||||
.collect();
|
||||
if let Some(typo) = find_best_match_for_name(&names, segment.ident.name, None) {
|
||||
diag.span_suggestion_verbose(
|
||||
segment.ident.span,
|
||||
format!(
|
||||
"you may have misspelled this associated item, causing `{}` \
|
||||
to be interpreted as a type rather than a trait",
|
||||
tcx.item_name(trait_def_id),
|
||||
),
|
||||
typo,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::slice;
|
|||
|
||||
use rustc_abi::FieldIdx;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey};
|
||||
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan};
|
||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
|
|
@ -806,17 +806,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let item_name = item_segment.ident;
|
||||
let result = self
|
||||
.resolve_fully_qualified_call(span, item_name, ty.normalized, qself.span, hir_id)
|
||||
.map(|r| {
|
||||
// lint bare trait if the method is found in the trait
|
||||
if span.edition().at_least_rust_2021() {
|
||||
self.dcx().try_steal_modify_and_emit_err(
|
||||
qself.span,
|
||||
StashKey::TraitMissingMethod,
|
||||
|_err| {},
|
||||
);
|
||||
}
|
||||
r
|
||||
})
|
||||
.or_else(|error| {
|
||||
let guar = self
|
||||
.dcx()
|
||||
|
|
@ -840,17 +829,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
// Emit the diagnostic for bare traits. (We used to cancel for slightly better
|
||||
// error messages, but cancelling stashed diagnostics is no longer allowed because
|
||||
// it causes problems when tracking whether errors have actually occurred.)
|
||||
if span.edition().at_least_rust_2021() {
|
||||
self.dcx().try_steal_modify_and_emit_err(
|
||||
qself.span,
|
||||
StashKey::TraitMissingMethod,
|
||||
|_err| {},
|
||||
);
|
||||
}
|
||||
|
||||
if item_name.name != kw::Empty {
|
||||
self.report_method_error(
|
||||
hir_id,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
use std::mem;
|
||||
|
||||
use rustc_data_structures::unord::ExtendUnord;
|
||||
use rustc_errors::{ErrorGuaranteed, StashKey};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::HirId;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
|
|
@ -582,15 +582,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
|||
&& last_opaque_ty.ty != hidden_type.ty
|
||||
{
|
||||
assert!(!self.fcx.next_trait_solver());
|
||||
if let Ok(d) = hidden_type.build_mismatch_error(
|
||||
&last_opaque_ty,
|
||||
opaque_type_key.def_id,
|
||||
self.tcx(),
|
||||
) {
|
||||
d.stash(
|
||||
self.tcx().def_span(opaque_type_key.def_id),
|
||||
StashKey::OpaqueHiddenTypeMismatch,
|
||||
);
|
||||
if let Ok(d) = hidden_type.build_mismatch_error(&last_opaque_ty, self.tcx()) {
|
||||
d.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
|
|||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_errors::{Diag, ErrorGuaranteed, StashKey};
|
||||
use rustc_errors::{Diag, ErrorGuaranteed};
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
|
||||
|
|
@ -782,18 +782,8 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
|
|||
pub fn build_mismatch_error(
|
||||
&self,
|
||||
other: &Self,
|
||||
opaque_def_id: LocalDefId,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> Result<Diag<'tcx>, ErrorGuaranteed> {
|
||||
// We used to cancel here for slightly better error messages, but
|
||||
// cancelling stashed diagnostics is no longer allowed because it
|
||||
// causes problems when tracking whether errors have actually
|
||||
// occurred.
|
||||
tcx.sess.dcx().try_steal_modify_and_emit_err(
|
||||
tcx.def_span(opaque_def_id),
|
||||
StashKey::OpaqueHiddenTypeMismatch,
|
||||
|_err| {},
|
||||
);
|
||||
(self.ty, other.ty).error_reported()?;
|
||||
// Found different concrete types for the opaque type.
|
||||
let sub_diag = if self.span == other.span {
|
||||
|
|
|
|||
56
compiler/rustc_mir_transform/src/impossible_predicates.rs
Normal file
56
compiler/rustc_mir_transform/src/impossible_predicates.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
//! Check if it's even possible to satisfy the 'where' clauses
|
||||
//! for this item.
|
||||
//!
|
||||
//! It's possible to `#!feature(trivial_bounds)]` to write
|
||||
//! a function with impossible to satisfy clauses, e.g.:
|
||||
//! `fn foo() where String: Copy {}`.
|
||||
//!
|
||||
//! We don't usually need to worry about this kind of case,
|
||||
//! since we would get a compilation error if the user tried
|
||||
//! to call it. However, since we optimize even without any
|
||||
//! calls to the function, we need to make sure that it even
|
||||
//! makes sense to try to evaluate the body.
|
||||
//!
|
||||
//! If there are unsatisfiable where clauses, then all bets are
|
||||
//! off, and we just give up.
|
||||
//!
|
||||
//! We manually filter the predicates, skipping anything that's not
|
||||
//! "global". We are in a potentially generic context
|
||||
//! (e.g. we are evaluating a function without instantiating generic
|
||||
//! parameters, so this filtering serves two purposes:
|
||||
//!
|
||||
//! 1. We skip evaluating any predicates that we would
|
||||
//! never be able prove are unsatisfiable (e.g. `<T as Foo>`
|
||||
//! 2. We avoid trying to normalize predicates involving generic
|
||||
//! parameters (e.g. `<T as Foo>::MyItem`). This can confuse
|
||||
//! the normalization code (leading to cycle errors), since
|
||||
//! it's usually never invoked in this way.
|
||||
|
||||
use rustc_middle::mir::{Body, START_BLOCK, TerminatorKind};
|
||||
use rustc_middle::ty::{TyCtxt, TypeVisitableExt};
|
||||
use rustc_trait_selection::traits;
|
||||
use tracing::trace;
|
||||
|
||||
use crate::pass_manager::MirPass;
|
||||
|
||||
pub(crate) struct ImpossiblePredicates;
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for ImpossiblePredicates {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
let predicates = tcx
|
||||
.predicates_of(body.source.def_id())
|
||||
.predicates
|
||||
.iter()
|
||||
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
|
||||
if traits::impossible_predicates(tcx, traits::elaborate(tcx, predicates).collect()) {
|
||||
trace!("found unsatisfiable predicates for {:?}", body.source);
|
||||
// Clear the body to only contain a single `unreachable` statement.
|
||||
let bbs = body.basic_blocks.as_mut();
|
||||
bbs.raw.truncate(1);
|
||||
bbs[START_BLOCK].statements.clear();
|
||||
bbs[START_BLOCK].terminator_mut().kind = TerminatorKind::Unreachable;
|
||||
body.var_debug_info.clear();
|
||||
body.local_decls.raw.truncate(body.arg_count + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -34,8 +34,7 @@ use rustc_middle::util::Providers;
|
|||
use rustc_middle::{bug, query, span_bug};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{DUMMY_SP, sym};
|
||||
use rustc_trait_selection::traits;
|
||||
use tracing::{debug, trace};
|
||||
use tracing::debug;
|
||||
|
||||
#[macro_use]
|
||||
mod pass_manager;
|
||||
|
|
@ -142,6 +141,7 @@ declare_passes! {
|
|||
// Made public so that `mir_drops_elaborated_and_const_checked` can be overridden
|
||||
// by custom rustc drivers, running all the steps by themselves. See #114628.
|
||||
pub mod inline : Inline, ForceInline;
|
||||
mod impossible_predicates : ImpossiblePredicates;
|
||||
mod instsimplify : InstSimplify { BeforeInline, AfterSimplifyCfg };
|
||||
mod jump_threading : JumpThreading;
|
||||
mod known_panics_lint : KnownPanicsLint;
|
||||
|
|
@ -502,50 +502,6 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
|
|||
body.tainted_by_errors = Some(error_reported);
|
||||
}
|
||||
|
||||
// Check if it's even possible to satisfy the 'where' clauses
|
||||
// for this item.
|
||||
//
|
||||
// This branch will never be taken for any normal function.
|
||||
// However, it's possible to `#!feature(trivial_bounds)]` to write
|
||||
// a function with impossible to satisfy clauses, e.g.:
|
||||
// `fn foo() where String: Copy {}`
|
||||
//
|
||||
// We don't usually need to worry about this kind of case,
|
||||
// since we would get a compilation error if the user tried
|
||||
// to call it. However, since we optimize even without any
|
||||
// calls to the function, we need to make sure that it even
|
||||
// makes sense to try to evaluate the body.
|
||||
//
|
||||
// If there are unsatisfiable where clauses, then all bets are
|
||||
// off, and we just give up.
|
||||
//
|
||||
// We manually filter the predicates, skipping anything that's not
|
||||
// "global". We are in a potentially generic context
|
||||
// (e.g. we are evaluating a function without instantiating generic
|
||||
// parameters, so this filtering serves two purposes:
|
||||
//
|
||||
// 1. We skip evaluating any predicates that we would
|
||||
// never be able prove are unsatisfiable (e.g. `<T as Foo>`
|
||||
// 2. We avoid trying to normalize predicates involving generic
|
||||
// parameters (e.g. `<T as Foo>::MyItem`). This can confuse
|
||||
// the normalization code (leading to cycle errors), since
|
||||
// it's usually never invoked in this way.
|
||||
let predicates = tcx
|
||||
.predicates_of(body.source.def_id())
|
||||
.predicates
|
||||
.iter()
|
||||
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
|
||||
if traits::impossible_predicates(tcx, traits::elaborate(tcx, predicates).collect()) {
|
||||
trace!("found unsatisfiable predicates for {:?}", body.source);
|
||||
// Clear the body to only contain a single `unreachable` statement.
|
||||
let bbs = body.basic_blocks.as_mut();
|
||||
bbs.raw.truncate(1);
|
||||
bbs[START_BLOCK].statements.clear();
|
||||
bbs[START_BLOCK].terminator_mut().kind = TerminatorKind::Unreachable;
|
||||
body.var_debug_info.clear();
|
||||
body.local_decls.raw.truncate(body.arg_count + 1);
|
||||
}
|
||||
|
||||
run_analysis_to_runtime_passes(tcx, &mut body);
|
||||
|
||||
// Now that drop elaboration has been performed, we can check for
|
||||
|
|
@ -593,6 +549,7 @@ pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'
|
|||
/// After this series of passes, no lifetime analysis based on borrowing can be done.
|
||||
fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
let passes: &[&dyn MirPass<'tcx>] = &[
|
||||
&impossible_predicates::ImpossiblePredicates,
|
||||
&cleanup_post_borrowck::CleanupPostBorrowck,
|
||||
&remove_noop_landing_pads::RemoveNoopLandingPads,
|
||||
&simplify::SimplifyCfg::PostAnalysis,
|
||||
|
|
|
|||
|
|
@ -383,9 +383,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
|
|||
/// Borrows a view into the keys stored in the node.
|
||||
pub fn keys(&self) -> &[K] {
|
||||
let leaf = self.into_leaf();
|
||||
unsafe {
|
||||
MaybeUninit::slice_assume_init_ref(leaf.keys.get_unchecked(..usize::from(leaf.len)))
|
||||
}
|
||||
unsafe { leaf.keys.get_unchecked(..usize::from(leaf.len)).assume_init_ref() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ impl<T, const N: usize> IntoIter<T, N> {
|
|||
// SAFETY: We know that all elements within `alive` are properly initialized.
|
||||
unsafe {
|
||||
let slice = self.data.get_unchecked(self.alive.clone());
|
||||
MaybeUninit::slice_assume_init_ref(slice)
|
||||
slice.assume_init_ref()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -224,7 +224,7 @@ impl<T, const N: usize> IntoIter<T, N> {
|
|||
// SAFETY: We know that all elements within `alive` are properly initialized.
|
||||
unsafe {
|
||||
let slice = self.data.get_unchecked_mut(self.alive.clone());
|
||||
MaybeUninit::slice_assume_init_mut(slice)
|
||||
slice.assume_init_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -285,7 +285,7 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
|
|||
// SAFETY: These elements are currently initialized, so it's fine to drop them.
|
||||
unsafe {
|
||||
let slice = self.data.get_unchecked_mut(range_to_drop);
|
||||
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice));
|
||||
slice.assume_init_drop();
|
||||
}
|
||||
|
||||
NonZero::new(remaining).map_or(Ok(()), Err)
|
||||
|
|
@ -340,7 +340,7 @@ impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
|
|||
// SAFETY: These elements are currently initialized, so it's fine to drop them.
|
||||
unsafe {
|
||||
let slice = self.data.get_unchecked_mut(range_to_drop);
|
||||
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice));
|
||||
slice.assume_init_drop();
|
||||
}
|
||||
|
||||
NonZero::new(remaining).map_or(Ok(()), Err)
|
||||
|
|
|
|||
|
|
@ -911,9 +911,7 @@ impl<T> Drop for Guard<'_, T> {
|
|||
|
||||
// SAFETY: this slice will contain only initialized objects.
|
||||
unsafe {
|
||||
crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
|
||||
self.array_mut.get_unchecked_mut(..self.initialized),
|
||||
));
|
||||
self.array_mut.get_unchecked_mut(..self.initialized).assume_init_drop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ impl<'data> BorrowedBuf<'data> {
|
|||
// SAFETY: We only slice the filled part of the buffer, which is always valid
|
||||
unsafe {
|
||||
let buf = self.buf.get_unchecked(..self.filled);
|
||||
MaybeUninit::slice_assume_init_ref(buf)
|
||||
buf.assume_init_ref()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ impl<'data> BorrowedBuf<'data> {
|
|||
// SAFETY: We only slice the filled part of the buffer, which is always valid
|
||||
unsafe {
|
||||
let buf = self.buf.get_unchecked_mut(..self.filled);
|
||||
MaybeUninit::slice_assume_init_mut(buf)
|
||||
buf.assume_init_mut()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ impl<'data> BorrowedBuf<'data> {
|
|||
// SAFETY: We only slice the filled part of the buffer, which is always valid
|
||||
unsafe {
|
||||
let buf = self.buf.get_unchecked(..self.filled);
|
||||
MaybeUninit::slice_assume_init_ref(buf)
|
||||
buf.assume_init_ref()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ impl<'data> BorrowedBuf<'data> {
|
|||
// SAFETY: We only slice the filled part of the buffer, which is always valid
|
||||
unsafe {
|
||||
let buf = self.buf.get_unchecked_mut(..self.filled);
|
||||
MaybeUninit::slice_assume_init_mut(buf)
|
||||
buf.assume_init_mut()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -233,7 +233,7 @@ impl<'a> BorrowedCursor<'a> {
|
|||
// SAFETY: We only slice the initialized part of the buffer, which is always valid
|
||||
unsafe {
|
||||
let buf = self.buf.buf.get_unchecked(self.buf.filled..self.buf.init);
|
||||
MaybeUninit::slice_assume_init_ref(buf)
|
||||
buf.assume_init_ref()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -243,7 +243,7 @@ impl<'a> BorrowedCursor<'a> {
|
|||
// SAFETY: We only slice the initialized part of the buffer, which is always valid
|
||||
unsafe {
|
||||
let buf = self.buf.buf.get_unchecked_mut(self.buf.filled..self.buf.init);
|
||||
MaybeUninit::slice_assume_init_mut(buf)
|
||||
buf.assume_init_mut()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -344,7 +344,7 @@ impl<'a> BorrowedCursor<'a> {
|
|||
|
||||
// SAFETY: we do not de-initialize any of the elements of the slice
|
||||
unsafe {
|
||||
MaybeUninit::copy_from_slice(&mut self.as_mut()[..buf.len()], buf);
|
||||
self.as_mut()[..buf.len()].write_copy_of_slice(buf);
|
||||
}
|
||||
|
||||
// SAFETY: We just added the entire contents of buf to the filled section.
|
||||
|
|
|
|||
|
|
@ -81,9 +81,7 @@ where
|
|||
if const { crate::mem::needs_drop::<T>() } {
|
||||
// SAFETY: self.initialized is always <= N, which also is the length of the array.
|
||||
unsafe {
|
||||
core::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
|
||||
self.array.get_unchecked_mut(..self.initialized),
|
||||
));
|
||||
self.array.get_unchecked_mut(..self.initialized).assume_init_drop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::any::type_name;
|
||||
use crate::mem::{self, ManuallyDrop};
|
||||
use crate::mem::ManuallyDrop;
|
||||
use crate::{fmt, intrinsics, ptr, slice};
|
||||
|
||||
/// A wrapper type to construct uninitialized instances of `T`.
|
||||
|
|
@ -354,7 +354,7 @@ impl<T> MaybeUninit<T> {
|
|||
/// fn read(buf: &mut [MaybeUninit<u8>]) -> &[u8] {
|
||||
/// unsafe {
|
||||
/// let len = read_into_buffer(buf.as_mut_ptr() as *mut u8, buf.len());
|
||||
/// MaybeUninit::slice_assume_init_ref(&buf[..len])
|
||||
/// buf[..len].assume_init_ref()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
|
|
@ -740,7 +740,7 @@ impl<T> MaybeUninit<T> {
|
|||
///
|
||||
/// On top of that, all additional invariants of the type `T` must be
|
||||
/// satisfied, as the `Drop` implementation of `T` (or its members) may
|
||||
/// rely on this. For example, setting a [`Vec<T>`] to an invalid but
|
||||
/// rely on this. For example, setting a `Vec<T>` to an invalid but
|
||||
/// non-null address makes it initialized (under the current implementation;
|
||||
/// this does not constitute a stable guarantee), because the only
|
||||
/// requirement the compiler knows about it is that the data pointer must be
|
||||
|
|
@ -748,7 +748,6 @@ impl<T> MaybeUninit<T> {
|
|||
/// behavior.
|
||||
///
|
||||
/// [`assume_init`]: MaybeUninit::assume_init
|
||||
/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
|
||||
#[stable(feature = "maybe_uninit_extra", since = "1.60.0")]
|
||||
pub unsafe fn assume_init_drop(&mut self) {
|
||||
// SAFETY: the caller must guarantee that `self` is initialized and
|
||||
|
|
@ -982,339 +981,6 @@ impl<T> MaybeUninit<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Assuming all the elements are initialized, get a slice to them.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee that the `MaybeUninit<T>` elements
|
||||
/// really are in an initialized state.
|
||||
/// Calling this when the content is not yet fully initialized causes undefined behavior.
|
||||
///
|
||||
/// See [`assume_init_ref`] for more details and examples.
|
||||
///
|
||||
/// [`assume_init_ref`]: MaybeUninit::assume_init_ref
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub const unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] {
|
||||
// SAFETY: casting `slice` to a `*const [T]` is safe since the caller guarantees that
|
||||
// `slice` is initialized, and `MaybeUninit` is guaranteed to have the same layout as `T`.
|
||||
// The pointer obtained is valid since it refers to memory owned by `slice` which is a
|
||||
// reference and thus guaranteed to be valid for reads.
|
||||
unsafe { &*(slice as *const [Self] as *const [T]) }
|
||||
}
|
||||
|
||||
/// Assuming all the elements are initialized, get a mutable slice to them.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee that the `MaybeUninit<T>` elements
|
||||
/// really are in an initialized state.
|
||||
/// Calling this when the content is not yet fully initialized causes undefined behavior.
|
||||
///
|
||||
/// See [`assume_init_mut`] for more details and examples.
|
||||
///
|
||||
/// [`assume_init_mut`]: MaybeUninit::assume_init_mut
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub const unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] {
|
||||
// SAFETY: similar to safety notes for `slice_get_ref`, but we have a
|
||||
// mutable reference which is also guaranteed to be valid for writes.
|
||||
unsafe { &mut *(slice as *mut [Self] as *mut [T]) }
|
||||
}
|
||||
|
||||
/// Gets a pointer to the first element of the array.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub const fn slice_as_ptr(this: &[MaybeUninit<T>]) -> *const T {
|
||||
this.as_ptr() as *const T
|
||||
}
|
||||
|
||||
/// Gets a mutable pointer to the first element of the array.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub const fn slice_as_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T {
|
||||
this.as_mut_ptr() as *mut T
|
||||
}
|
||||
|
||||
/// Copies the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`.
|
||||
///
|
||||
/// If `T` does not implement `Copy`, use [`clone_from_slice`]
|
||||
///
|
||||
/// This is similar to [`slice::copy_from_slice`].
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if the two slices have different lengths.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_write_slice)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut dst = [MaybeUninit::uninit(); 32];
|
||||
/// let src = [0; 32];
|
||||
///
|
||||
/// let init = MaybeUninit::copy_from_slice(&mut dst, &src);
|
||||
///
|
||||
/// assert_eq!(init, src);
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_write_slice)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut vec = Vec::with_capacity(32);
|
||||
/// let src = [0; 16];
|
||||
///
|
||||
/// MaybeUninit::copy_from_slice(&mut vec.spare_capacity_mut()[..src.len()], &src);
|
||||
///
|
||||
/// // SAFETY: we have just copied all the elements of len into the spare capacity
|
||||
/// // the first src.len() elements of the vec are valid now.
|
||||
/// unsafe {
|
||||
/// vec.set_len(src.len());
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(vec, src);
|
||||
/// ```
|
||||
///
|
||||
/// [`clone_from_slice`]: MaybeUninit::clone_from_slice
|
||||
#[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
|
||||
pub fn copy_from_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T]
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
// SAFETY: &[T] and &[MaybeUninit<T>] have the same layout
|
||||
let uninit_src: &[MaybeUninit<T>] = unsafe { super::transmute(src) };
|
||||
|
||||
this.copy_from_slice(uninit_src);
|
||||
|
||||
// SAFETY: Valid elements have just been copied into `this` so it is initialized
|
||||
unsafe { MaybeUninit::slice_assume_init_mut(this) }
|
||||
}
|
||||
|
||||
/// Clones the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`.
|
||||
/// Any already initialized elements will not be dropped.
|
||||
///
|
||||
/// If `T` implements `Copy`, use [`copy_from_slice`]
|
||||
///
|
||||
/// This is similar to [`slice::clone_from_slice`] but does not drop existing elements.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if the two slices have different lengths, or if the implementation of `Clone` panics.
|
||||
///
|
||||
/// If there is a panic, the already cloned elements will be dropped.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_write_slice)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()];
|
||||
/// let src = ["wibbly".to_string(), "wobbly".to_string(), "timey".to_string(), "wimey".to_string(), "stuff".to_string()];
|
||||
///
|
||||
/// let init = MaybeUninit::clone_from_slice(&mut dst, &src);
|
||||
///
|
||||
/// assert_eq!(init, src);
|
||||
/// # // Prevent leaks for Miri
|
||||
/// # unsafe { std::ptr::drop_in_place(init); }
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_write_slice)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut vec = Vec::with_capacity(32);
|
||||
/// let src = ["rust", "is", "a", "pretty", "cool", "language"];
|
||||
///
|
||||
/// MaybeUninit::clone_from_slice(&mut vec.spare_capacity_mut()[..src.len()], &src);
|
||||
///
|
||||
/// // SAFETY: we have just cloned all the elements of len into the spare capacity
|
||||
/// // the first src.len() elements of the vec are valid now.
|
||||
/// unsafe {
|
||||
/// vec.set_len(src.len());
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(vec, src);
|
||||
/// ```
|
||||
///
|
||||
/// [`copy_from_slice`]: MaybeUninit::copy_from_slice
|
||||
#[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
|
||||
pub fn clone_from_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T]
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
// unlike copy_from_slice this does not call clone_from_slice on the slice
|
||||
// this is because `MaybeUninit<T: Clone>` does not implement Clone.
|
||||
|
||||
assert_eq!(this.len(), src.len(), "destination and source slices have different lengths");
|
||||
// NOTE: We need to explicitly slice them to the same length
|
||||
// for bounds checking to be elided, and the optimizer will
|
||||
// generate memcpy for simple cases (for example T = u8).
|
||||
let len = this.len();
|
||||
let src = &src[..len];
|
||||
|
||||
// guard is needed b/c panic might happen during a clone
|
||||
let mut guard = Guard { slice: this, initialized: 0 };
|
||||
|
||||
for i in 0..len {
|
||||
guard.slice[i].write(src[i].clone());
|
||||
guard.initialized += 1;
|
||||
}
|
||||
|
||||
super::forget(guard);
|
||||
|
||||
// SAFETY: Valid elements have just been written into `this` so it is initialized
|
||||
unsafe { MaybeUninit::slice_assume_init_mut(this) }
|
||||
}
|
||||
|
||||
/// Fills `this` with elements by cloning `value`, returning a mutable reference to the now
|
||||
/// initialized contents of `this`.
|
||||
/// Any previously initialized elements will not be dropped.
|
||||
///
|
||||
/// This is similar to [`slice::fill`].
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if any call to `Clone` panics.
|
||||
///
|
||||
/// If such a panic occurs, any elements previously initialized during this operation will be
|
||||
/// dropped.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Fill an uninit vec with 1.
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_fill)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut buf = vec![MaybeUninit::uninit(); 10];
|
||||
/// let initialized = MaybeUninit::fill(buf.as_mut_slice(), 1);
|
||||
/// assert_eq!(initialized, &mut [1; 10]);
|
||||
/// ```
|
||||
#[doc(alias = "memset")]
|
||||
#[unstable(feature = "maybe_uninit_fill", issue = "117428")]
|
||||
pub fn fill<'a>(this: &'a mut [MaybeUninit<T>], value: T) -> &'a mut [T]
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
SpecFill::spec_fill(this, value);
|
||||
// SAFETY: Valid elements have just been filled into `this` so it is initialized
|
||||
unsafe { MaybeUninit::slice_assume_init_mut(this) }
|
||||
}
|
||||
|
||||
/// Fills `this` with elements returned by calling a closure repeatedly.
|
||||
///
|
||||
/// This method uses a closure to create new values. If you'd rather `Clone` a given value, use
|
||||
/// [`MaybeUninit::fill`]. If you want to use the `Default` trait to generate values, you can
|
||||
/// pass [`Default::default`] as the argument.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if any call to the provided closure panics.
|
||||
///
|
||||
/// If such a panic occurs, any elements previously initialized during this operation will be
|
||||
/// dropped.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Fill an uninit vec with the default value.
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_fill)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut buf = vec![MaybeUninit::<i32>::uninit(); 10];
|
||||
/// let initialized = MaybeUninit::fill_with(buf.as_mut_slice(), Default::default);
|
||||
/// assert_eq!(initialized, &mut [0; 10]);
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_fill", issue = "117428")]
|
||||
pub fn fill_with<'a, F>(this: &'a mut [MaybeUninit<T>], mut f: F) -> &'a mut [T]
|
||||
where
|
||||
F: FnMut() -> T,
|
||||
{
|
||||
let mut guard = Guard { slice: this, initialized: 0 };
|
||||
|
||||
for element in guard.slice.iter_mut() {
|
||||
element.write(f());
|
||||
guard.initialized += 1;
|
||||
}
|
||||
|
||||
super::forget(guard);
|
||||
|
||||
// SAFETY: Valid elements have just been written into `this` so it is initialized
|
||||
unsafe { MaybeUninit::slice_assume_init_mut(this) }
|
||||
}
|
||||
|
||||
/// Fills `this` with elements yielded by an iterator until either all elements have been
|
||||
/// initialized or the iterator is empty.
|
||||
///
|
||||
/// Returns two slices. The first slice contains the initialized portion of the original slice.
|
||||
/// The second slice is the still-uninitialized remainder of the original slice.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if the iterator's `next` function panics.
|
||||
///
|
||||
/// If such a panic occurs, any elements previously initialized during this operation will be
|
||||
/// dropped.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Fill an uninit vec with a cycling iterator.
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_fill)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut buf = vec![MaybeUninit::uninit(); 5];
|
||||
///
|
||||
/// let iter = [1, 2, 3].into_iter().cycle();
|
||||
/// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter);
|
||||
///
|
||||
/// assert_eq!(initialized, &mut [1, 2, 3, 1, 2]);
|
||||
/// assert_eq!(0, remainder.len());
|
||||
/// ```
|
||||
///
|
||||
/// Fill an uninit vec, but not completely.
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_fill)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut buf = vec![MaybeUninit::uninit(); 5];
|
||||
/// let iter = [1, 2];
|
||||
/// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter);
|
||||
///
|
||||
/// assert_eq!(initialized, &mut [1, 2]);
|
||||
/// assert_eq!(remainder.len(), 3);
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_fill", issue = "117428")]
|
||||
pub fn fill_from<'a, I>(
|
||||
this: &'a mut [MaybeUninit<T>],
|
||||
it: I,
|
||||
) -> (&'a mut [T], &'a mut [MaybeUninit<T>])
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
{
|
||||
let iter = it.into_iter();
|
||||
let mut guard = Guard { slice: this, initialized: 0 };
|
||||
|
||||
for (element, val) in guard.slice.iter_mut().zip(iter) {
|
||||
element.write(val);
|
||||
guard.initialized += 1;
|
||||
}
|
||||
|
||||
let initialized_len = guard.initialized;
|
||||
super::forget(guard);
|
||||
|
||||
// SAFETY: guard.initialized <= this.len()
|
||||
let (initted, remainder) = unsafe { this.split_at_mut_unchecked(initialized_len) };
|
||||
|
||||
// SAFETY: Valid elements have just been written into `init`, so that portion
|
||||
// of `this` is initialized.
|
||||
(unsafe { MaybeUninit::slice_assume_init_mut(initted) }, remainder)
|
||||
}
|
||||
|
||||
/// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes.
|
||||
///
|
||||
/// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
|
||||
|
|
@ -1329,14 +995,14 @@ impl<T> MaybeUninit<T> {
|
|||
/// let val = 0x12345678_i32;
|
||||
/// let uninit = MaybeUninit::new(val);
|
||||
/// let uninit_bytes = uninit.as_bytes();
|
||||
/// let bytes = unsafe { MaybeUninit::slice_assume_init_ref(uninit_bytes) };
|
||||
/// let bytes = unsafe { uninit_bytes.assume_init_ref() };
|
||||
/// assert_eq!(bytes, val.to_ne_bytes());
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
|
||||
pub fn as_bytes(&self) -> &[MaybeUninit<u8>] {
|
||||
pub const fn as_bytes(&self) -> &[MaybeUninit<u8>] {
|
||||
// SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
|
||||
unsafe {
|
||||
slice::from_raw_parts(self.as_ptr() as *const MaybeUninit<u8>, mem::size_of::<T>())
|
||||
slice::from_raw_parts(self.as_ptr().cast::<MaybeUninit<u8>>(), super::size_of::<T>())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1364,18 +1030,397 @@ impl<T> MaybeUninit<T> {
|
|||
/// assert_eq!(val2, 0x123456cd);
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
|
||||
pub fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
|
||||
pub const fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
|
||||
// SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
self.as_mut_ptr() as *mut MaybeUninit<u8>,
|
||||
mem::size_of::<T>(),
|
||||
self.as_mut_ptr().cast::<MaybeUninit<u8>>(),
|
||||
super::size_of::<T>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the contents of this slice of `MaybeUninit` as a slice of potentially uninitialized
|
||||
/// bytes.
|
||||
/// Deprecated version of [`slice::assume_init_ref`].
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[deprecated(
|
||||
note = "replaced by inherent assume_init_ref method; will eventually be removed",
|
||||
since = "1.83.0"
|
||||
)]
|
||||
pub const unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] {
|
||||
// SAFETY: Same for both methods.
|
||||
unsafe { slice.assume_init_ref() }
|
||||
}
|
||||
|
||||
/// Deprecated version of [`slice::assume_init_mut`].
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[deprecated(
|
||||
note = "replaced by inherent assume_init_mut method; will eventually be removed",
|
||||
since = "1.83.0"
|
||||
)]
|
||||
pub const unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] {
|
||||
// SAFETY: Same for both methods.
|
||||
unsafe { slice.assume_init_mut() }
|
||||
}
|
||||
|
||||
/// Gets a pointer to the first element of the array.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub const fn slice_as_ptr(this: &[MaybeUninit<T>]) -> *const T {
|
||||
this.as_ptr() as *const T
|
||||
}
|
||||
|
||||
/// Gets a mutable pointer to the first element of the array.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub const fn slice_as_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T {
|
||||
this.as_mut_ptr() as *mut T
|
||||
}
|
||||
|
||||
/// Deprecated version of [`slice::write_copy_of_slice`].
|
||||
#[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
|
||||
#[deprecated(
|
||||
note = "replaced by inherent write_copy_of_slice method; will eventually be removed",
|
||||
since = "1.83.0"
|
||||
)]
|
||||
pub fn copy_from_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T]
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
this.write_copy_of_slice(src)
|
||||
}
|
||||
|
||||
/// Deprecated version of [`slice::write_clone_of_slice`].
|
||||
#[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
|
||||
#[deprecated(
|
||||
note = "replaced by inherent write_clone_of_slice method; will eventually be removed",
|
||||
since = "1.83.0"
|
||||
)]
|
||||
pub fn clone_from_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T]
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
this.write_clone_of_slice(src)
|
||||
}
|
||||
|
||||
/// Fills a slice with elements by cloning `value`, returning a mutable reference to the now
|
||||
/// initialized contents of the slice.
|
||||
/// Any previously initialized elements will not be dropped.
|
||||
///
|
||||
/// This is similar to [`slice::fill`].
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if any call to `Clone` panics.
|
||||
///
|
||||
/// If such a panic occurs, any elements previously initialized during this operation will be
|
||||
/// dropped.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_fill)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut buf = [const { MaybeUninit::uninit() }; 10];
|
||||
/// let initialized = MaybeUninit::fill(&mut buf, 1);
|
||||
/// assert_eq!(initialized, &mut [1; 10]);
|
||||
/// ```
|
||||
#[doc(alias = "memset")]
|
||||
#[unstable(feature = "maybe_uninit_fill", issue = "117428")]
|
||||
pub fn fill(this: &mut [MaybeUninit<T>], value: T) -> &mut [T]
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
SpecFill::spec_fill(this, value);
|
||||
// SAFETY: Valid elements have just been filled into `this` so it is initialized
|
||||
unsafe { this.assume_init_mut() }
|
||||
}
|
||||
|
||||
/// Fills a slice with elements returned by calling a closure repeatedly.
|
||||
///
|
||||
/// This method uses a closure to create new values. If you'd rather `Clone` a given value, use
|
||||
/// [`MaybeUninit::fill`]. If you want to use the `Default` trait to generate values, you can
|
||||
/// pass [`Default::default`] as the argument.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if any call to the provided closure panics.
|
||||
///
|
||||
/// If such a panic occurs, any elements previously initialized during this operation will be
|
||||
/// dropped.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_fill)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut buf = [const { MaybeUninit::<i32>::uninit() }; 10];
|
||||
/// let initialized = MaybeUninit::fill_with(&mut buf, Default::default);
|
||||
/// assert_eq!(initialized, &mut [0; 10]);
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_fill", issue = "117428")]
|
||||
pub fn fill_with<F>(this: &mut [MaybeUninit<T>], mut f: F) -> &mut [T]
|
||||
where
|
||||
F: FnMut() -> T,
|
||||
{
|
||||
let mut guard = Guard { slice: this, initialized: 0 };
|
||||
|
||||
for element in guard.slice.iter_mut() {
|
||||
element.write(f());
|
||||
guard.initialized += 1;
|
||||
}
|
||||
|
||||
super::forget(guard);
|
||||
|
||||
// SAFETY: Valid elements have just been written into `this` so it is initialized
|
||||
unsafe { this.assume_init_mut() }
|
||||
}
|
||||
|
||||
/// Fills a slice with elements yielded by an iterator until either all elements have been
|
||||
/// initialized or the iterator is empty.
|
||||
///
|
||||
/// Returns two slices. The first slice contains the initialized portion of the original slice.
|
||||
/// The second slice is the still-uninitialized remainder of the original slice.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if the iterator's `next` function panics.
|
||||
///
|
||||
/// If such a panic occurs, any elements previously initialized during this operation will be
|
||||
/// dropped.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Completely filling the slice:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_fill)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut buf = [const { MaybeUninit::uninit() }; 5];
|
||||
///
|
||||
/// let iter = [1, 2, 3].into_iter().cycle();
|
||||
/// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter);
|
||||
///
|
||||
/// assert_eq!(initialized, &mut [1, 2, 3, 1, 2]);
|
||||
/// assert_eq!(remainder.len(), 0);
|
||||
/// ```
|
||||
///
|
||||
/// Partially filling the slice:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_fill)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut buf = [const { MaybeUninit::uninit() }; 5];
|
||||
/// let iter = [1, 2];
|
||||
/// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter);
|
||||
///
|
||||
/// assert_eq!(initialized, &mut [1, 2]);
|
||||
/// assert_eq!(remainder.len(), 3);
|
||||
/// ```
|
||||
///
|
||||
/// Checking an iterator after filling a slice:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_fill)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut buf = [const { MaybeUninit::uninit() }; 3];
|
||||
/// let mut iter = [1, 2, 3, 4, 5].into_iter();
|
||||
/// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter.by_ref());
|
||||
///
|
||||
/// assert_eq!(initialized, &mut [1, 2, 3]);
|
||||
/// assert_eq!(remainder.len(), 0);
|
||||
/// assert_eq!(iter.as_slice(), &[4, 5]);
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_fill", issue = "117428")]
|
||||
pub fn fill_from<I>(this: &mut [MaybeUninit<T>], it: I) -> (&mut [T], &mut [MaybeUninit<T>])
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
{
|
||||
let iter = it.into_iter();
|
||||
let mut guard = Guard { slice: this, initialized: 0 };
|
||||
|
||||
for (element, val) in guard.slice.iter_mut().zip(iter) {
|
||||
element.write(val);
|
||||
guard.initialized += 1;
|
||||
}
|
||||
|
||||
let initialized_len = guard.initialized;
|
||||
super::forget(guard);
|
||||
|
||||
// SAFETY: guard.initialized <= this.len()
|
||||
let (initted, remainder) = unsafe { this.split_at_mut_unchecked(initialized_len) };
|
||||
|
||||
// SAFETY: Valid elements have just been written into `init`, so that portion
|
||||
// of `this` is initialized.
|
||||
(unsafe { initted.assume_init_mut() }, remainder)
|
||||
}
|
||||
|
||||
/// Deprecated version of [`slice::as_bytes`].
|
||||
#[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
|
||||
#[deprecated(
|
||||
note = "replaced by inherent as_bytes method; will eventually be removed",
|
||||
since = "1.83.0"
|
||||
)]
|
||||
pub fn slice_as_bytes(this: &[MaybeUninit<T>]) -> &[MaybeUninit<u8>] {
|
||||
this.as_bytes()
|
||||
}
|
||||
|
||||
/// Deprecated version of [`slice::as_bytes_mut`].
|
||||
#[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
|
||||
#[deprecated(
|
||||
note = "replaced by inherent as_bytes_mut method; will eventually be removed",
|
||||
since = "1.83.0"
|
||||
)]
|
||||
pub fn slice_as_bytes_mut(this: &mut [MaybeUninit<T>]) -> &mut [MaybeUninit<u8>] {
|
||||
this.as_bytes_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> [MaybeUninit<T>] {
|
||||
/// Copies the elements from `src` to `self`,
|
||||
/// returning a mutable reference to the now initialized contents of `self`.
|
||||
///
|
||||
/// If `T` does not implement `Copy`, use [`write_clone_of_slice`] instead.
|
||||
///
|
||||
/// This is similar to [`slice::copy_from_slice`].
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if the two slices have different lengths.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_write_slice)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut dst = [MaybeUninit::uninit(); 32];
|
||||
/// let src = [0; 32];
|
||||
///
|
||||
/// let init = dst.write_copy_of_slice(&src);
|
||||
///
|
||||
/// assert_eq!(init, src);
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_write_slice)]
|
||||
///
|
||||
/// let mut vec = Vec::with_capacity(32);
|
||||
/// let src = [0; 16];
|
||||
///
|
||||
/// vec.spare_capacity_mut()[..src.len()].write_copy_of_slice(&src);
|
||||
///
|
||||
/// // SAFETY: we have just copied all the elements of len into the spare capacity
|
||||
/// // the first src.len() elements of the vec are valid now.
|
||||
/// unsafe {
|
||||
/// vec.set_len(src.len());
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(vec, src);
|
||||
/// ```
|
||||
///
|
||||
/// [`write_clone_of_slice`]: slice::write_clone_of_slice
|
||||
#[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
|
||||
#[rustc_const_unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
|
||||
pub const fn write_copy_of_slice(&mut self, src: &[T]) -> &mut [T]
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
// SAFETY: &[T] and &[MaybeUninit<T>] have the same layout
|
||||
let uninit_src: &[MaybeUninit<T>] = unsafe { super::transmute(src) };
|
||||
|
||||
self.copy_from_slice(uninit_src);
|
||||
|
||||
// SAFETY: Valid elements have just been copied into `self` so it is initialized
|
||||
unsafe { self.assume_init_mut() }
|
||||
}
|
||||
|
||||
/// Clones the elements from `src` to `self`,
|
||||
/// returning a mutable reference to the now initialized contents of `self`.
|
||||
/// Any already initialized elements will not be dropped.
|
||||
///
|
||||
/// If `T` implements `Copy`, use [`write_copy_of_slice`] instead.
|
||||
///
|
||||
/// This is similar to [`slice::clone_from_slice`] but does not drop existing elements.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if the two slices have different lengths, or if the implementation of `Clone` panics.
|
||||
///
|
||||
/// If there is a panic, the already cloned elements will be dropped.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_write_slice)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut dst = [const { MaybeUninit::uninit() }; 5];
|
||||
/// let src = ["wibbly", "wobbly", "timey", "wimey", "stuff"].map(|s| s.to_string());
|
||||
///
|
||||
/// let init = dst.write_clone_of_slice(&src);
|
||||
///
|
||||
/// assert_eq!(init, src);
|
||||
///
|
||||
/// # // Prevent leaks for Miri
|
||||
/// # unsafe { std::ptr::drop_in_place(init); }
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_write_slice)]
|
||||
///
|
||||
/// let mut vec = Vec::with_capacity(32);
|
||||
/// let src = ["rust", "is", "a", "pretty", "cool", "language"].map(|s| s.to_string());
|
||||
///
|
||||
/// vec.spare_capacity_mut()[..src.len()].write_clone_of_slice(&src);
|
||||
///
|
||||
/// // SAFETY: we have just cloned all the elements of len into the spare capacity
|
||||
/// // the first src.len() elements of the vec are valid now.
|
||||
/// unsafe {
|
||||
/// vec.set_len(src.len());
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(vec, src);
|
||||
/// ```
|
||||
///
|
||||
/// [`write_copy_of_slice`]: slice::write_copy_of_slice
|
||||
#[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
|
||||
pub fn write_clone_of_slice(&mut self, src: &[T]) -> &mut [T]
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
// unlike copy_from_slice this does not call clone_from_slice on the slice
|
||||
// this is because `MaybeUninit<T: Clone>` does not implement Clone.
|
||||
|
||||
assert_eq!(self.len(), src.len(), "destination and source slices have different lengths");
|
||||
|
||||
// NOTE: We need to explicitly slice them to the same length
|
||||
// for bounds checking to be elided, and the optimizer will
|
||||
// generate memcpy for simple cases (for example T = u8).
|
||||
let len = self.len();
|
||||
let src = &src[..len];
|
||||
|
||||
// guard is needed b/c panic might happen during a clone
|
||||
let mut guard = Guard { slice: self, initialized: 0 };
|
||||
|
||||
for i in 0..len {
|
||||
guard.slice[i].write(src[i].clone());
|
||||
guard.initialized += 1;
|
||||
}
|
||||
|
||||
super::forget(guard);
|
||||
|
||||
// SAFETY: Valid elements have just been written into `self` so it is initialized
|
||||
unsafe { self.assume_init_mut() }
|
||||
}
|
||||
|
||||
/// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes.
|
||||
///
|
||||
/// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
|
||||
/// contain padding bytes which are left uninitialized.
|
||||
|
|
@ -1387,21 +1432,22 @@ impl<T> MaybeUninit<T> {
|
|||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let uninit = [MaybeUninit::new(0x1234u16), MaybeUninit::new(0x5678u16)];
|
||||
/// let uninit_bytes = MaybeUninit::slice_as_bytes(&uninit);
|
||||
/// let bytes = unsafe { MaybeUninit::slice_assume_init_ref(&uninit_bytes) };
|
||||
/// let uninit_bytes = uninit.as_bytes();
|
||||
/// let bytes = unsafe { uninit_bytes.assume_init_ref() };
|
||||
/// let val1 = u16::from_ne_bytes(bytes[0..2].try_into().unwrap());
|
||||
/// let val2 = u16::from_ne_bytes(bytes[2..4].try_into().unwrap());
|
||||
/// assert_eq!(&[val1, val2], &[0x1234u16, 0x5678u16]);
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
|
||||
pub fn slice_as_bytes(this: &[MaybeUninit<T>]) -> &[MaybeUninit<u8>] {
|
||||
let bytes = mem::size_of_val(this);
|
||||
pub const fn as_bytes(&self) -> &[MaybeUninit<u8>] {
|
||||
// SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
|
||||
unsafe { slice::from_raw_parts(this.as_ptr() as *const MaybeUninit<u8>, bytes) }
|
||||
unsafe {
|
||||
slice::from_raw_parts(self.as_ptr().cast::<MaybeUninit<u8>>(), super::size_of_val(self))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the contents of this mutable slice of `MaybeUninit` as a mutable slice of
|
||||
/// potentially uninitialized bytes.
|
||||
/// Returns the contents of this `MaybeUninit` slice as a mutable slice of potentially
|
||||
/// uninitialized bytes.
|
||||
///
|
||||
/// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
|
||||
/// contain padding bytes which are left uninitialized.
|
||||
|
|
@ -1414,8 +1460,8 @@ impl<T> MaybeUninit<T> {
|
|||
///
|
||||
/// let mut uninit = [MaybeUninit::<u16>::uninit(), MaybeUninit::<u16>::uninit()];
|
||||
/// let uninit_bytes = MaybeUninit::slice_as_bytes_mut(&mut uninit);
|
||||
/// MaybeUninit::copy_from_slice(uninit_bytes, &[0x12, 0x34, 0x56, 0x78]);
|
||||
/// let vals = unsafe { MaybeUninit::slice_assume_init_ref(&uninit) };
|
||||
/// uninit_bytes.write_copy_of_slice(&[0x12, 0x34, 0x56, 0x78]);
|
||||
/// let vals = unsafe { uninit.assume_init_ref() };
|
||||
/// if cfg!(target_endian = "little") {
|
||||
/// assert_eq!(vals, &[0x3412u16, 0x7856u16]);
|
||||
/// } else {
|
||||
|
|
@ -1423,10 +1469,74 @@ impl<T> MaybeUninit<T> {
|
|||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
|
||||
pub fn slice_as_bytes_mut(this: &mut [MaybeUninit<T>]) -> &mut [MaybeUninit<u8>] {
|
||||
let bytes = mem::size_of_val(this);
|
||||
pub const fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
|
||||
// SAFETY: MaybeUninit<u8> is always valid, even for padding bytes
|
||||
unsafe { slice::from_raw_parts_mut(this.as_mut_ptr() as *mut MaybeUninit<u8>, bytes) }
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
self.as_mut_ptr() as *mut MaybeUninit<u8>,
|
||||
super::size_of_val(self),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Drops the contained values in place.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee that every `MaybeUninit<T>` in the slice
|
||||
/// really is in an initialized state. Calling this when the content is not yet
|
||||
/// fully initialized causes undefined behavior.
|
||||
///
|
||||
/// On top of that, all additional invariants of the type `T` must be
|
||||
/// satisfied, as the `Drop` implementation of `T` (or its members) may
|
||||
/// rely on this. For example, setting a `Vec<T>` to an invalid but
|
||||
/// non-null address makes it initialized (under the current implementation;
|
||||
/// this does not constitute a stable guarantee), because the only
|
||||
/// requirement the compiler knows about it is that the data pointer must be
|
||||
/// non-null. Dropping such a `Vec<T>` however will cause undefined
|
||||
/// behaviour.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub unsafe fn assume_init_drop(&mut self) {
|
||||
if !self.is_empty() {
|
||||
// SAFETY: the caller must guarantee that every element of `self`
|
||||
// is initialized and satisfies all invariants of `T`.
|
||||
// Dropping the value in place is safe if that is the case.
|
||||
unsafe { ptr::drop_in_place(self as *mut [MaybeUninit<T>] as *mut [T]) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a shared reference to the contained value.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Calling this when the content is not yet fully initialized causes undefined
|
||||
/// behavior: it is up to the caller to guarantee that every `MaybeUninit<T>` in
|
||||
/// the slice really is in an initialized state.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub const unsafe fn assume_init_ref(&self) -> &[T] {
|
||||
// SAFETY: casting `slice` to a `*const [T]` is safe since the caller guarantees that
|
||||
// `slice` is initialized, and `MaybeUninit` is guaranteed to have the same layout as `T`.
|
||||
// The pointer obtained is valid since it refers to memory owned by `slice` which is a
|
||||
// reference and thus guaranteed to be valid for reads.
|
||||
unsafe { &*(self as *const Self as *const [T]) }
|
||||
}
|
||||
|
||||
/// Gets a mutable (unique) reference to the contained value.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Calling this when the content is not yet fully initialized causes undefined
|
||||
/// behavior: it is up to the caller to guarantee that every `MaybeUninit<T>` in the
|
||||
/// slice really is in an initialized state. For instance, `.assume_init_mut()` cannot
|
||||
/// be used to initialize a `MaybeUninit` slice.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub const unsafe fn assume_init_mut(&mut self) -> &mut [T] {
|
||||
// SAFETY: similar to safety notes for `slice_get_ref`, but we have a
|
||||
// mutable reference which is also guaranteed to be valid for writes.
|
||||
unsafe { &mut *(self as *mut Self as *mut [T]) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1479,7 +1589,7 @@ impl<'a, T> Drop for Guard<'a, T> {
|
|||
let initialized_part = &mut self.slice[..self.initialized];
|
||||
// SAFETY: this raw sub-slice will contain only initialized objects.
|
||||
unsafe {
|
||||
crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(initialized_part));
|
||||
initialized_part.assume_init_drop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ impl<const SIZE: usize> DisplayBuffer<SIZE> {
|
|||
// SAFETY: `buf` is only written to by the `fmt::Write::write_str` implementation
|
||||
// which writes a valid UTF-8 string to `buf` and correctly sets `len`.
|
||||
unsafe {
|
||||
let s = MaybeUninit::slice_assume_init_ref(&self.buf[..self.len]);
|
||||
let s = self.buf[..self.len].assume_init_ref();
|
||||
str::from_utf8_unchecked(s)
|
||||
}
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ impl<const SIZE: usize> fmt::Write for DisplayBuffer<SIZE> {
|
|||
let bytes = s.as_bytes();
|
||||
|
||||
if let Some(buf) = self.buf.get_mut(self.len..(self.len + bytes.len())) {
|
||||
MaybeUninit::copy_from_slice(buf, bytes);
|
||||
buf.write_copy_of_slice(bytes);
|
||||
self.len += bytes.len();
|
||||
Ok(())
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -210,10 +210,10 @@ fn digits_to_dec_str<'a>(
|
|||
if frac_digits > buf.len() && frac_digits - buf.len() > minus_exp {
|
||||
parts[3] = MaybeUninit::new(Part::Zero((frac_digits - buf.len()) - minus_exp));
|
||||
// SAFETY: we just initialized the elements `..4`.
|
||||
unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) }
|
||||
unsafe { parts[..4].assume_init_ref() }
|
||||
} else {
|
||||
// SAFETY: we just initialized the elements `..3`.
|
||||
unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) }
|
||||
unsafe { parts[..3].assume_init_ref() }
|
||||
}
|
||||
} else {
|
||||
let exp = exp as usize;
|
||||
|
|
@ -225,10 +225,10 @@ fn digits_to_dec_str<'a>(
|
|||
if frac_digits > buf.len() - exp {
|
||||
parts[3] = MaybeUninit::new(Part::Zero(frac_digits - (buf.len() - exp)));
|
||||
// SAFETY: we just initialized the elements `..4`.
|
||||
unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) }
|
||||
unsafe { parts[..4].assume_init_ref() }
|
||||
} else {
|
||||
// SAFETY: we just initialized the elements `..3`.
|
||||
unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) }
|
||||
unsafe { parts[..3].assume_init_ref() }
|
||||
}
|
||||
} else {
|
||||
// the decimal point is after rendered digits: [1234][____0000] or [1234][__][.][__].
|
||||
|
|
@ -238,10 +238,10 @@ fn digits_to_dec_str<'a>(
|
|||
parts[2] = MaybeUninit::new(Part::Copy(b"."));
|
||||
parts[3] = MaybeUninit::new(Part::Zero(frac_digits));
|
||||
// SAFETY: we just initialized the elements `..4`.
|
||||
unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) }
|
||||
unsafe { parts[..4].assume_init_ref() }
|
||||
} else {
|
||||
// SAFETY: we just initialized the elements `..2`.
|
||||
unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) }
|
||||
unsafe { parts[..2].assume_init_ref() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -292,7 +292,7 @@ fn digits_to_exp_str<'a>(
|
|||
parts[n + 1] = MaybeUninit::new(Part::Num(exp as u16));
|
||||
}
|
||||
// SAFETY: we just initialized the elements `..n + 2`.
|
||||
unsafe { MaybeUninit::slice_assume_init_ref(&parts[..n + 2]) }
|
||||
unsafe { parts[..n + 2].assume_init_ref() }
|
||||
}
|
||||
|
||||
/// Sign formatting options.
|
||||
|
|
@ -366,12 +366,12 @@ where
|
|||
FullDecoded::Nan => {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
|
||||
}
|
||||
FullDecoded::Infinite => {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
|
||||
}
|
||||
FullDecoded::Zero => {
|
||||
if frac_digits > 0 {
|
||||
|
|
@ -381,14 +381,14 @@ where
|
|||
Formatted {
|
||||
sign,
|
||||
// SAFETY: we just initialized the elements `..2`.
|
||||
parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) },
|
||||
parts: unsafe { parts[..2].assume_init_ref() },
|
||||
}
|
||||
} else {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"0"));
|
||||
Formatted {
|
||||
sign,
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) },
|
||||
parts: unsafe { parts[..1].assume_init_ref() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -442,12 +442,12 @@ where
|
|||
FullDecoded::Nan => {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
|
||||
}
|
||||
FullDecoded::Infinite => {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
|
||||
}
|
||||
FullDecoded::Zero => {
|
||||
parts[0] = if dec_bounds.0 <= 0 && 0 < dec_bounds.1 {
|
||||
|
|
@ -456,7 +456,7 @@ where
|
|||
MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" }))
|
||||
};
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
|
||||
}
|
||||
FullDecoded::Finite(ref decoded) => {
|
||||
let (buf, exp) = format_shortest(decoded, buf);
|
||||
|
|
@ -533,12 +533,12 @@ where
|
|||
FullDecoded::Nan => {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
|
||||
}
|
||||
FullDecoded::Infinite => {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
|
||||
}
|
||||
FullDecoded::Zero => {
|
||||
if ndigits > 1 {
|
||||
|
|
@ -549,14 +549,14 @@ where
|
|||
Formatted {
|
||||
sign,
|
||||
// SAFETY: we just initialized the elements `..3`.
|
||||
parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) },
|
||||
parts: unsafe { parts[..3].assume_init_ref() },
|
||||
}
|
||||
} else {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" }));
|
||||
Formatted {
|
||||
sign,
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) },
|
||||
parts: unsafe { parts[..1].assume_init_ref() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -607,12 +607,12 @@ where
|
|||
FullDecoded::Nan => {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
|
||||
}
|
||||
FullDecoded::Infinite => {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
|
||||
}
|
||||
FullDecoded::Zero => {
|
||||
if frac_digits > 0 {
|
||||
|
|
@ -622,14 +622,14 @@ where
|
|||
Formatted {
|
||||
sign,
|
||||
// SAFETY: we just initialized the elements `..2`.
|
||||
parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) },
|
||||
parts: unsafe { parts[..2].assume_init_ref() },
|
||||
}
|
||||
} else {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"0"));
|
||||
Formatted {
|
||||
sign,
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) },
|
||||
parts: unsafe { parts[..1].assume_init_ref() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -654,14 +654,14 @@ where
|
|||
Formatted {
|
||||
sign,
|
||||
// SAFETY: we just initialized the elements `..2`.
|
||||
parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) },
|
||||
parts: unsafe { parts[..2].assume_init_ref() },
|
||||
}
|
||||
} else {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"0"));
|
||||
Formatted {
|
||||
sign,
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) },
|
||||
parts: unsafe { parts[..1].assume_init_ref() },
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ pub fn format_shortest<'a>(
|
|||
// it seems that this condition is very hard to satisfy (possibly impossible),
|
||||
// but we are just being safe and consistent here.
|
||||
// SAFETY: we initialized that memory above.
|
||||
if let Some(c) = round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) }) {
|
||||
if let Some(c) = round_up(unsafe { buf[..i].assume_init_mut() }) {
|
||||
buf[i] = MaybeUninit::new(c);
|
||||
i += 1;
|
||||
k += 1;
|
||||
|
|
@ -255,7 +255,7 @@ pub fn format_shortest<'a>(
|
|||
}
|
||||
|
||||
// SAFETY: we initialized that memory above.
|
||||
(unsafe { MaybeUninit::slice_assume_init_ref(&buf[..i]) }, k)
|
||||
(unsafe { buf[..i].assume_init_ref() }, k)
|
||||
}
|
||||
|
||||
/// The exact and fixed mode implementation for Dragon.
|
||||
|
|
@ -333,7 +333,7 @@ pub fn format_exact<'a>(
|
|||
*c = MaybeUninit::new(b'0');
|
||||
}
|
||||
// SAFETY: we initialized that memory above.
|
||||
return (unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, k);
|
||||
return (unsafe { buf[..len].assume_init_ref() }, k);
|
||||
}
|
||||
|
||||
let mut d = 0;
|
||||
|
|
@ -372,7 +372,7 @@ pub fn format_exact<'a>(
|
|||
// if rounding up changes the length, the exponent should also change.
|
||||
// but we've been requested a fixed number of digits, so do not alter the buffer...
|
||||
// SAFETY: we initialized that memory above.
|
||||
if let Some(c) = round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..len]) }) {
|
||||
if let Some(c) = round_up(unsafe { buf[..len].assume_init_mut() }) {
|
||||
// ...unless we've been requested the fixed precision instead.
|
||||
// we also need to check that, if the original buffer was empty,
|
||||
// the additional digit can only be added when `k == limit` (edge case).
|
||||
|
|
@ -385,5 +385,5 @@ pub fn format_exact<'a>(
|
|||
}
|
||||
|
||||
// SAFETY: we initialized that memory above.
|
||||
(unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, k)
|
||||
(unsafe { buf[..len].assume_init_ref() }, k)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ pub fn format_shortest_opt<'a>(
|
|||
let ten_kappa = (ten_kappa as u64) << e; // scale 10^kappa back to the shared exponent
|
||||
return round_and_weed(
|
||||
// SAFETY: we initialized that memory above.
|
||||
unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) },
|
||||
unsafe { buf[..i].assume_init_mut() },
|
||||
exp,
|
||||
plus1rem,
|
||||
delta1,
|
||||
|
|
@ -324,7 +324,7 @@ pub fn format_shortest_opt<'a>(
|
|||
let ten_kappa = 1 << e; // implicit divisor
|
||||
return round_and_weed(
|
||||
// SAFETY: we initialized that memory above.
|
||||
unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) },
|
||||
unsafe { buf[..i].assume_init_mut() },
|
||||
exp,
|
||||
r,
|
||||
threshold,
|
||||
|
|
@ -713,7 +713,7 @@ pub fn format_exact_opt<'a>(
|
|||
// `10^kappa` did not overflow after all, the second check is fine.
|
||||
if ten_kappa - remainder > remainder && ten_kappa - 2 * remainder >= 2 * ulp {
|
||||
// SAFETY: our caller initialized that memory.
|
||||
return Some((unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, exp));
|
||||
return Some((unsafe { buf[..len].assume_init_ref() }, exp));
|
||||
}
|
||||
|
||||
// :<------- remainder ------>| :
|
||||
|
|
@ -736,7 +736,7 @@ pub fn format_exact_opt<'a>(
|
|||
if remainder > ulp && ten_kappa - (remainder - ulp) <= remainder - ulp {
|
||||
if let Some(c) =
|
||||
// SAFETY: our caller must have initialized that memory.
|
||||
round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..len]) })
|
||||
round_up(unsafe { buf[..len].assume_init_mut() })
|
||||
{
|
||||
// only add an additional digit when we've been requested the fixed precision.
|
||||
// we also need to check that, if the original buffer was empty,
|
||||
|
|
@ -748,7 +748,7 @@ pub fn format_exact_opt<'a>(
|
|||
}
|
||||
}
|
||||
// SAFETY: we and our caller initialized that memory.
|
||||
return Some((unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, exp));
|
||||
return Some((unsafe { buf[..len].assume_init_ref() }, exp));
|
||||
}
|
||||
|
||||
// otherwise we are doomed (i.e., some values between `v - 1 ulp` and `v + 1 ulp` are
|
||||
|
|
|
|||
|
|
@ -200,60 +200,60 @@ fn uninit_array_assume_init() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn uninit_write_slice() {
|
||||
fn uninit_write_copy_of_slice() {
|
||||
let mut dst = [MaybeUninit::new(255); 64];
|
||||
let src = [0; 64];
|
||||
|
||||
assert_eq!(MaybeUninit::copy_from_slice(&mut dst, &src), &src);
|
||||
assert_eq!(dst.write_copy_of_slice(&src), &src);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "source slice length (32) does not match destination slice length (64)")]
|
||||
fn uninit_write_slice_panic_lt() {
|
||||
fn uninit_write_copy_of_slice_panic_lt() {
|
||||
let mut dst = [MaybeUninit::uninit(); 64];
|
||||
let src = [0; 32];
|
||||
|
||||
MaybeUninit::copy_from_slice(&mut dst, &src);
|
||||
dst.write_copy_of_slice(&src);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "source slice length (128) does not match destination slice length (64)")]
|
||||
fn uninit_write_slice_panic_gt() {
|
||||
fn uninit_write_copy_of_slice_panic_gt() {
|
||||
let mut dst = [MaybeUninit::uninit(); 64];
|
||||
let src = [0; 128];
|
||||
|
||||
MaybeUninit::copy_from_slice(&mut dst, &src);
|
||||
dst.write_copy_of_slice(&src);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uninit_clone_from_slice() {
|
||||
fn uninit_write_clone_of_slice() {
|
||||
let mut dst = [MaybeUninit::new(255); 64];
|
||||
let src = [0; 64];
|
||||
|
||||
assert_eq!(MaybeUninit::clone_from_slice(&mut dst, &src), &src);
|
||||
assert_eq!(dst.write_clone_of_slice(&src), &src);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "destination and source slices have different lengths")]
|
||||
fn uninit_write_slice_cloned_panic_lt() {
|
||||
fn uninit_write_clone_of_slice_panic_lt() {
|
||||
let mut dst = [MaybeUninit::uninit(); 64];
|
||||
let src = [0; 32];
|
||||
|
||||
MaybeUninit::clone_from_slice(&mut dst, &src);
|
||||
dst.write_clone_of_slice(&src);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "destination and source slices have different lengths")]
|
||||
fn uninit_write_slice_cloned_panic_gt() {
|
||||
fn uninit_write_clone_of_slice_panic_gt() {
|
||||
let mut dst = [MaybeUninit::uninit(); 64];
|
||||
let src = [0; 128];
|
||||
|
||||
MaybeUninit::clone_from_slice(&mut dst, &src);
|
||||
dst.write_clone_of_slice(&src);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(panic = "unwind")]
|
||||
fn uninit_write_slice_cloned_mid_panic() {
|
||||
fn uninit_write_clone_of_slice_mid_panic() {
|
||||
use std::panic;
|
||||
|
||||
enum IncrementOrPanic {
|
||||
|
|
@ -289,7 +289,7 @@ fn uninit_write_slice_cloned_mid_panic() {
|
|||
];
|
||||
|
||||
let err = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
MaybeUninit::clone_from_slice(&mut dst, &src);
|
||||
dst.write_clone_of_slice(&src);
|
||||
}));
|
||||
|
||||
drop(src);
|
||||
|
|
@ -317,11 +317,11 @@ impl Drop for Bomb {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn uninit_write_slice_cloned_no_drop() {
|
||||
fn uninit_write_clone_of_slice_no_drop() {
|
||||
let mut dst = [MaybeUninit::uninit()];
|
||||
let src = [Bomb];
|
||||
|
||||
MaybeUninit::clone_from_slice(&mut dst, &src);
|
||||
dst.write_clone_of_slice(&src);
|
||||
|
||||
forget(src);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ impl Arena {
|
|||
#[allow(clippy::mut_from_ref)] // arena allocator
|
||||
pub(crate) fn alloc_str<'a>(&'a self, string: &str) -> &'a mut str {
|
||||
let alloc = self.alloc_raw(string.len());
|
||||
let bytes = MaybeUninit::copy_from_slice(alloc, string.as_bytes());
|
||||
let bytes = alloc.write_copy_of_slice(string.as_bytes());
|
||||
|
||||
// SAFETY: we convert from `&str` to `&[u8]`, clone it into the arena,
|
||||
// and immediately convert the clone back to `&str`.
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ fn clone_to_uninit() {
|
|||
|
||||
let mut storage = vec![MaybeUninit::<u8>::uninit(); size_of_val::<OsStr>(a)];
|
||||
unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()).cast()) };
|
||||
assert_eq!(a.as_encoded_bytes(), unsafe { MaybeUninit::slice_assume_init_ref(&storage) });
|
||||
assert_eq!(a.as_encoded_bytes(), unsafe { storage.assume_init_ref() });
|
||||
|
||||
let mut b: Box<OsStr> = OsStr::new("world.exe").into();
|
||||
assert_eq!(size_of_val::<OsStr>(a), size_of_val::<OsStr>(&b));
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ impl Buffer {
|
|||
pub fn buffer(&self) -> &[u8] {
|
||||
// SAFETY: self.pos and self.cap are valid, and self.cap => self.pos, and
|
||||
// that region is initialized because those are all invariants of this type.
|
||||
unsafe { MaybeUninit::slice_assume_init_ref(self.buf.get_unchecked(self.pos..self.filled)) }
|
||||
unsafe { self.buf.get_unchecked(self.pos..self.filled).assume_init_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -2069,9 +2069,7 @@ fn clone_to_uninit() {
|
|||
|
||||
let mut storage = vec![MaybeUninit::<u8>::uninit(); size_of_val::<Path>(a)];
|
||||
unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()).cast()) };
|
||||
assert_eq!(a.as_os_str().as_encoded_bytes(), unsafe {
|
||||
MaybeUninit::slice_assume_init_ref(&storage)
|
||||
});
|
||||
assert_eq!(a.as_os_str().as_encoded_bytes(), unsafe { storage.assume_init_ref() });
|
||||
|
||||
let mut b: Box<Path> = Path::new("world.exe").into();
|
||||
assert_eq!(size_of_val::<Path>(a), size_of_val::<Path>(&b));
|
||||
|
|
|
|||
|
|
@ -272,7 +272,7 @@ where
|
|||
unreachable!();
|
||||
} else {
|
||||
// Safety: First `k` values are initialized.
|
||||
let slice: &[u16] = MaybeUninit::slice_assume_init_ref(&buf[..k]);
|
||||
let slice: &[u16] = buf[..k].assume_init_ref();
|
||||
return Ok(f2(slice));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result<usiz
|
|||
assert!(result != 0, "Unexpected error in MultiByteToWideChar");
|
||||
|
||||
// Safety: MultiByteToWideChar initializes `result` values.
|
||||
MaybeUninit::slice_assume_init_ref(&utf16[..result as usize])
|
||||
utf16[..result as usize].assume_init_ref()
|
||||
};
|
||||
|
||||
let mut written = write_u16s(handle, utf16)?;
|
||||
|
|
@ -283,7 +283,7 @@ impl io::Read for Stdin {
|
|||
let read = read_u16s_fixup_surrogates(handle, &mut utf16_buf, 1, &mut self.surrogate)?;
|
||||
// Read bytes, using the (now-empty) self.incomplete_utf8 as extra space.
|
||||
let read_bytes = utf16_to_utf8(
|
||||
unsafe { MaybeUninit::slice_assume_init_ref(&utf16_buf[..read]) },
|
||||
unsafe { utf16_buf[..read].assume_init_ref() },
|
||||
&mut self.incomplete_utf8.bytes,
|
||||
)?;
|
||||
|
||||
|
|
@ -303,7 +303,7 @@ impl io::Read for Stdin {
|
|||
read_u16s_fixup_surrogates(handle, &mut utf16_buf, amount, &mut self.surrogate)?;
|
||||
// Safety `read_u16s_fixup_surrogates` returns the number of items
|
||||
// initialized.
|
||||
let utf16s = unsafe { MaybeUninit::slice_assume_init_ref(&utf16_buf[..read]) };
|
||||
let utf16s = unsafe { utf16_buf[..read].assume_init_ref() };
|
||||
match utf16_to_utf8(utf16s, buf) {
|
||||
Ok(value) => return Ok(bytes_copied + value),
|
||||
Err(e) => return Err(e),
|
||||
|
|
|
|||
|
|
@ -39,18 +39,22 @@ macro_rules! string_enum {
|
|||
}
|
||||
|
||||
impl FromStr for $name {
|
||||
type Err = ();
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, ()> {
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
$($repr => Ok(Self::$variant),)*
|
||||
_ => Err(()),
|
||||
_ => Err(format!(concat!("unknown `", stringify!($name), "` variant: `{}`"), s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make the macro visible outside of this module, for tests.
|
||||
#[cfg(test)]
|
||||
pub(crate) use string_enum;
|
||||
|
||||
string_enum! {
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub enum Mode {
|
||||
|
|
|
|||
|
|
@ -66,3 +66,30 @@ fn is_test_test() {
|
|||
assert!(!is_test(&OsString::from("#a_dog_gif")));
|
||||
assert!(!is_test(&OsString::from("~a_temp_file")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_enums() {
|
||||
// These imports are needed for the macro-generated code
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
crate::common::string_enum! {
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
enum Animal {
|
||||
Cat => "meow",
|
||||
Dog => "woof",
|
||||
}
|
||||
}
|
||||
|
||||
// General assertions, mostly to silence the dead code warnings
|
||||
assert_eq!(Animal::VARIANTS.len(), 2);
|
||||
assert_eq!(Animal::STR_VARIANTS.len(), 2);
|
||||
|
||||
// Correct string conversions
|
||||
assert_eq!(Animal::Cat, "meow".parse().unwrap());
|
||||
assert_eq!(Animal::Dog, "woof".parse().unwrap());
|
||||
|
||||
// Invalid conversions
|
||||
let animal = "nya".parse::<Animal>();
|
||||
assert_eq!("unknown `Animal` variant: `nya`", animal.unwrap_err());
|
||||
}
|
||||
|
|
|
|||
24
tests/crashes/135122.rs
Normal file
24
tests/crashes/135122.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
//@ known-bug: #135122
|
||||
trait Add {
|
||||
type Output;
|
||||
fn add(_: (), _: Self::Output) {}
|
||||
}
|
||||
|
||||
trait IsSame<Lhs> {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
trait Data {
|
||||
type Elem;
|
||||
}
|
||||
|
||||
impl<B> IsSame<i16> for f32 where f32: IsSame<B, Assoc = B> {}
|
||||
|
||||
impl<A> Add for i64
|
||||
where
|
||||
f32: IsSame<A>,
|
||||
i8: Data<Elem = A>,
|
||||
{
|
||||
type Output = <f32 as IsSame<A>>::Assoc;
|
||||
fn add(_: Data, _: Self::Output) {}
|
||||
}
|
||||
9
tests/crashes/135124.rs
Normal file
9
tests/crashes/135124.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
//@ known-bug: #135124
|
||||
trait A {
|
||||
fn y(&self)
|
||||
{
|
||||
fn call() -> impl Sized {}
|
||||
self.fold(call());
|
||||
}
|
||||
fn fold(&self, &self._) {}
|
||||
}
|
||||
10
tests/crashes/135128.rs
Normal file
10
tests/crashes/135128.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
//@ known-bug: #135128
|
||||
//@ compile-flags: -Copt-level=1 --edition=2021
|
||||
|
||||
async fn return_str() -> str
|
||||
where
|
||||
str: Sized,
|
||||
{
|
||||
*"Sized".to_string().into_boxed_str()
|
||||
}
|
||||
fn main() {}
|
||||
8
tests/crashes/135210.rs
Normal file
8
tests/crashes/135210.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
//@ known-bug: #135210
|
||||
|
||||
#![feature(const_trait_impl)]
|
||||
const _: fn(&String) = |s| {
|
||||
&*s as &str;
|
||||
};
|
||||
|
||||
fn main() {}
|
||||
5
tests/crashes/135341.rs
Normal file
5
tests/crashes/135341.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
//@ known-bug: #135341
|
||||
type A<T> = B;
|
||||
type B = _;
|
||||
|
||||
pub fn main() {}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
- // MIR for `impossible_predicate` before ImpossiblePredicates
|
||||
+ // MIR for `impossible_predicate` after ImpossiblePredicates
|
||||
|
||||
fn impossible_predicate(_1: &mut i32) -> (&mut i32, &mut i32) {
|
||||
- debug x => _1;
|
||||
let mut _0: (&mut i32, &mut i32);
|
||||
- let _2: &mut i32;
|
||||
- let mut _3: &mut i32;
|
||||
- let mut _4: &mut i32;
|
||||
scope 1 {
|
||||
- debug y => _2;
|
||||
}
|
||||
|
||||
bb0: {
|
||||
- StorageLive(_2);
|
||||
- _2 = copy _1;
|
||||
- FakeRead(ForLet(None), _2);
|
||||
- StorageLive(_3);
|
||||
- _3 = &mut (*_2);
|
||||
- StorageLive(_4);
|
||||
- _4 = &mut (*_1);
|
||||
- _0 = (move _3, move _4);
|
||||
- StorageDead(_4);
|
||||
- StorageDead(_3);
|
||||
- StorageDead(_2);
|
||||
- return;
|
||||
+ unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
10
tests/mir-opt/impossible_predicates.rs
Normal file
10
tests/mir-opt/impossible_predicates.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// skip-filecheck
|
||||
// EMIT_MIR impossible_predicates.impossible_predicate.ImpossiblePredicates.diff
|
||||
|
||||
pub fn impossible_predicate(x: &mut i32) -> (&mut i32, &mut i32)
|
||||
where
|
||||
for<'a> &'a mut i32: Copy,
|
||||
{
|
||||
let y = x;
|
||||
(y, x)
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ fn f<T>(
|
|||
}],
|
||||
) -> impl Iterator<Item = SubAssign> {
|
||||
//~^ ERROR expected a type, found a trait
|
||||
//~| ERROR expected a type, found a trait
|
||||
//~| ERROR `()` is not an iterator
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,14 +16,6 @@ help: you might be missing a type parameter
|
|||
LL | fn f<T, F>(
|
||||
| +++
|
||||
|
||||
error[E0277]: `()` is not an iterator
|
||||
--> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:6
|
||||
|
|
||||
LL | ) -> impl Iterator<Item = SubAssign> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
|
||||
|
|
||||
= help: the trait `Iterator` is not implemented for `()`
|
||||
|
||||
error[E0782]: expected a type, found a trait
|
||||
--> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:27
|
||||
|
|
||||
|
|
@ -39,7 +31,31 @@ help: you might have meant to write a bound here
|
|||
LL | ) -> impl Iterator<Item: SubAssign> {
|
||||
| ~
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error[E0782]: expected a type, found a trait
|
||||
--> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:27
|
||||
|
|
||||
LL | ) -> impl Iterator<Item = SubAssign> {
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
help: you can add the `dyn` keyword if you want a trait object
|
||||
|
|
||||
LL | ) -> impl Iterator<Item = dyn SubAssign> {
|
||||
| +++
|
||||
help: you might have meant to write a bound here
|
||||
|
|
||||
LL | ) -> impl Iterator<Item: SubAssign> {
|
||||
| ~
|
||||
|
||||
error[E0277]: `()` is not an iterator
|
||||
--> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:6
|
||||
|
|
||||
LL | ) -> impl Iterator<Item = SubAssign> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
|
||||
|
|
||||
= help: the trait `Iterator` is not implemented for `()`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0412, E0782.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
12
tests/ui/dyn-keyword/misspelled-associated-item.rs
Normal file
12
tests/ui/dyn-keyword/misspelled-associated-item.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
//@ edition: 2021
|
||||
|
||||
trait Trait {
|
||||
fn typo() -> Self;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let () = Trait::typoe();
|
||||
//~^ ERROR expected a type, found a trait
|
||||
//~| HELP you can add the `dyn` keyword if you want a trait object
|
||||
//~| HELP you may have misspelled this associated item
|
||||
}
|
||||
18
tests/ui/dyn-keyword/misspelled-associated-item.stderr
Normal file
18
tests/ui/dyn-keyword/misspelled-associated-item.stderr
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
error[E0782]: expected a type, found a trait
|
||||
--> $DIR/misspelled-associated-item.rs:8:14
|
||||
|
|
||||
LL | let () = Trait::typoe();
|
||||
| ^^^^^
|
||||
|
|
||||
help: you can add the `dyn` keyword if you want a trait object
|
||||
|
|
||||
LL | let () = <dyn Trait>::typoe();
|
||||
| ++++ +
|
||||
help: you may have misspelled this associated item, causing `Trait` to be interpreted as a type rather than a trait
|
||||
|
|
||||
LL | let () = Trait::typo();
|
||||
| ~~~~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0782`.
|
||||
|
|
@ -9,6 +9,18 @@ help: you can add the `dyn` keyword if you want a trait object
|
|||
LL | fn ice() -> impl AsRef<dyn Fn(&())> {
|
||||
| +++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error[E0782]: expected a type, found a trait
|
||||
--> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:24
|
||||
|
|
||||
LL | fn ice() -> impl AsRef<Fn(&())> {
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
help: you can add the `dyn` keyword if you want a trait object
|
||||
|
|
||||
LL | fn ice() -> impl AsRef<dyn Fn(&())> {
|
||||
| +++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0782`.
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
fn ice() -> impl AsRef<Fn(&())> {
|
||||
//[edition2015]~^ ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277]
|
||||
//[edition2021]~^^ ERROR: expected a type, found a trait [E0782]
|
||||
//[edition2021]~| ERROR: expected a type, found a trait [E0782]
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
error[E0792]: expected generic type parameter, found `i32`
|
||||
--> $DIR/issue-99073-2.rs:9:22
|
||||
|
|
||||
LL | fn test<T: Display>(t: T, recurse: bool) -> impl Display {
|
||||
| - this generic parameter must be used with a generic type parameter
|
||||
LL | let f = || {
|
||||
LL | let i: u32 = test::<i32>(-1, false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/issue-99073-2.rs:9:22
|
||||
|
|
||||
|
|
@ -19,6 +10,15 @@ note: previous use here
|
|||
LL | fn test<T: Display>(t: T, recurse: bool) -> impl Display {
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error[E0792]: expected generic type parameter, found `i32`
|
||||
--> $DIR/issue-99073-2.rs:9:22
|
||||
|
|
||||
LL | fn test<T: Display>(t: T, recurse: bool) -> impl Display {
|
||||
| - this generic parameter must be used with a generic type parameter
|
||||
LL | let f = || {
|
||||
LL | let i: u32 = test::<i32>(-1, false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0792`.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,3 @@
|
|||
error[E0792]: expected generic type parameter, found `&F`
|
||||
--> $DIR/issue-99073.rs:6:11
|
||||
|
|
||||
LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
|
||||
| - this generic parameter must be used with a generic type parameter
|
||||
LL | move || f(fix(&f))
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/issue-99073.rs:6:13
|
||||
|
|
||||
|
|
@ -18,6 +10,14 @@ note: previous use here
|
|||
LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
|
||||
| ^^^^^^^^^
|
||||
|
||||
error[E0792]: expected generic type parameter, found `&F`
|
||||
--> $DIR/issue-99073.rs:6:11
|
||||
|
|
||||
LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
|
||||
| - this generic parameter must be used with a generic type parameter
|
||||
LL | move || f(fix(&f))
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0792`.
|
||||
|
|
|
|||
|
|
@ -1,15 +1,3 @@
|
|||
warning: function cannot return without recursing
|
||||
--> $DIR/multiple-defining-usages-in-body.rs:4:1
|
||||
|
|
||||
LL | fn foo<T: Trait, U: Trait>() -> impl Trait {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||
LL |
|
||||
LL | let a: T = foo::<T, U>();
|
||||
| ------------- recursive call site
|
||||
|
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
= note: `#[warn(unconditional_recursion)]` on by default
|
||||
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/multiple-defining-usages-in-body.rs:8:16
|
||||
|
|
||||
|
|
@ -22,5 +10,17 @@ note: previous use here
|
|||
LL | let a: T = foo::<T, U>();
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
warning: function cannot return without recursing
|
||||
--> $DIR/multiple-defining-usages-in-body.rs:4:1
|
||||
|
|
||||
LL | fn foo<T: Trait, U: Trait>() -> impl Trait {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||
LL |
|
||||
LL | let a: T = foo::<T, U>();
|
||||
| ------------- recursive call site
|
||||
|
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
= note: `#[warn(unconditional_recursion)]` on by default
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
error[E0792]: expected generic lifetime parameter, found `'_`
|
||||
--> $DIR/early_bound.rs:7:17
|
||||
|
|
||||
LL | fn test<'a: 'a>(n: bool) -> impl Sized + 'a {
|
||||
| -- this generic parameter must be used with a generic lifetime parameter
|
||||
...
|
||||
LL | let _ = identity::<&'a ()>(test(false));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/early_bound.rs:3:29
|
||||
|
|
||||
|
|
@ -19,6 +10,15 @@ note: previous use here
|
|||
LL | let _ = identity::<&'a ()>(test(false));
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error[E0792]: expected generic lifetime parameter, found `'_`
|
||||
--> $DIR/early_bound.rs:7:17
|
||||
|
|
||||
LL | fn test<'a: 'a>(n: bool) -> impl Sized + 'a {
|
||||
| -- this generic parameter must be used with a generic lifetime parameter
|
||||
...
|
||||
LL | let _ = identity::<&'a ()>(test(false));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0792`.
|
||||
|
|
|
|||
|
|
@ -6,14 +6,6 @@ LL | fn foo<T>() -> impl Sized {
|
|||
LL | let _: () = foo::<u8>();
|
||||
| ^^
|
||||
|
||||
error[E0792]: expected generic type parameter, found `u8`
|
||||
--> $DIR/non-defining-use.rs:8:12
|
||||
|
|
||||
LL | fn bar<T>(val: T) -> impl Sized {
|
||||
| - this generic parameter must be used with a generic type parameter
|
||||
LL | let _: u8 = bar(0u8);
|
||||
| ^^
|
||||
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/non-defining-use.rs:8:17
|
||||
|
|
||||
|
|
@ -26,6 +18,14 @@ note: previous use here
|
|||
LL | fn bar<T>(val: T) -> impl Sized {
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0792]: expected generic type parameter, found `u8`
|
||||
--> $DIR/non-defining-use.rs:8:12
|
||||
|
|
||||
LL | fn bar<T>(val: T) -> impl Sized {
|
||||
| - this generic parameter must be used with a generic type parameter
|
||||
LL | let _: u8 = bar(0u8);
|
||||
| ^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0792`.
|
||||
|
|
|
|||
|
|
@ -1,42 +1,3 @@
|
|||
error: associated item referring to unboxed trait object for its own trait
|
||||
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13
|
||||
|
|
||||
LL | trait A: Sized {
|
||||
| - in this trait
|
||||
LL | fn f(a: A) -> A;
|
||||
| ^ ^
|
||||
|
|
||||
help: you might have meant to use `Self` to refer to the implementing type
|
||||
|
|
||||
LL | fn f(a: Self) -> Self;
|
||||
| ~~~~ ~~~~
|
||||
|
||||
error: associated item referring to unboxed trait object for its own trait
|
||||
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13
|
||||
|
|
||||
LL | trait B {
|
||||
| - in this trait
|
||||
LL | fn f(b: B) -> B;
|
||||
| ^ ^
|
||||
|
|
||||
help: you might have meant to use `Self` to refer to the implementing type
|
||||
|
|
||||
LL | fn f(b: Self) -> Self;
|
||||
| ~~~~ ~~~~
|
||||
|
||||
error: associated item referring to unboxed trait object for its own trait
|
||||
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:20
|
||||
|
|
||||
LL | trait C {
|
||||
| - in this trait
|
||||
LL | fn f(&self, c: C) -> C;
|
||||
| ^ ^
|
||||
|
|
||||
help: you might have meant to use `Self` to refer to the implementing type
|
||||
|
|
||||
LL | fn f(&self, c: Self) -> Self;
|
||||
| ~~~~ ~~~~
|
||||
|
||||
error[E0782]: expected a type, found a trait
|
||||
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13
|
||||
|
|
||||
|
|
@ -118,6 +79,45 @@ help: `C` is dyn-incompatible, use `impl C` to return an opaque type, as long as
|
|||
LL | fn f(&self, c: C) -> impl C;
|
||||
| ++++
|
||||
|
||||
error: associated item referring to unboxed trait object for its own trait
|
||||
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13
|
||||
|
|
||||
LL | trait A: Sized {
|
||||
| - in this trait
|
||||
LL | fn f(a: A) -> A;
|
||||
| ^ ^
|
||||
|
|
||||
help: you might have meant to use `Self` to refer to the implementing type
|
||||
|
|
||||
LL | fn f(a: Self) -> Self;
|
||||
| ~~~~ ~~~~
|
||||
|
||||
error: associated item referring to unboxed trait object for its own trait
|
||||
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13
|
||||
|
|
||||
LL | trait B {
|
||||
| - in this trait
|
||||
LL | fn f(b: B) -> B;
|
||||
| ^ ^
|
||||
|
|
||||
help: you might have meant to use `Self` to refer to the implementing type
|
||||
|
|
||||
LL | fn f(b: Self) -> Self;
|
||||
| ~~~~ ~~~~
|
||||
|
||||
error: associated item referring to unboxed trait object for its own trait
|
||||
--> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:20
|
||||
|
|
||||
LL | trait C {
|
||||
| - in this trait
|
||||
LL | fn f(&self, c: C) -> C;
|
||||
| ^ ^
|
||||
|
|
||||
help: you might have meant to use `Self` to refer to the implementing type
|
||||
|
|
||||
LL | fn f(&self, c: Self) -> Self;
|
||||
| ~~~~ ~~~~
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0782`.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
#[derive(Clone)] //~ expected a type, found a trait
|
||||
#[derive(Clone)]
|
||||
//~^ expected a type, found a trait
|
||||
//~| expected a type, found a trait
|
||||
struct Foo;
|
||||
trait Foo {} //~ the name `Foo` is defined multiple times
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0428]: the name `Foo` is defined multiple times
|
||||
--> $DIR/issue-106072.rs:3:1
|
||||
--> $DIR/issue-106072.rs:5:1
|
||||
|
|
||||
LL | struct Foo;
|
||||
| ----------- previous definition of the type `Foo` here
|
||||
|
|
@ -16,7 +16,16 @@ LL | #[derive(Clone)]
|
|||
|
|
||||
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error[E0782]: expected a type, found a trait
|
||||
--> $DIR/issue-106072.rs:1:10
|
||||
|
|
||||
LL | #[derive(Clone)]
|
||||
| ^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0428, E0782.
|
||||
For more information about an error, try `rustc --explain E0428`.
|
||||
|
|
|
|||
|
|
@ -1,15 +1,3 @@
|
|||
error[E0277]: the trait bound `i64: Foo<i64>` is not satisfied
|
||||
--> $DIR/missing-for-type-in-impl.rs:19:19
|
||||
|
|
||||
LL | let x: i64 = <i64 as Foo<i64>>::id(10);
|
||||
| ^^^ the trait `Foo<i64>` is not implemented for `i64`
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/missing-for-type-in-impl.rs:3:1
|
||||
|
|
||||
LL | trait Foo<T> {
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error[E0782]: expected a type, found a trait
|
||||
--> $DIR/missing-for-type-in-impl.rs:8:6
|
||||
|
|
||||
|
|
@ -25,6 +13,18 @@ help: you might have intended to implement this trait for a given type
|
|||
LL | impl Foo<i64> for /* Type */ {
|
||||
| ++++++++++++++
|
||||
|
||||
error[E0277]: the trait bound `i64: Foo<i64>` is not satisfied
|
||||
--> $DIR/missing-for-type-in-impl.rs:19:19
|
||||
|
|
||||
LL | let x: i64 = <i64 as Foo<i64>>::id(10);
|
||||
| ^^^ the trait `Foo<i64>` is not implemented for `i64`
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/missing-for-type-in-impl.rs:3:1
|
||||
|
|
||||
LL | trait Foo<T> {
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0782.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,15 @@
|
|||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/hkl_forbidden4.rs:12:1
|
||||
|
|
||||
LL | async fn operation(_: &mut ()) -> () {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body of operation()}`
|
||||
|
|
||||
note: previous use here
|
||||
--> $DIR/hkl_forbidden4.rs:14:5
|
||||
|
|
||||
LL | call(operation).await
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: item does not constrain `FutNothing::{opaque#0}`, but has it in its signature
|
||||
--> $DIR/hkl_forbidden4.rs:18:10
|
||||
|
|
||||
|
|
@ -35,18 +47,6 @@ LL |
|
|||
LL | call(operation).await
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/hkl_forbidden4.rs:12:1
|
||||
|
|
||||
LL | async fn operation(_: &mut ()) -> () {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body of operation()}`
|
||||
|
|
||||
note: previous use here
|
||||
--> $DIR/hkl_forbidden4.rs:14:5
|
||||
|
|
||||
LL | call(operation).await
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0792]: expected generic lifetime parameter, found `'any`
|
||||
--> $DIR/hkl_forbidden4.rs:22:1
|
||||
|
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue