Auto merge of #69590 - Dylan-DPC:rollup-i3z0sic, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #69504 (Use assert_ne in hash tests) - #69571 (remove unneeded .as_ref() calls.) - #69572 (use .iter() instead of .into_iter() on references) - #69581 (fix aliasing violation in align_to_mut) - #69582 (improve transmute and Vec::from_raw_parts docs) - #69584 (Correct comment to match behavior) - #69587 (rustc_parse: Tweak the function parameter name check) Failed merges: r? @ghost
This commit is contained in:
commit
d3c79346a3
29 changed files with 65 additions and 46 deletions
|
@ -404,7 +404,10 @@ impl<T> Vec<T> {
|
|||
///
|
||||
/// * `ptr` needs to have been previously allocated via [`String`]/`Vec<T>`
|
||||
/// (at least, it's highly likely to be incorrect if it wasn't).
|
||||
/// * `ptr`'s `T` needs to have the same size and alignment as it was allocated with.
|
||||
/// * `T` needs to have the same size and alignment as what `ptr` was allocated with.
|
||||
/// (`T` having a less strict alignment is not sufficient, the alignment really
|
||||
/// needs to be equal to satsify the [`dealloc`] requirement that memory must be
|
||||
/// allocated and deallocated with the same layout.)
|
||||
/// * `length` needs to be less than or equal to `capacity`.
|
||||
/// * `capacity` needs to be the capacity that the pointer was allocated with.
|
||||
///
|
||||
|
@ -423,6 +426,7 @@ impl<T> Vec<T> {
|
|||
/// function.
|
||||
///
|
||||
/// [`String`]: ../../std/string/struct.String.html
|
||||
/// [`dealloc`]: ../../alloc/alloc/trait.GlobalAlloc.html#tymethod.dealloc
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
|
@ -881,7 +881,8 @@ extern "rust-intrinsic" {
|
|||
/// // clone the vector as we will reuse them later
|
||||
/// let v_clone = v_orig.clone();
|
||||
///
|
||||
/// // Using transmute: this is Undefined Behavior, and a bad idea.
|
||||
/// // Using transmute: this relies on the unspecified data layout of `Vec`, which is a
|
||||
/// // bad idea and could cause Undefined Behavior.
|
||||
/// // However, it is no-copy.
|
||||
/// let v_transmuted = unsafe {
|
||||
/// std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(v_clone)
|
||||
|
@ -897,13 +898,14 @@ extern "rust-intrinsic" {
|
|||
///
|
||||
/// let v_clone = v_orig.clone();
|
||||
///
|
||||
/// // The no-copy, unsafe way, still using transmute, but not UB.
|
||||
/// // This is equivalent to the original, but safer, and reuses the
|
||||
/// // same `Vec` internals. Therefore, the new inner type must have the
|
||||
/// // exact same size, and the same alignment, as the old type.
|
||||
/// // The no-copy, unsafe way, still using transmute, but not relying on the data layout.
|
||||
/// // Like the first approach, this reuses the `Vec` internals.
|
||||
/// // Therefore, the new inner type must have the
|
||||
/// // exact same size, *and the same alignment*, as the old type.
|
||||
/// // The same caveats exist for this method as transmute, for
|
||||
/// // the original inner type (`&i32`) to the converted inner type
|
||||
/// // (`Option<&i32>`), so read the nomicon pages linked above.
|
||||
/// // (`Option<&i32>`), so read the nomicon pages linked above and also
|
||||
/// // consult the [`from_raw_parts`] documentation.
|
||||
/// let v_from_raw = unsafe {
|
||||
// FIXME Update this when vec_into_raw_parts is stabilized
|
||||
/// // Ensure the original vector is not dropped.
|
||||
|
@ -914,6 +916,8 @@ extern "rust-intrinsic" {
|
|||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// [`from_raw_parts`]: ../../std/vec/struct.Vec.html#method.from_raw_parts
|
||||
///
|
||||
/// Implementing `split_at_mut`:
|
||||
///
|
||||
/// ```
|
||||
|
|
|
@ -2571,11 +2571,13 @@ impl<T> [T] {
|
|||
let (left, rest) = self.split_at_mut(offset);
|
||||
// now `rest` is definitely aligned, so `from_raw_parts_mut` below is okay
|
||||
let (us_len, ts_len) = rest.align_to_offsets::<U>();
|
||||
let rest_len = rest.len();
|
||||
let mut_ptr = rest.as_mut_ptr();
|
||||
// We can't use `rest` again after this, that would invalidate its alias `mut_ptr`!
|
||||
(
|
||||
left,
|
||||
from_raw_parts_mut(mut_ptr as *mut U, us_len),
|
||||
from_raw_parts_mut(mut_ptr.add(rest.len() - ts_len), ts_len),
|
||||
from_raw_parts_mut(mut_ptr.add(rest_len - ts_len), ts_len),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1570,6 +1570,18 @@ fn test_align_to_empty_mid() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_align_to_mut_aliasing() {
|
||||
let mut val = [1u8, 2, 3, 4, 5];
|
||||
// `align_to_mut` used to create `mid` in a way that there was some intermediate
|
||||
// incorrect aliasing, invalidating the resulting `mid` slice.
|
||||
let (begin, mid, end) = unsafe { val.align_to_mut::<[u8; 2]>() };
|
||||
assert!(begin.len() == 0);
|
||||
assert!(end.len() == 1);
|
||||
mid[0] = mid[1];
|
||||
assert_eq!(val, [3, 4, 3, 4, 5])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_slice_partition_dedup_by() {
|
||||
let mut slice: [i32; 9] = [1, -1, 2, 3, 1, -5, 5, -2, 2];
|
||||
|
|
|
@ -2291,13 +2291,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
#[inline]
|
||||
pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
|
||||
let kinds: Vec<_> = ts.into_iter().map(|&t| GenericArg::from(t)).collect();
|
||||
let kinds: Vec<_> = ts.iter().map(|&t| GenericArg::from(t)).collect();
|
||||
self.mk_ty(Tuple(self.intern_substs(&kinds)))
|
||||
}
|
||||
|
||||
pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I) -> I::Output {
|
||||
iter.intern_with(|ts| {
|
||||
let kinds: Vec<_> = ts.into_iter().map(|&t| GenericArg::from(t)).collect();
|
||||
let kinds: Vec<_> = ts.iter().map(|&t| GenericArg::from(t)).collect();
|
||||
self.mk_ty(Tuple(self.intern_substs(&kinds)))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ impl<'a> CollectProcMacros<'a> {
|
|||
.span_err(attr.span(), "attribute must be of form: `attributes(foo, bar)`");
|
||||
&[]
|
||||
})
|
||||
.into_iter()
|
||||
.iter()
|
||||
.filter_map(|attr| {
|
||||
let attr = match attr.meta_item() {
|
||||
Some(meta_item) => meta_item,
|
||||
|
|
|
@ -630,7 +630,7 @@ pub fn make_query_region_constraints<'tcx>(
|
|||
assert!(givens.is_empty());
|
||||
|
||||
let outlives: Vec<_> = constraints
|
||||
.into_iter()
|
||||
.iter()
|
||||
.map(|(k, _)| match *k {
|
||||
// Swap regions because we are going from sub (<=) to outlives
|
||||
// (>=).
|
||||
|
|
|
@ -237,10 +237,8 @@ impl<'tcx> OnUnimplementedDirective {
|
|||
}
|
||||
}
|
||||
|
||||
let options: FxHashMap<Symbol, String> = options
|
||||
.into_iter()
|
||||
.filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned())))
|
||||
.collect();
|
||||
let options: FxHashMap<Symbol, String> =
|
||||
options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
|
||||
OnUnimplementedNote {
|
||||
label: label.map(|l| l.format(tcx, trait_ref, &options)),
|
||||
message: message.map(|m| m.format(tcx, trait_ref, &options)),
|
||||
|
|
|
@ -2411,7 +2411,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
types
|
||||
.skip_binder()
|
||||
.into_iter()
|
||||
.iter()
|
||||
.flat_map(|ty| {
|
||||
// binder moved -\
|
||||
let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/
|
||||
|
|
|
@ -739,7 +739,7 @@ impl EarlyLintPass for DeprecatedAttr {
|
|||
}
|
||||
|
||||
fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &[ast::Attribute]) {
|
||||
let mut attrs = attrs.into_iter().peekable();
|
||||
let mut attrs = attrs.iter().peekable();
|
||||
|
||||
// Accumulate a single span for sugared doc comments.
|
||||
let mut sugared_span: Option<Span> = None;
|
||||
|
|
|
@ -519,7 +519,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn add_move_error_details(&self, err: &mut DiagnosticBuilder<'a>, binds_to: &[Local]) {
|
||||
for (j, local) in binds_to.into_iter().enumerate() {
|
||||
for (j, local) in binds_to.iter().enumerate() {
|
||||
let bind_to = &self.body.local_decls[*local];
|
||||
let binding_span = bind_to.source_info.span;
|
||||
|
||||
|
|
|
@ -419,7 +419,7 @@ impl RustcMirAttrs {
|
|||
let mut ret = RustcMirAttrs::default();
|
||||
|
||||
let rustc_mir_attrs = attrs
|
||||
.into_iter()
|
||||
.iter()
|
||||
.filter(|attr| attr.check_name(sym::rustc_mir))
|
||||
.flat_map(|attr| attr.meta_item_list().into_iter().flat_map(|v| v.into_iter()));
|
||||
|
||||
|
|
|
@ -195,7 +195,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
|
|||
.local_map
|
||||
.get(&place.local)
|
||||
.into_iter()
|
||||
.flat_map(|bs| bs.into_iter())
|
||||
.flat_map(|bs| bs.iter())
|
||||
.copied();
|
||||
|
||||
// If the borrowed place is a local with no projections, all other borrows of this
|
||||
|
|
|
@ -509,7 +509,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
&self,
|
||||
ops: &[mir::Operand<'tcx>],
|
||||
) -> InterpResult<'tcx, Vec<OpTy<'tcx, M::PointerTag>>> {
|
||||
ops.into_iter().map(|op| self.eval_operand(op, None)).collect()
|
||||
ops.iter().map(|op| self.eval_operand(op, None)).collect()
|
||||
}
|
||||
|
||||
// Used when the miri-engine runs into a constant and for extracting information from constants
|
||||
|
|
|
@ -401,10 +401,8 @@ fn record_accesses<'tcx>(
|
|||
// We collect this into a `SmallVec` to avoid calling `is_inlining_candidate` in the lock.
|
||||
// FIXME: Call `is_inlining_candidate` when pushing to `neighbors` in `collect_items_rec`
|
||||
// instead to avoid creating this `SmallVec`.
|
||||
let accesses: SmallVec<[_; 128]> = callees
|
||||
.into_iter()
|
||||
.map(|mono_item| (*mono_item, is_inlining_candidate(mono_item)))
|
||||
.collect();
|
||||
let accesses: SmallVec<[_; 128]> =
|
||||
callees.iter().map(|mono_item| (*mono_item, is_inlining_candidate(mono_item))).collect();
|
||||
|
||||
inlining_map.lock_mut().record_accesses(caller, &accesses);
|
||||
}
|
||||
|
|
|
@ -644,7 +644,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) {
|
|||
}
|
||||
}
|
||||
|
||||
let mut unsafe_blocks: Vec<_> = unsafe_blocks.into_iter().collect();
|
||||
let mut unsafe_blocks: Vec<_> = unsafe_blocks.iter().collect();
|
||||
unsafe_blocks.sort_by_cached_key(|(hir_id, _)| tcx.hir().hir_to_node_id(*hir_id));
|
||||
let used_unsafe: FxHashSet<_> =
|
||||
unsafe_blocks.iter().flat_map(|&&(id, used)| used.then_some(id)).collect();
|
||||
|
|
|
@ -100,7 +100,7 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
|
|||
&mut body.basic_blocks_mut()[bb].terminator_mut().kind
|
||||
{
|
||||
let vals = &*values;
|
||||
let zipped = vals.iter().zip(targets.into_iter());
|
||||
let zipped = vals.iter().zip(targets.iter());
|
||||
|
||||
let mut matched_values = Vec::with_capacity(allowed_variants.len());
|
||||
let mut matched_targets = Vec::with_capacity(allowed_variants.len() + 1);
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::maybe_whole;
|
|||
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::{struct_span_err, Applicability, PResult, StashKey};
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::{self, Span};
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use syntax::ast::{self, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID};
|
||||
|
@ -636,7 +637,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
pub fn parse_trait_item(&mut self) -> PResult<'a, Option<Option<P<AssocItem>>>> {
|
||||
self.parse_assoc_item(|t| t.span.rust_2018())
|
||||
self.parse_assoc_item(|edition| edition >= Edition::Edition2018)
|
||||
}
|
||||
|
||||
/// Parses associated items.
|
||||
|
@ -1380,7 +1381,7 @@ impl<'a> Parser<'a> {
|
|||
/// The parsing configuration used to parse a parameter list (see `parse_fn_params`).
|
||||
///
|
||||
/// The function decides if, per-parameter `p`, `p` must have a pattern or just a type.
|
||||
type ReqName = fn(&token::Token) -> bool;
|
||||
type ReqName = fn(Edition) -> bool;
|
||||
|
||||
/// Parsing of functions and methods.
|
||||
impl<'a> Parser<'a> {
|
||||
|
@ -1536,7 +1537,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
let is_name_required = match self.token.kind {
|
||||
token::DotDotDot => false,
|
||||
_ => req_name(&self.normalized_token),
|
||||
_ => req_name(self.normalized_token.span.edition()),
|
||||
};
|
||||
let (pat, ty) = if is_name_required || self.is_named_param() {
|
||||
debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
|
||||
|
|
|
@ -657,7 +657,7 @@ impl EmbargoVisitor<'tcx> {
|
|||
.map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id))
|
||||
{
|
||||
if let hir::ItemKind::Mod(m) = &item.kind {
|
||||
for item_id in m.item_ids.as_ref() {
|
||||
for item_id in m.item_ids {
|
||||
let item = self.tcx.hir().expect_item(item_id.id);
|
||||
let def_id = self.tcx.hir().local_def_id(item_id.id);
|
||||
if !self.tcx.hygienic_eq(segment.ident, item.ident, def_id) {
|
||||
|
|
|
@ -1426,7 +1426,7 @@ crate fn show_candidates(
|
|||
// we want consistent results across executions, but candidates are produced
|
||||
// by iterating through a hash map, so make sure they are ordered:
|
||||
let mut path_strings: Vec<_> =
|
||||
candidates.into_iter().map(|c| path_names_to_string(&c.path)).collect();
|
||||
candidates.iter().map(|c| path_names_to_string(&c.path)).collect();
|
||||
path_strings.sort();
|
||||
path_strings.dedup();
|
||||
|
||||
|
|
|
@ -430,7 +430,7 @@ impl Sig for ast::Item {
|
|||
sig.text.push_str(" = ");
|
||||
let ty = match ty {
|
||||
Some(ty) => ty.make(offset + sig.text.len(), id, scx)?,
|
||||
None => Err("Ty")?,
|
||||
None => return Err("Ty"),
|
||||
};
|
||||
sig.text.push_str(&ty.text);
|
||||
sig.text.push(';');
|
||||
|
|
|
@ -395,7 +395,7 @@ impl SourceMap {
|
|||
.unwrap_or_else(|x| x);
|
||||
let special_chars = end_width_idx - start_width_idx;
|
||||
let non_narrow: usize = f.non_narrow_chars[start_width_idx..end_width_idx]
|
||||
.into_iter()
|
||||
.iter()
|
||||
.map(|x| x.width())
|
||||
.sum();
|
||||
col.0 - special_chars + non_narrow
|
||||
|
@ -413,7 +413,7 @@ impl SourceMap {
|
|||
.binary_search_by_key(&pos, |x| x.pos())
|
||||
.unwrap_or_else(|x| x);
|
||||
let non_narrow: usize =
|
||||
f.non_narrow_chars[0..end_width_idx].into_iter().map(|x| x.width()).sum();
|
||||
f.non_narrow_chars[0..end_width_idx].iter().map(|x| x.width()).sum();
|
||||
chpos.0 - end_width_idx + non_narrow
|
||||
};
|
||||
Loc { file: f, line: 0, col: chpos, col_display }
|
||||
|
|
|
@ -256,7 +256,7 @@ fn program_clauses_for_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
|
|||
|
||||
// `WellFormed(WC)`
|
||||
let wf_conditions = where_clauses
|
||||
.into_iter()
|
||||
.iter()
|
||||
.map(|wc| wc.subst(tcx, bound_vars))
|
||||
.map(|wc| wc.map_bound(|goal| goal.into_well_formed_goal()));
|
||||
|
||||
|
|
|
@ -239,7 +239,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
|||
.segments
|
||||
.iter()
|
||||
.filter_map(|seg| seg.args.as_ref())
|
||||
.map(|generic_args| generic_args.args.as_ref())
|
||||
.map(|generic_args| generic_args.args)
|
||||
.find_map(|args| {
|
||||
args.iter()
|
||||
.filter(|arg| arg.is_const())
|
||||
|
|
|
@ -2388,9 +2388,9 @@ impl Clean<TypeBindingKind> for hir::TypeBindingKind<'_> {
|
|||
hir::TypeBindingKind::Equality { ref ty } => {
|
||||
TypeBindingKind::Equality { ty: ty.clean(cx) }
|
||||
}
|
||||
hir::TypeBindingKind::Constraint { ref bounds } => TypeBindingKind::Constraint {
|
||||
bounds: bounds.into_iter().map(|b| b.clean(cx)).collect(),
|
||||
},
|
||||
hir::TypeBindingKind::Constraint { ref bounds } => {
|
||||
TypeBindingKind::Constraint { bounds: bounds.iter().map(|b| b.clean(cx)).collect() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -738,7 +738,7 @@ impl Markdown<'_> {
|
|||
return String::new();
|
||||
}
|
||||
let replacer = |_: &str, s: &str| {
|
||||
if let Some(&(_, ref replace)) = links.into_iter().find(|link| &*link.0 == s) {
|
||||
if let Some(&(_, ref replace)) = links.iter().find(|link| &*link.0 == s) {
|
||||
Some((replace.clone(), s.to_owned()))
|
||||
} else {
|
||||
None
|
||||
|
@ -816,7 +816,7 @@ impl MarkdownSummaryLine<'_> {
|
|||
}
|
||||
|
||||
let replacer = |_: &str, s: &str| {
|
||||
if let Some(&(_, ref replace)) = links.into_iter().find(|link| &*link.0 == s) {
|
||||
if let Some(&(_, ref replace)) = links.iter().find(|link| &*link.0 == s) {
|
||||
Some((replace.clone(), s.to_owned()))
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -670,7 +670,7 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option
|
|||
match *clean_type {
|
||||
clean::ResolvedPath { ref path, .. } => {
|
||||
let segments = &path.segments;
|
||||
let path_segment = segments.into_iter().last().unwrap_or_else(|| panic!(
|
||||
let path_segment = segments.iter().last().unwrap_or_else(|| panic!(
|
||||
"get_index_type_name(clean_type: {:?}, accept_generic: {:?}) had length zero path",
|
||||
clean_type, accept_generic
|
||||
));
|
||||
|
|
|
@ -2011,7 +2011,7 @@ impl Path {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn file_name(&self) -> Option<&OsStr> {
|
||||
self.components().next_back().and_then(|p| match p {
|
||||
Component::Normal(p) => Some(p.as_ref()),
|
||||
Component::Normal(p) => Some(p),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -284,7 +284,7 @@ impl Instant {
|
|||
}
|
||||
|
||||
/// Returns the amount of time elapsed from another instant to this one,
|
||||
/// or zero duration if that instant is earlier than this one.
|
||||
/// or zero duration if that instant is later than this one.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue