diff --git a/compiler/rustc_apfloat/src/ieee.rs b/compiler/rustc_apfloat/src/ieee.rs index 71bcb8f090d07..96277950cfe1a 100644 --- a/compiler/rustc_apfloat/src/ieee.rs +++ b/compiler/rustc_apfloat/src/ieee.rs @@ -2273,6 +2273,7 @@ impl Loss { mod sig { use super::{limbs_for_bits, ExpInt, Limb, Loss, LIMB_BITS}; use core::cmp::Ordering; + use core::iter; use core::mem; pub(super) fn is_all_zeros(limbs: &[Limb]) -> bool { @@ -2483,7 +2484,7 @@ mod sig { pub(super) fn add(a: &mut [Limb], b: &[Limb], mut c: Limb) -> Limb { assert!(c <= 1); - for (a, &b) in a.iter_mut().zip(b) { + for (a, &b) in iter::zip(a, b) { let (r, overflow) = a.overflowing_add(b); let (r, overflow2) = r.overflowing_add(c); *a = r; @@ -2497,7 +2498,7 @@ mod sig { pub(super) fn sub(a: &mut [Limb], b: &[Limb], mut c: Limb) -> Limb { assert!(c <= 1); - for (a, &b) in a.iter_mut().zip(b) { + for (a, &b) in iter::zip(a, b) { let (r, overflow) = a.overflowing_sub(b); let (r, overflow2) = r.overflowing_sub(c); *a = r; diff --git a/compiler/rustc_apfloat/src/lib.rs b/compiler/rustc_apfloat/src/lib.rs index c1aa74029f5eb..c648147d108fb 100644 --- a/compiler/rustc_apfloat/src/lib.rs +++ b/compiler/rustc_apfloat/src/lib.rs @@ -33,6 +33,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![no_std] #![forbid(unsafe_code)] +#![feature(iter_zip)] #![feature(nll)] #![cfg_attr(bootstrap, feature(or_patterns))] diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index a823d375fcf50..032a4e6c78211 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -14,6 +14,7 @@ #![feature(const_fn_transmute)] #![feature(const_panic)] #![feature(crate_visibility_modifier)] +#![feature(iter_zip)] #![feature(label_break_value)] #![feature(nll)] #![cfg_attr(bootstrap, feature(or_patterns))] diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index c5c3142602b9b..1e63ca172e7fc 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -341,7 +341,7 @@ impl TokenStream { pub fn eq_unspanned(&self, other: &TokenStream) -> bool { let mut t1 = self.trees(); let mut t2 = other.trees(); - for (t1, t2) in t1.by_ref().zip(t2.by_ref()) { + for (t1, t2) in iter::zip(&mut t1, &mut t2) { if !t1.eq_unspanned(&t2) { return false; } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index edd0c5fb9647e..ea01632d75d6a 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -18,6 +18,7 @@ use rustc_target::spec::abi; use smallvec::{smallvec, SmallVec}; use tracing::debug; +use std::iter; use std::mem; pub(super) struct ItemLowerer<'a, 'lowering, 'hir> { @@ -206,7 +207,7 @@ impl<'hir> LoweringContext<'_, 'hir> { UseTreeKind::Glob => {} UseTreeKind::Simple(_, id1, id2) => { for (_, &id) in - self.expect_full_res_from_use(base_id).skip(1).zip([id1, id2].iter()) + iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2]) { vec.push(id); } @@ -537,7 +538,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // won't be dealing with macros in the rest of the compiler. // Essentially a single `use` which imports two names is desugared into // two imports. - for (res, &new_node_id) in resolutions.zip([id1, id2].iter()) { + for (res, &new_node_id) in iter::zip(resolutions, &[id1, id2]) { let ident = *ident; let mut path = path.clone(); for seg in &mut path.segments { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 046e7fc70fced..192c328032712 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -33,6 +33,7 @@ #![feature(crate_visibility_modifier)] #![cfg_attr(bootstrap, feature(or_patterns))] #![feature(box_patterns)] +#![feature(iter_zip)] #![recursion_limit = "256"] use rustc_ast::node_id::NodeMap; diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index da85cc73ffd3c..04753926c3e2a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -1034,7 +1034,7 @@ impl<'a> MethodDef<'a> { // make a series of nested matches, to destructure the // structs. This is actually right-to-left, but it shouldn't // matter. - for (arg_expr, pat) in self_args.iter().zip(patterns) { + for (arg_expr, pat) in iter::zip(self_args, patterns) { body = cx.expr_match( trait_.span, arg_expr.clone(), @@ -1351,7 +1351,7 @@ impl<'a> MethodDef<'a> { let mut discriminant_test = cx.expr_bool(sp, true); let mut first_ident = None; - for (&ident, self_arg) in vi_idents.iter().zip(&self_args) { + for (&ident, self_arg) in iter::zip(&vi_idents, &self_args) { let self_addr = cx.expr_addr_of(sp, self_arg.clone()); let variant_value = deriving::call_intrinsic(cx, sp, sym::discriminant_value, vec![self_addr]); @@ -1571,9 +1571,7 @@ impl<'a> TraitDef<'a> { let subpats = self.create_subpatterns(cx, paths, mutbl, use_temporaries); let pattern = match *struct_def { VariantData::Struct(..) => { - let field_pats = subpats - .into_iter() - .zip(&ident_exprs) + let field_pats = iter::zip(subpats, &ident_exprs) .map(|(pat, &(sp, ident, ..))| { if ident.is_none() { cx.span_bug(sp, "a braced struct with unnamed fields in `derive`"); diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index fe4bede6a48b9..d7926ed0e0bce 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -7,6 +7,7 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] +#![feature(iter_zip)] #![feature(nll)] #![cfg_attr(bootstrap, feature(or_patterns))] #![feature(proc_macro_internals)] diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 5effe68752808..4226ed7d99be1 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -24,6 +24,7 @@ use tracing::{debug, info}; use std::ffi::{CStr, CString}; use std::fs::File; use std::io; +use std::iter; use std::path::Path; use std::ptr; use std::slice; @@ -916,9 +917,7 @@ impl ThinLTOKeysMap { modules: &[llvm::ThinLTOModule], names: &[CString], ) -> Self { - let keys = modules - .iter() - .zip(names.iter()) + let keys = iter::zip(modules, names) .map(|(module, name)| { let key = build_string(|rust_str| unsafe { llvm::LLVMRustComputeLTOCacheKey(rust_str, module.identifier, data.0); diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index f4852c91e53d5..896e56a9a1e3a 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -21,6 +21,7 @@ use rustc_target::abi::{self, Align, Size}; use rustc_target::spec::{HasTargetSpec, Target}; use std::borrow::Cow; use std::ffi::CStr; +use std::iter; use std::ops::{Deref, Range}; use std::ptr; use tracing::debug; @@ -1352,18 +1353,14 @@ impl Builder<'a, 'll, 'tcx> { let param_tys = self.cx.func_params_types(fn_ty); - let all_args_match = param_tys - .iter() - .zip(args.iter().map(|&v| self.val_ty(v))) + let all_args_match = iter::zip(¶m_tys, args.iter().map(|&v| self.val_ty(v))) .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty); if all_args_match { return Cow::Borrowed(args); } - let casted_args: Vec<_> = param_tys - .into_iter() - .zip(args.iter()) + let casted_args: Vec<_> = iter::zip(param_tys, args) .enumerate() .map(|(i, (expected_ty, &actual_val))| { let actual_ty = self.val_ty(actual_val); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index d5b32e58cc397..d90e93f116cc1 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1962,9 +1962,7 @@ fn prepare_enum_metadata( let discriminant_type_metadata = |discr: Primitive| { let enumerators_metadata: Vec<_> = match enum_type.kind() { - ty::Adt(def, _) => def - .discriminants(tcx) - .zip(&def.variants) + ty::Adt(def, _) => iter::zip(def.discriminants(tcx), &def.variants) .map(|((_, discr), v)| { let name = v.ident.as_str(); let is_unsigned = match discr.ty.kind() { @@ -2336,9 +2334,7 @@ fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> &'ll DIAr if substs.types().next().is_some() { let generics = cx.tcx.generics_of(def.did); let names = get_parameter_names(cx, generics); - let template_params: Vec<_> = substs - .iter() - .zip(names) + let template_params: Vec<_> = iter::zip(substs, names) .filter_map(|(kind, name)| { if let GenericArgKind::Type(ty) = kind.unpack() { let actual_type = diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index abb87cb36568e..e157a38aa03d5 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -37,6 +37,7 @@ use rustc_target::abi::{LayoutOf, Primitive, Size}; use libc::c_uint; use smallvec::SmallVec; use std::cell::RefCell; +use std::iter; use tracing::debug; mod create_scope_map; @@ -448,9 +449,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { // Again, only create type information if full debuginfo is enabled let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full { let names = get_parameter_names(cx, generics); - substs - .iter() - .zip(names) + iter::zip(substs, names) .filter_map(|(kind, name)| { if let GenericArgKind::Type(ty) = kind.unpack() { let actual_type = diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index de7f5fc6e2982..5ca4b226c38fb 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -11,6 +11,7 @@ #![feature(extended_key_value_attributes)] #![feature(extern_types)] #![feature(in_band_lifetimes)] +#![feature(iter_zip)] #![feature(nll)] #![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 6eead2812ba70..56b4ef7938312 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -8,6 +8,7 @@ #![feature(nll)] #![cfg_attr(bootstrap, feature(or_patterns))] #![feature(associated_type_bounds)] +#![feature(iter_zip)] #![recursion_limit = "256"] #![feature(box_syntax)] diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 3f94547821349..91df67b53d21f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -282,9 +282,7 @@ fn create_funclets<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( IndexVec>, IndexVec>, ) { - block_bxs - .iter_enumerated() - .zip(cleanup_kinds) + iter::zip(block_bxs.iter_enumerated(), cleanup_kinds) .map(|((bb, &llbb), cleanup_kind)| { match *cleanup_kind { CleanupKind::Funclet if base::wants_msvc_seh(bx.sess()) => {} diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 66499fbb8da92..633c64af3c590 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2214,9 +2214,7 @@ pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool { }; let ascii_confusables = &['c', 'f', 'i', 'k', 'o', 's', 'u', 'v', 'w', 'x', 'y', 'z']; // All the chars that differ in capitalization are confusable (above): - let confusable = found - .chars() - .zip(suggested.chars()) + let confusable = iter::zip(found.chars(), suggested.chars()) .filter(|(f, s)| f != s) .all(|(f, s)| (ascii_confusables.contains(&f) || ascii_confusables.contains(&s))); confusable && found.to_lowercase() == suggested.to_lowercase() diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index fa855f544e819..6f3ce20fc8ed2 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -6,6 +6,7 @@ #![feature(crate_visibility_modifier)] #![feature(backtrace)] #![feature(extended_key_value_attributes)] +#![feature(iter_zip)] #![feature(nll)] #[macro_use] diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs index ef71ee36ea36c..ec122e7be6e8e 100644 --- a/compiler/rustc_errors/src/styled_buffer.rs +++ b/compiler/rustc_errors/src/styled_buffer.rs @@ -1,6 +1,7 @@ // Code for creating styled buffers use crate::snippet::{Style, StyledString}; +use std::iter; #[derive(Debug)] pub struct StyledBuffer { @@ -20,11 +21,11 @@ impl StyledBuffer { let mut output: Vec> = vec![]; let mut styled_vec: Vec = vec![]; - for (row, row_style) in self.text.iter().zip(&self.styles) { + for (row, row_style) in iter::zip(&self.text, &self.styles) { let mut current_style = Style::NoStyle; let mut current_text = String::new(); - for (&c, &s) in row.iter().zip(row_style) { + for (&c, &s) in iter::zip(row, row_style) { if s != current_style { if !current_text.is_empty() { styled_vec.push(StyledString { text: current_text, style: current_style }); diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 14f04dcb51a0b..5fb8586750167 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -2,6 +2,7 @@ #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(destructuring_assignment)] +#![feature(iter_zip)] #![cfg_attr(bootstrap, feature(or_patterns))] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 91add4f921844..3497e5ad543a1 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -116,6 +116,8 @@ use rustc_span::{symbol::MacroRulesNormalizedIdent, MultiSpan, Span}; use smallvec::SmallVec; +use std::iter; + /// Stack represented as linked list. /// /// Those are used for environments because they grow incrementally and are not mutable. @@ -204,7 +206,7 @@ pub(super) fn check_meta_variables( sess.span_diagnostic.span_bug(span, "length mismatch between LHSes and RHSes") } let mut valid = true; - for (lhs, rhs) in lhses.iter().zip(rhses.iter()) { + for (lhs, rhs) in iter::zip(lhses, rhses) { let mut binders = Binders::default(); check_binders(sess, node_id, lhs, &Stack::Empty, &mut binders, &Stack::Empty, &mut valid); check_occurrences(sess, node_id, rhs, &Stack::Empty, &binders, &Stack::Empty, &mut valid); diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 100824f4b9448..cfea5092bc306 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -356,7 +356,7 @@ where { assert_eq!(out_vec.len(), in_vec.len()); let mut changed = false; - for (out_elem, in_elem) in out_vec.iter_mut().zip(in_vec.iter()) { + for (out_elem, in_elem) in iter::zip(out_vec, in_vec) { let old_val = *out_elem; let new_val = op(old_val, *in_elem); *out_elem = new_val; @@ -842,7 +842,7 @@ impl BitMatrix { let (write_start, write_end) = self.range(write); let words = &mut self.words[..]; let mut changed = false; - for (read_index, write_index) in (read_start..read_end).zip(write_start..write_end) { + for (read_index, write_index) in iter::zip(read_start..read_end, write_start..write_end) { let word = words[write_index]; let new_word = word | words[read_index]; words[write_index] = new_word; @@ -858,7 +858,7 @@ impl BitMatrix { assert_eq!(with.domain_size(), self.num_columns); let (write_start, write_end) = self.range(write); let mut changed = false; - for (read_index, write_index) in (0..with.words().len()).zip(write_start..write_end) { + for (read_index, write_index) in iter::zip(0..with.words().len(), write_start..write_end) { let word = self.words[write_index]; let new_word = word | with.words()[read_index]; self.words[write_index] = new_word; diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index 995034e81da28..3ced3920cfdfe 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -2,6 +2,7 @@ #![feature(const_fn)] #![feature(const_panic)] #![feature(extend_one)] +#![feature(iter_zip)] #![feature(unboxed_closures)] #![feature(test)] #![feature(fn_traits)] diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 2ec9b9e0be4a8..f000d491b99a6 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -27,6 +27,7 @@ use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; use rustc_middle::ty::{self, BoundVar, Const, ToPredicate, Ty, TyCtxt}; use std::fmt::Debug; +use std::iter; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// This method is meant to be invoked as the final step of a canonical query @@ -418,7 +419,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { // In terms of our example above, we are iterating over pairs like: // [(?A, Vec), ('static, '?1), (?B, ?0)] - for (original_value, result_value) in original_values.var_values.iter().zip(result_values) { + for (original_value, result_value) in iter::zip(&original_values.var_values, result_values) + { match result_value.unpack() { GenericArgKind::Type(result_value) => { // e.g., here `result_value` might be `?0` in the example above... diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 5e11932eafc4e..ffe947d209dd6 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -543,10 +543,6 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { true } - fn visit_ct_substs(&self) -> bool { - true - } - fn binders( &mut self, a: ty::Binder, @@ -737,6 +733,16 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { } } } + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) + if self.tcx().lazy_normalization() => + { + assert_eq!(promoted, None); + let substs = self.relate_with_variance(ty::Variance::Invariant, substs, substs)?; + Ok(self.tcx().mk_const(ty::Const { + ty: c.ty, + val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }), + })) + } _ => relate::super_relate_consts(self, c, c), } } @@ -822,10 +828,6 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { true } - fn visit_ct_substs(&self) -> bool { - true - } - fn relate_with_variance>( &mut self, _variance: ty::Variance, @@ -959,6 +961,16 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { } } } + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) + if self.tcx().lazy_normalization() => + { + assert_eq!(promoted, None); + let substs = self.relate_with_variance(ty::Variance::Invariant, substs, substs)?; + Ok(self.tcx().mk_const(ty::Const { + ty: c.ty, + val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }), + })) + } _ => relate::super_relate_consts(self, c, c), } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index c171b11e3ffa7..a18c9569a8cd3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -73,7 +73,7 @@ use rustc_middle::ty::{ use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span}; use rustc_target::spec::abi; use std::ops::ControlFlow; -use std::{cmp, fmt}; +use std::{cmp, fmt, iter}; mod note; @@ -963,7 +963,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty::GenericParamDefKind::Const { has_default: true } => Some(param.def_id), _ => None, }); - for (def_id, actual) in default_params.zip(substs.iter().rev()) { + for (def_id, actual) in iter::zip(default_params, substs.iter().rev()) { match actual.unpack() { GenericArgKind::Const(c) => { if self.tcx.const_param_default(def_id).subst(self.tcx, substs) != c { @@ -1040,7 +1040,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let len1 = sig1.inputs().len(); let len2 = sig2.inputs().len(); if len1 == len2 { - for (i, (l, r)) in sig1.inputs().iter().zip(sig2.inputs().iter()).enumerate() { + for (i, (l, r)) in iter::zip(sig1.inputs(), sig2.inputs()).enumerate() { let (x1, x2) = self.cmp(l, r); (values.0).0.extend(x1.0); (values.1).0.extend(x2.0); @@ -1161,12 +1161,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let common_len = cmp::min(len1, len2); let remainder1: Vec<_> = sub1.types().skip(common_len).collect(); let remainder2: Vec<_> = sub2.types().skip(common_len).collect(); - let common_default_params = remainder1 - .iter() - .rev() - .zip(remainder2.iter().rev()) - .filter(|(a, b)| a == b) - .count(); + let common_default_params = + iter::zip(remainder1.iter().rev(), remainder2.iter().rev()) + .filter(|(a, b)| a == b) + .count(); let len = sub1.len() - common_default_params; let consts_offset = len - sub1.consts().count(); @@ -1297,12 +1295,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { const SEPARATOR: &str = "::"; let separator_len = SEPARATOR.len(); - let split_idx: usize = t1_str - .split(SEPARATOR) - .zip(t2_str.split(SEPARATOR)) - .take_while(|(mod1_str, mod2_str)| mod1_str == mod2_str) - .map(|(mod_str, _)| mod_str.len() + separator_len) - .sum(); + let split_idx: usize = + iter::zip(t1_str.split(SEPARATOR), t2_str.split(SEPARATOR)) + .take_while(|(mod1_str, mod2_str)| mod1_str == mod2_str) + .map(|(mod_str, _)| mod_str.len() + separator_len) + .sum(); debug!( "cmp: separator_len={}, split_idx={}, min_len={}", @@ -1907,7 +1904,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .find_map(|(path, msg)| (&path_str == path).then_some(msg)) { let mut show_suggestion = true; - for (exp_ty, found_ty) in exp_substs.types().zip(found_substs.types()) { + for (exp_ty, found_ty) in + iter::zip(exp_substs.types(), found_substs.types()) + { match *exp_ty.kind() { ty::Ref(_, exp_ty, _) => { match (exp_ty.kind(), found_ty.kind()) { diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 4ec229ebcf559..d352214b57926 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -19,6 +19,7 @@ #![feature(const_fn)] #![feature(const_panic)] #![feature(extend_one)] +#![feature(iter_zip)] #![feature(never_type)] #![cfg_attr(bootstrap, feature(or_patterns))] #![feature(in_band_lifetimes)] diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index ad15af9ab3f2d..0ac4b6b25bbfe 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -9,6 +9,7 @@ use rustc_middle::ty::TyCtxt; use rustc_span::symbol::Symbol; use rustc_span::{MultiSpan, Span}; use std::fmt; +use std::iter; impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn report_extra_impl_obligation( @@ -94,7 +95,7 @@ pub fn report_object_safety_error( note_span .push_span_label(trait_span, "this trait cannot be made into an object...".to_string()); } - for (span, msg) in multi_span.into_iter().zip(messages.into_iter()) { + for (span, msg) in iter::zip(multi_span, messages) { note_span.push_span_label(span, msg); } err.span_note( diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index c9de85a2f1877..cf2f1489e0296 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -45,6 +45,7 @@ use rustc_target::abi::LayoutOf; use tracing::debug; use std::cell::Cell; +use std::iter; use std::slice; /// Information about the registered lints. @@ -864,7 +865,7 @@ impl<'tcx> LateContext<'tcx> { pub fn match_def_path(&self, def_id: DefId, path: &[Symbol]) -> bool { let names = self.get_def_path(def_id); - names.len() == path.len() && names.into_iter().zip(path.iter()).all(|(a, &b)| a == b) + names.len() == path.len() && iter::zip(names, path).all(|(a, &b)| a == b) } /// Gets the absolute path of `def_id` as a vector of `Symbol`. diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index cacdf26054825..e2724b52453a5 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -33,6 +33,7 @@ #![feature(box_patterns)] #![feature(crate_visibility_modifier)] #![feature(iter_order_by)] +#![feature(iter_zip)] #![feature(never_type)] #![feature(nll)] #![cfg_attr(bootstrap, feature(or_patterns))] @@ -325,6 +326,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { store.register_renamed("exceeding_bitshifts", "arithmetic_overflow"); store.register_renamed("redundant_semicolon", "redundant_semicolons"); store.register_renamed("overlapping_patterns", "overlapping_range_endpoints"); + store.register_renamed("safe_packed_borrows", "unaligned_references"); // These were moved to tool lints, but rustc still sees them when compiling normally, before // tool lints are registered, so `check_tool_name_for_backwards_compat` doesn't work. Use diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 2d311cc32f8b7..9c94bab04e98f 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -17,6 +17,7 @@ use rustc_target::abi::{Integer, LayoutOf, TagEncoding, VariantIdx, Variants}; use rustc_target::spec::abi::Abi as SpecAbi; use std::cmp; +use std::iter; use std::ops::ControlFlow; use tracing::debug; @@ -1255,7 +1256,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let sig = self.cx.tcx.fn_sig(def_id); let sig = self.cx.tcx.erase_late_bound_regions(sig); - for (input_ty, input_hir) in sig.inputs().iter().zip(decl.inputs) { + for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) { self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty, false, false); } @@ -1355,10 +1356,7 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences { layout ); - let (largest, slargest, largest_index) = enum_definition - .variants - .iter() - .zip(variants) + let (largest, slargest, largest_index) = iter::zip(enum_definition.variants, variants) .map(|(variant, variant_layout)| { // Subtract the size of the enum tag. let bytes = variant_layout.size.bytes().saturating_sub(tag_size); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index cd4d01ddc058e..3baafee46125d 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1057,6 +1057,7 @@ declare_lint! { /// unsafe { /// let foo = Foo { field1: 0, field2: 0 }; /// let _ = &foo.field1; + /// println!("{}", foo.field1); // An implicit `&` is added here, triggering the lint. /// } /// } /// ``` @@ -1065,20 +1066,20 @@ declare_lint! { /// /// ### Explanation /// - /// Creating a reference to an insufficiently aligned packed field is - /// [undefined behavior] and should be disallowed. - /// - /// This lint is "allow" by default because there is no stable - /// alternative, and it is not yet certain how widespread existing code - /// will trigger this lint. - /// - /// See [issue #27060] for more discussion. + /// Creating a reference to an insufficiently aligned packed field is [undefined behavior] and + /// should be disallowed. Using an `unsafe` block does not change anything about this. Instead, + /// the code should do a copy of the data in the packed field or use raw pointers and unaligned + /// accesses. See [issue #82523] for more information. /// /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html - /// [issue #27060]: https://github.com/rust-lang/rust/issues/27060 + /// [issue #82523]: https://github.com/rust-lang/rust/issues/82523 pub UNALIGNED_REFERENCES, - Allow, + Warn, "detects unaligned references to fields of packed structs", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #82523 ", + edition: None, + }; report_in_external_macro } @@ -1150,49 +1151,6 @@ declare_lint! { "detects attempts to mutate a `const` item", } -declare_lint! { - /// The `safe_packed_borrows` lint detects borrowing a field in the - /// interior of a packed structure with alignment other than 1. - /// - /// ### Example - /// - /// ```rust - /// #[repr(packed)] - /// pub struct Unaligned(pub T); - /// - /// pub struct Foo { - /// start: u8, - /// data: Unaligned, - /// } - /// - /// fn main() { - /// let x = Foo { start: 0, data: Unaligned(1) }; - /// let y = &x.data.0; - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// This type of borrow is unsafe and can cause errors on some platforms - /// and violates some assumptions made by the compiler. This was - /// previously allowed unintentionally. This is a [future-incompatible] - /// lint to transition this to a hard error in the future. See [issue - /// #46043] for more details, including guidance on how to solve the - /// problem. - /// - /// [issue #46043]: https://github.com/rust-lang/rust/issues/46043 - /// [future-incompatible]: ../index.md#future-incompatible-lints - pub SAFE_PACKED_BORROWS, - Warn, - "safe borrows of fields of packed structs were erroneously allowed", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #46043 ", - edition: None, - }; -} - declare_lint! { /// The `patterns_in_fns_without_body` lint detects `mut` identifier /// patterns as a parameter in functions without a body. @@ -2953,7 +2911,6 @@ declare_lint_pass! { RENAMED_AND_REMOVED_LINTS, UNALIGNED_REFERENCES, CONST_ITEM_MUTATION, - SAFE_PACKED_BORROWS, PATTERNS_IN_FNS_WITHOUT_BODY, MISSING_FRAGMENT_SPECIFIER, LATE_BOUND_LIFETIME_ARGUMENTS, diff --git a/compiler/rustc_macros/src/symbols/tests.rs b/compiler/rustc_macros/src/symbols/tests.rs index 82b4b876978f2..842d2a977189d 100644 --- a/compiler/rustc_macros/src/symbols/tests.rs +++ b/compiler/rustc_macros/src/symbols/tests.rs @@ -43,7 +43,7 @@ fn test_symbols_macro(input: TokenStream, expected_errors: &[&str]) { "Macro generated a different number of errors than expected" ); - for (found_error, &expected_error) in found_errors.iter().zip(expected_errors.iter()) { + for (found_error, &expected_error) in found_errors.iter().zip(expected_errors) { let found_error_str = format!("{}", found_error); assert_eq!(found_error_str, expected_error); } diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index e106db38b2c9a..8a13ceec2211b 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -27,6 +27,7 @@ use crate::ty::{self, BoundVar, List, Region, TyCtxt}; use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use smallvec::SmallVec; +use std::iter; use std::ops::Index; /// A "canonicalized" type `V` is one where all free inference @@ -315,10 +316,7 @@ impl<'tcx> CanonicalVarValues<'tcx> { use crate::ty::subst::GenericArgKind; CanonicalVarValues { - var_values: self - .var_values - .iter() - .zip(0..) + var_values: iter::zip(&self.var_values, 0..) .map(|(kind, i)| match kind.unpack() { GenericArgKind::Type(..) => { tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into() diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 1561b3d7d2962..bd0749792db8b 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -51,6 +51,7 @@ #![feature(exclusive_range_pattern)] #![feature(control_flow_enum)] #![feature(associated_type_defaults)] +#![feature(iter_zip)] #![recursion_limit = "512"] #[macro_use] diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index d05269913ebe4..807d63948003a 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2329,7 +2329,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { CtorKind::Fn => fmt_tuple(fmt, &name), CtorKind::Fictive => { let mut struct_fmt = fmt.debug_struct(&name); - for (field, place) in variant_def.fields.iter().zip(places) { + for (field, place) in iter::zip(&variant_def.fields, places) { struct_fmt.field(&field.ident.as_str(), place); } struct_fmt.finish() @@ -2353,7 +2353,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { let mut struct_fmt = fmt.debug_struct(&name); if let Some(upvars) = tcx.upvars_mentioned(def_id) { - for (&var_id, place) in upvars.keys().zip(places) { + for (&var_id, place) in iter::zip(upvars.keys(), places) { let var_name = tcx.hir().name(var_id); struct_fmt.field(&var_name.as_str(), place); } @@ -2372,7 +2372,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { let mut struct_fmt = fmt.debug_struct(&name); if let Some(upvars) = tcx.upvars_mentioned(def_id) { - for (&var_id, place) in upvars.keys().zip(places) { + for (&var_id, place) in iter::zip(upvars.keys(), places) { let var_name = tcx.hir().name(var_id); struct_fmt.field(&var_name.as_str(), place); } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index bde480180136b..ad3baccf15496 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -23,15 +23,9 @@ pub enum UnsafetyViolationKind { General, /// Permitted both in `const fn`s and regular `fn`s. GeneralAndConstFn, - /// Borrow of packed field. - /// Has to be handled as a lint for backwards compatibility. - BorrowPacked, /// Unsafe operation in an `unsafe fn` but outside an `unsafe` block. /// Has to be handled as a lint for backwards compatibility. UnsafeFn, - /// Borrow of packed field in an `unsafe fn` but outside an `unsafe` block. - /// Has to be handled as a lint for backwards compatibility. - UnsafeFnBorrowPacked, } #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 887dbefa9f2da..c8db4aeb449b8 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -67,7 +67,7 @@ impl SwitchTargets { /// /// Note that this may yield 0 elements. Only the `otherwise` branch is mandatory. pub fn iter(&self) -> SwitchTargetsIter<'_> { - SwitchTargetsIter { inner: self.values.iter().zip(self.targets.iter()) } + SwitchTargetsIter { inner: iter::zip(&self.values, &self.targets) } } /// Returns a slice with all possible jump targets (including the fallback target). diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 57225b7abf77c..8fdae695ceb7f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -789,7 +789,7 @@ impl CanonicalUserType<'tcx> { return false; } - user_substs.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { + iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| { match kind.unpack() { GenericArgKind::Type(ty) => match ty.kind() { ty::Bound(debruijn, b) => { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 3a75a6d907d05..0d03cf4575fcf 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1251,13 +1251,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } else { // Try to use a ScalarPair for all tagged enums. let mut common_prim = None; - for (field_layouts, layout_variant) in variants.iter().zip(&layout_variants) { + for (field_layouts, layout_variant) in iter::zip(&variants, &layout_variants) { let offsets = match layout_variant.fields { FieldsShape::Arbitrary { ref offsets, .. } => offsets, _ => bug!(), }; let mut fields = - field_layouts.iter().zip(offsets).filter(|p| !p.0.is_zst()); + iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst()); let (field, offset) = match (fields.next(), fields.next()) { (None, None) => continue, (Some(pair), None) => pair, @@ -1626,7 +1626,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { const INVALID_FIELD_IDX: u32 = !0; let mut combined_inverse_memory_index = vec![INVALID_FIELD_IDX; promoted_memory_index.len() + memory_index.len()]; - let mut offsets_and_memory_index = offsets.into_iter().zip(memory_index); + let mut offsets_and_memory_index = iter::zip(offsets, memory_index); let combined_offsets = variant_fields .iter() .enumerate() diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3b72cc011d6ea..f23c64cb036cf 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -19,6 +19,7 @@ use std::char; use std::collections::BTreeMap; use std::convert::TryFrom; use std::fmt::{self, Write as _}; +use std::iter; use std::ops::{ControlFlow, Deref, DerefMut}; // `pretty` is a separate module only for organization. @@ -1223,7 +1224,7 @@ pub trait PrettyPrinter<'tcx>: CtorKind::Fictive => { p!(" {{ "); let mut first = true; - for (field_def, field) in variant_def.fields.iter().zip(fields) { + for (field_def, field) in iter::zip(&variant_def.fields, fields) { if !first { p!(", "); } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index c936c30f456dd..e2bbb31263a79 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -33,15 +33,6 @@ pub trait TypeRelation<'tcx>: Sized { /// relation. Just affects error messages. fn a_is_expected(&self) -> bool; - /// Whether we should look into the substs of unevaluated constants - /// even if `feature(const_evaluatable_checked)` is active. - /// - /// This is needed in `combine` to prevent accidentially creating - /// infinite types as we abuse `TypeRelation` to walk a type there. - fn visit_ct_substs(&self) -> bool { - false - } - fn with_cause(&mut self, _cause: Cause, f: F) -> R where F: FnOnce(&mut Self) -> R, @@ -149,7 +140,7 @@ pub fn relate_substs>( ) -> RelateResult<'tcx, SubstsRef<'tcx>> { let tcx = relation.tcx(); - let params = a_subst.iter().zip(b_subst).enumerate().map(|(i, (a, b))| { + let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| { let variance = variances.map_or(ty::Invariant, |v| v[i]); relation.relate_with_variance(variance, a, b) }); @@ -179,12 +170,8 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { return Err(TypeError::ArgCount); } - let inputs_and_output = a - .inputs() - .iter() - .cloned() - .zip(b.inputs().iter().cloned()) - .map(|x| (x, false)) + let inputs_and_output = iter::zip(a.inputs(), b.inputs()) + .map(|(&a, &b)| ((a, b), false)) .chain(iter::once(((a.output(), b.output()), true))) .map(|((a, b), is_output)| { if is_output { @@ -308,7 +295,7 @@ impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> { ) -> RelateResult<'tcx, GeneratorWitness<'tcx>> { assert_eq!(a.0.len(), b.0.len()); let tcx = relation.tcx(); - let types = tcx.mk_type_list(a.0.iter().zip(b.0).map(|(a, b)| relation.relate(a, b)))?; + let types = tcx.mk_type_list(iter::zip(a.0, b.0).map(|(a, b)| relation.relate(a, b)))?; Ok(GeneratorWitness(types)) } } @@ -432,9 +419,9 @@ pub fn super_relate_tys>( let sz_a = sz_a.try_eval_usize(tcx, relation.param_env()); let sz_b = sz_b.try_eval_usize(tcx, relation.param_env()); match (sz_a, sz_b) { - (Some(sz_a_val), Some(sz_b_val)) => Err(TypeError::FixedArraySize( - expected_found(relation, sz_a_val, sz_b_val), - )), + (Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err( + TypeError::FixedArraySize(expected_found(relation, sz_a_val, sz_b_val)), + ), _ => Err(err), } } @@ -449,7 +436,7 @@ pub fn super_relate_tys>( (&ty::Tuple(as_), &ty::Tuple(bs)) => { if as_.len() == bs.len() { Ok(tcx.mk_tup( - as_.iter().zip(bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())), + iter::zip(as_, bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())), )?) } else if !(as_.is_empty() || bs.is_empty()) { Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len()))) @@ -532,7 +519,7 @@ pub fn super_relate_consts>( } (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) - if tcx.features().const_evaluatable_checked && !relation.visit_ct_substs() => + if tcx.features().const_evaluatable_checked => { tcx.try_unify_abstract_consts(((au.def, au.substs), (bu.def, bu.substs))) } @@ -593,9 +580,7 @@ fn check_const_value_eq>( // Both the variant and each field have to be equal. if a_destructured.variant == b_destructured.variant { - for (a_field, b_field) in - a_destructured.fields.iter().zip(b_destructured.fields.iter()) - { + for (a_field, b_field) in iter::zip(a_destructured.fields, b_destructured.fields) { relation.consts(a_field, b_field)?; } @@ -631,7 +616,7 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List Ok(ty::Binder::bind(Trait( diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index cff8166974a7a..9926cca2f51c6 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -21,7 +21,7 @@ use rustc_macros::HashStable; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Integer, Size, TargetDataLayout}; use smallvec::SmallVec; -use std::{cmp, fmt}; +use std::{cmp, fmt, iter}; #[derive(Copy, Clone, Debug)] pub struct Discr<'tcx> { @@ -414,9 +414,7 @@ impl<'tcx> TyCtxt<'tcx> { _ => bug!(), }; - let result = item_substs - .iter() - .zip(impl_substs.iter()) + let result = iter::zip(item_substs, impl_substs) .filter(|&(_, k)| { match k.unpack() { GenericArgKind::Lifetime(&ty::RegionKind::ReEarlyBound(ref ebr)) => { diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs index ec561fa38580c..4f61b8d0910ff 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs @@ -18,6 +18,7 @@ use rustc_span::{ Span, }; use rustc_target::abi::VariantIdx; +use std::iter; use super::borrow_set::BorrowData; use super::MirBorrowckCtxt; @@ -970,13 +971,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind; debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr); if let hir::ExprKind::Closure(.., body_id, args_span, _) = expr { - for (captured_place, place) in self - .infcx - .tcx - .typeck(def_id.expect_local()) - .closure_min_captures_flattened(def_id) - .zip(places) - { + for (captured_place, place) in iter::zip( + self.infcx.tcx.typeck(def_id.expect_local()).closure_min_captures_flattened(def_id), + places, + ) { let upvar_hir_id = captured_place.get_root_variable(); //FIXME(project-rfc-2229#8): Use better span from captured_place let span = self.infcx.tcx.upvars_mentioned(local_did)?[&upvar_hir_id].span; diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs index 03738f1b40a1c..1f168c612f167 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs @@ -1,4 +1,5 @@ use std::fmt::{self, Display}; +use std::iter; use rustc_errors::DiagnosticBuilder; use rustc_hir as hir; @@ -536,7 +537,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // just worry about trying to match up the rustc type // with the HIR types: (ty::Tuple(elem_tys), hir::TyKind::Tup(elem_hir_tys)) => { - search_stack.extend(elem_tys.iter().map(|k| k.expect_ty()).zip(*elem_hir_tys)); + search_stack + .extend(iter::zip(elem_tys.iter().map(|k| k.expect_ty()), *elem_hir_tys)); } (ty::Slice(elem_ty), hir::TyKind::Slice(elem_hir_ty)) @@ -611,7 +613,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { args: &'hir hir::GenericArgs<'hir>, search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>, ) -> Option<&'hir hir::Lifetime> { - for (kind, hir_arg) in substs.iter().zip(args.args) { + for (kind, hir_arg) in iter::zip(substs, args.args) { match (kind.unpack(), hir_arg) { (GenericArgKind::Lifetime(r), hir::GenericArg::Lifetime(lt)) => { if r.to_region_vid() == needle_fr { diff --git a/compiler/rustc_mir/src/borrow_check/invalidation.rs b/compiler/rustc_mir/src/borrow_check/invalidation.rs index 17c4f3c649460..1055e30a3a44c 100644 --- a/compiler/rustc_mir/src/borrow_check/invalidation.rs +++ b/compiler/rustc_mir/src/borrow_check/invalidation.rs @@ -5,6 +5,7 @@ use rustc_middle::mir::{BorrowKind, Mutability, Operand}; use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind}; use rustc_middle::mir::{Statement, StatementKind}; use rustc_middle::ty::TyCtxt; +use std::iter; use crate::dataflow::indexes::BorrowIndex; @@ -69,7 +70,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { self.mutate_place(location, **place, Shallow(None), JustWrite); } StatementKind::LlvmInlineAsm(asm) => { - for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) { + for (o, output) in iter::zip(&asm.asm.outputs, &*asm.outputs) { if o.is_indirect { // FIXME(eddyb) indirect inline asm outputs should // be encoded through MIR place derefs instead. diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs index 5b8bb7257e230..583f73d5775d1 100644 --- a/compiler/rustc_mir/src/borrow_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/mod.rs @@ -25,6 +25,7 @@ use either::Either; use smallvec::SmallVec; use std::cell::RefCell; use std::collections::BTreeMap; +use std::iter; use std::mem; use std::rc::Rc; @@ -595,7 +596,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc self.mutate_place(location, (**place, span), Shallow(None), JustWrite, flow_state); } StatementKind::LlvmInlineAsm(ref asm) => { - for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) { + for (o, output) in iter::zip(&asm.asm.outputs, &*asm.outputs) { if o.is_indirect { // FIXME(eddyb) indirect inline asm outputs should // be encoded through MIR place derefs instead. diff --git a/compiler/rustc_mir/src/borrow_check/places_conflict.rs b/compiler/rustc_mir/src/borrow_check/places_conflict.rs index 02c7b7dc200c3..3654b51949e70 100644 --- a/compiler/rustc_mir/src/borrow_check/places_conflict.rs +++ b/compiler/rustc_mir/src/borrow_check/places_conflict.rs @@ -5,6 +5,7 @@ use rustc_hir as hir; use rustc_middle::mir::{Body, BorrowKind, Local, Place, PlaceElem, PlaceRef, ProjectionElem}; use rustc_middle::ty::{self, TyCtxt}; use std::cmp::max; +use std::iter; /// When checking if a place conflicts with another place, this enum is used to influence decisions /// where a place might be equal or disjoint with another place, such as if `a[i] == a[j]`. @@ -139,7 +140,7 @@ fn place_components_conflict<'tcx>( // loop invariant: borrow_c is always either equal to access_c or disjoint from it. for (i, (borrow_c, &access_c)) in - borrow_place.projection.iter().zip(access_place.projection.iter()).enumerate() + iter::zip(borrow_place.projection, access_place.projection).enumerate() { debug!("borrow_conflicts_with_place: borrow_c = {:?}", borrow_c); let borrow_proj_base = &borrow_place.projection[..i]; diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index aaa2bf4ff1b50..fddd140186883 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -1770,7 +1770,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) { span_mirbug!(self, term, "call to {:?} with wrong # of args", sig); } - for (n, (fn_arg, op_arg)) in sig.inputs().iter().zip(args).enumerate() { + for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() { let op_arg_ty = op_arg.ty(body, self.tcx()); let op_arg_ty = self.normalize(op_arg_ty, term_location); let category = if from_hir_call { diff --git a/compiler/rustc_mir/src/borrow_check/universal_regions.rs b/compiler/rustc_mir/src/borrow_check/universal_regions.rs index 4b1acc1cd105e..68fa9d8bf9858 100644 --- a/compiler/rustc_mir/src/borrow_check/universal_regions.rs +++ b/compiler/rustc_mir/src/borrow_check/universal_regions.rs @@ -580,7 +580,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static)); let subst_mapping = - identity_substs.regions().zip(fr_substs.regions().map(|r| r.to_region_vid())); + iter::zip(identity_substs.regions(), fr_substs.regions().map(|r| r.to_region_vid())); UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect() } } diff --git a/compiler/rustc_mir/src/dataflow/framework/lattice.rs b/compiler/rustc_mir/src/dataflow/framework/lattice.rs index e7ef9267db5e5..f937b31f4cfc9 100644 --- a/compiler/rustc_mir/src/dataflow/framework/lattice.rs +++ b/compiler/rustc_mir/src/dataflow/framework/lattice.rs @@ -40,6 +40,7 @@ use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; +use std::iter; /// A [partially ordered set][poset] that has a [least upper bound][lub] for any pair of elements /// in the set. @@ -110,7 +111,7 @@ impl JoinSemiLattice for IndexVec { assert_eq!(self.len(), other.len()); let mut changed = false; - for (a, b) in self.iter_mut().zip(other.iter()) { + for (a, b) in iter::zip(self, other) { changed |= a.join(b); } changed @@ -122,7 +123,7 @@ impl MeetSemiLattice for IndexVec { assert_eq!(self.len(), other.len()); let mut changed = false; - for (a, b) in self.iter_mut().zip(other.iter()) { + for (a, b) in iter::zip(self, other) { changed |= a.meet(b); } changed diff --git a/compiler/rustc_mir/src/dataflow/impls/borrows.rs b/compiler/rustc_mir/src/dataflow/impls/borrows.rs index f24d0f0266d9f..c92cff1433f1a 100644 --- a/compiler/rustc_mir/src/dataflow/impls/borrows.rs +++ b/compiler/rustc_mir/src/dataflow/impls/borrows.rs @@ -11,6 +11,7 @@ use crate::borrow_check::{ use crate::dataflow::{self, fmt::DebugWithContext, GenKill}; use std::fmt; +use std::iter; rustc_index::newtype_index! { pub struct BorrowIndex { @@ -292,7 +293,7 @@ impl<'tcx> dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { } mir::StatementKind::LlvmInlineAsm(ref asm) => { - for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) { + for (output, kind) in iter::zip(&*asm.outputs, &asm.asm.outputs) { if !kind.is_indirect && !kind.is_rw { self.kill_borrows_on_place(trans, *output); } diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs index 1ddd81e779b15..52b6e9f3753be 100644 --- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs +++ b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs @@ -4,6 +4,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; use smallvec::{smallvec, SmallVec}; +use std::iter; use std::mem; use super::abs_domain::Lift; @@ -296,7 +297,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { self.create_move_path(**place); } StatementKind::LlvmInlineAsm(ref asm) => { - for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) { + for (output, kind) in iter::zip(&*asm.outputs, &asm.asm.outputs) { if !kind.is_indirect { self.gather_init(output.as_ref(), InitKind::Deep); } diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs index 3235464141237..b0db4f9e649b3 100644 --- a/compiler/rustc_mir/src/lib.rs +++ b/compiler/rustc_mir/src/lib.rs @@ -18,6 +18,7 @@ Rust MIR: a lowered representation of Rust. #![feature(decl_macro)] #![feature(exact_size_is_empty)] #![feature(exhaustive_patterns)] +#![feature(iter_zip)] #![feature(never_type)] #![feature(map_try_insert)] #![feature(min_specialization)] diff --git a/compiler/rustc_mir/src/transform/check_packed_ref.rs b/compiler/rustc_mir/src/transform/check_packed_ref.rs index ee88daa83e783..13b7221046bda 100644 --- a/compiler/rustc_mir/src/transform/check_packed_ref.rs +++ b/compiler/rustc_mir/src/transform/check_packed_ref.rs @@ -1,11 +1,18 @@ +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::*; +use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::UNALIGNED_REFERENCES; +use rustc_span::symbol::sym; use crate::transform::MirPass; use crate::util; +pub(crate) fn provide(providers: &mut Providers) { + *providers = Providers { unsafe_derive_on_repr_packed, ..*providers }; +} + pub struct CheckPackedRef; impl<'tcx> MirPass<'tcx> for CheckPackedRef { @@ -24,6 +31,41 @@ struct PackedRefChecker<'a, 'tcx> { source_info: SourceInfo, } +fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) { + let lint_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + + tcx.struct_span_lint_hir(UNALIGNED_REFERENCES, lint_hir_id, tcx.def_span(def_id), |lint| { + // FIXME: when we make this a hard error, this should have its + // own error code. + let message = if tcx.generics_of(def_id).own_requires_monomorphization() { + "`#[derive]` can't be used on a `#[repr(packed)]` struct with \ + type or const parameters (error E0133)" + .to_string() + } else { + "`#[derive]` can't be used on a `#[repr(packed)]` struct that \ + does not derive Copy (error E0133)" + .to_string() + }; + lint.build(&message).emit() + }); +} + +fn builtin_derive_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + debug!("builtin_derive_def_id({:?})", def_id); + if let Some(impl_def_id) = tcx.impl_of_method(def_id) { + if tcx.has_attr(impl_def_id, sym::automatically_derived) { + debug!("builtin_derive_def_id({:?}) - is {:?}", def_id, impl_def_id); + Some(impl_def_id) + } else { + debug!("builtin_derive_def_id({:?}) - not automatically derived", def_id); + None + } + } else { + debug!("builtin_derive_def_id({:?}) - not a method", def_id); + None + } +} + impl<'a, 'tcx> Visitor<'tcx> for PackedRefChecker<'a, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { // Make sure we know where in the MIR we are. @@ -40,26 +82,33 @@ impl<'a, 'tcx> Visitor<'tcx> for PackedRefChecker<'a, 'tcx> { fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { if context.is_borrow() { if util::is_disaligned(self.tcx, self.body, self.param_env, *place) { - let source_info = self.source_info; - let lint_root = self.body.source_scopes[source_info.scope] - .local_data - .as_ref() - .assert_crate_local() - .lint_root; - self.tcx.struct_span_lint_hir( - UNALIGNED_REFERENCES, - lint_root, - source_info.span, - |lint| { - lint.build("reference to packed field is unaligned") - .note( - "fields of packed structs are not properly aligned, and creating \ - a misaligned reference is undefined behavior (even if that \ - reference is never dereferenced)", - ) - .emit() - }, - ); + let def_id = self.body.source.instance.def_id(); + if let Some(impl_def_id) = builtin_derive_def_id(self.tcx, def_id) { + // If a method is defined in the local crate, + // the impl containing that method should also be. + self.tcx.ensure().unsafe_derive_on_repr_packed(impl_def_id.expect_local()); + } else { + let source_info = self.source_info; + let lint_root = self.body.source_scopes[source_info.scope] + .local_data + .as_ref() + .assert_crate_local() + .lint_root; + self.tcx.struct_span_lint_hir( + UNALIGNED_REFERENCES, + lint_root, + source_info.span, + |lint| { + lint.build("reference to packed field is unaligned") + .note( + "fields of packed structs are not properly aligned, and creating \ + a misaligned reference is undefined behavior (even if that \ + reference is never dereferenced)", + ) + .emit() + }, + ); + } } } } diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir/src/transform/check_unsafety.rs index 532d201e056d1..09da9b2e4d6ff 100644 --- a/compiler/rustc_mir/src/transform/check_unsafety.rs +++ b/compiler/rustc_mir/src/transform/check_unsafety.rs @@ -10,14 +10,12 @@ use rustc_middle::mir::*; use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; -use rustc_session::lint::builtin::{SAFE_PACKED_BORROWS, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; +use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::Level; -use rustc_span::symbol::sym; use std::ops::Bound; use crate::const_eval::is_min_const_fn; -use crate::util; pub struct UnsafetyChecker<'a, 'tcx> { body: &'a Body<'tcx>, @@ -182,18 +180,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.check_mut_borrowing_layout_constrained_field(*place, context.is_mutating_use()); } - // Check for borrows to packed fields. - // `is_disaligned` already traverses the place to consider all projections after the last - // `Deref`, so this only needs to be called once at the top level. - if context.is_borrow() { - if util::is_disaligned(self.tcx, self.body, self.param_env, *place) { - self.require_unsafe( - UnsafetyViolationKind::BorrowPacked, - UnsafetyViolationDetails::BorrowOfPackedField, - ); - } - } - // Some checks below need the extra metainfo of the local declaration. let decl = &self.body.local_decls[place.local]; @@ -317,25 +303,15 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { // `unsafe` blocks are required in safe code Safety::Safe => { for violation in violations { - let mut violation = *violation; match violation.kind { UnsafetyViolationKind::GeneralAndConstFn | UnsafetyViolationKind::General => {} - UnsafetyViolationKind::BorrowPacked => { - if self.min_const_fn { - // const fns don't need to be backwards compatible and can - // emit these violations as a hard error instead of a backwards - // compat lint - violation.kind = UnsafetyViolationKind::General; - } - } - UnsafetyViolationKind::UnsafeFn - | UnsafetyViolationKind::UnsafeFnBorrowPacked => { + UnsafetyViolationKind::UnsafeFn => { bug!("`UnsafetyViolationKind::UnsafeFn` in an `Safe` context") } } - if !self.violations.contains(&violation) { - self.violations.push(violation) + if !self.violations.contains(violation) { + self.violations.push(*violation) } } false @@ -345,11 +321,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { for violation in violations { let mut violation = *violation; - if violation.kind == UnsafetyViolationKind::BorrowPacked { - violation.kind = UnsafetyViolationKind::UnsafeFnBorrowPacked; - } else { - violation.kind = UnsafetyViolationKind::UnsafeFn; - } + violation.kind = UnsafetyViolationKind::UnsafeFn; if !self.violations.contains(&violation) { self.violations.push(violation) } @@ -369,8 +341,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { // these unsafe things are stable in const fn UnsafetyViolationKind::GeneralAndConstFn => {} // these things are forbidden in const fns - UnsafetyViolationKind::General - | UnsafetyViolationKind::BorrowPacked => { + UnsafetyViolationKind::General => { let mut violation = *violation; // const fns don't need to be backwards compatible and can // emit these violations as a hard error instead of a backwards @@ -380,8 +351,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { self.violations.push(violation) } } - UnsafetyViolationKind::UnsafeFn - | UnsafetyViolationKind::UnsafeFnBorrowPacked => bug!( + UnsafetyViolationKind::UnsafeFn => bug!( "`UnsafetyViolationKind::UnsafeFn` in an `ExplicitUnsafe` context" ), } @@ -464,7 +434,6 @@ pub(crate) fn provide(providers: &mut Providers) { ty::WithOptConstParam { did, const_param_did: Some(param_did) }, ) }, - unsafe_derive_on_repr_packed, ..*providers }; } @@ -544,25 +513,6 @@ fn unsafety_check_result<'tcx>( }) } -fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) { - let lint_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - - tcx.struct_span_lint_hir(SAFE_PACKED_BORROWS, lint_hir_id, tcx.def_span(def_id), |lint| { - // FIXME: when we make this a hard error, this should have its - // own error code. - let message = if tcx.generics_of(def_id).own_requires_monomorphization() { - "`#[derive]` can't be used on a `#[repr(packed)]` struct with \ - type or const parameters (error E0133)" - .to_string() - } else { - "`#[derive]` can't be used on a `#[repr(packed)]` struct that \ - does not derive Copy (error E0133)" - .to_string() - }; - lint.build(&message).emit() - }); -} - /// Returns the `HirId` for an enclosing scope that is also `unsafe`. fn is_enclosed( tcx: TyCtxt<'_>, @@ -609,22 +559,6 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, used_unsafe: &FxHashSet, id }); } -fn builtin_derive_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - debug!("builtin_derive_def_id({:?})", def_id); - if let Some(impl_def_id) = tcx.impl_of_method(def_id) { - if tcx.has_attr(impl_def_id, sym::automatically_derived) { - debug!("builtin_derive_def_id({:?}) - is {:?}", def_id, impl_def_id); - Some(impl_def_id) - } else { - debug!("builtin_derive_def_id({:?}) - not automatically derived", def_id); - None - } - } else { - debug!("builtin_derive_def_id({:?}) - not a method", def_id); - None - } -} - pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { debug!("check_unsafety({:?})", def_id); @@ -657,27 +591,6 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { .note(note) .emit(); } - UnsafetyViolationKind::BorrowPacked => { - if let Some(impl_def_id) = builtin_derive_def_id(tcx, def_id.to_def_id()) { - // If a method is defined in the local crate, - // the impl containing that method should also be. - tcx.ensure().unsafe_derive_on_repr_packed(impl_def_id.expect_local()); - } else { - tcx.struct_span_lint_hir( - SAFE_PACKED_BORROWS, - lint_root, - source_info.span, - |lint| { - lint.build(&format!( - "{} is unsafe and requires unsafe{} block (error E0133)", - description, unsafe_fn_msg, - )) - .note(note) - .emit() - }, - ) - } - } UnsafetyViolationKind::UnsafeFn => tcx.struct_span_lint_hir( UNSAFE_OP_IN_UNSAFE_FN, lint_root, @@ -692,35 +605,6 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { .emit(); }, ), - UnsafetyViolationKind::UnsafeFnBorrowPacked => { - // When `unsafe_op_in_unsafe_fn` is disallowed, the behavior of safe and unsafe functions - // should be the same in terms of warnings and errors. Therefore, with `#[warn(safe_packed_borrows)]`, - // a safe packed borrow should emit a warning *but not an error* in an unsafe function, - // just like in a safe function, even if `unsafe_op_in_unsafe_fn` is `deny`. - // - // Also, `#[warn(unsafe_op_in_unsafe_fn)]` can't cause any new errors. Therefore, with - // `#[deny(safe_packed_borrows)]` and `#[warn(unsafe_op_in_unsafe_fn)]`, a packed borrow - // should only issue a warning for the sake of backwards compatibility. - // - // The solution those 2 expectations is to always take the minimum of both lints. - // This prevent any new errors (unless both lints are explicitly set to `deny`). - let lint = if tcx.lint_level_at_node(SAFE_PACKED_BORROWS, lint_root).0 - <= tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, lint_root).0 - { - SAFE_PACKED_BORROWS - } else { - UNSAFE_OP_IN_UNSAFE_FN - }; - tcx.struct_span_lint_hir(&lint, lint_root, source_info.span, |lint| { - lint.build(&format!( - "{} is unsafe and requires unsafe block (error E0133)", - description, - )) - .span_label(source_info.span, description) - .note(note) - .emit(); - }) - } } } diff --git a/compiler/rustc_mir/src/transform/coverage/debug.rs b/compiler/rustc_mir/src/transform/coverage/debug.rs index aabfee53acb29..0e9728df73ca7 100644 --- a/compiler/rustc_mir/src/transform/coverage/debug.rs +++ b/compiler/rustc_mir/src/transform/coverage/debug.rs @@ -121,6 +121,7 @@ use rustc_middle::mir::coverage::*; use rustc_middle::mir::{self, BasicBlock, TerminatorKind}; use rustc_middle::ty::TyCtxt; +use std::iter; use std::lazy::SyncOnceCell; pub const NESTED_INDENT: &str = " "; @@ -703,9 +704,7 @@ pub(super) fn dump_coverage_graphviz( let edge_counters = from_terminator .successors() .map(|&successor_bb| graphviz_data.get_edge_counter(from_bcb, successor_bb)); - edge_labels - .iter() - .zip(edge_counters) + iter::zip(&edge_labels, edge_counters) .map(|(label, some_counter)| { if let Some(counter) = some_counter { format!("{}\n{}", label, debug_counters.format_counter(counter)) diff --git a/compiler/rustc_mir/src/transform/deduplicate_blocks.rs b/compiler/rustc_mir/src/transform/deduplicate_blocks.rs index e102512e1f37f..c41e71e09a4ef 100644 --- a/compiler/rustc_mir/src/transform/deduplicate_blocks.rs +++ b/compiler/rustc_mir/src/transform/deduplicate_blocks.rs @@ -1,7 +1,7 @@ //! This pass finds basic blocks that are completely equal, //! and replaces all uses with just one of them. -use std::{collections::hash_map::Entry, hash::Hash, hash::Hasher}; +use std::{collections::hash_map::Entry, hash::Hash, hash::Hasher, iter}; use crate::transform::MirPass; @@ -115,11 +115,7 @@ impl<'tcx, 'a> PartialEq for BasicBlockHashable<'tcx, 'a> { fn eq(&self, other: &Self) -> bool { self.basic_block_data.statements.len() == other.basic_block_data.statements.len() && &self.basic_block_data.terminator().kind == &other.basic_block_data.terminator().kind - && self - .basic_block_data - .statements - .iter() - .zip(&other.basic_block_data.statements) + && iter::zip(&self.basic_block_data.statements, &other.basic_block_data.statements) .all(|(x, y)| statement_eq(&x.kind, &y.kind)) } } diff --git a/compiler/rustc_mir/src/transform/match_branches.rs b/compiler/rustc_mir/src/transform/match_branches.rs index d04a7011ab064..f7a9835353e5c 100644 --- a/compiler/rustc_mir/src/transform/match_branches.rs +++ b/compiler/rustc_mir/src/transform/match_branches.rs @@ -1,6 +1,7 @@ use crate::transform::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use std::iter; use super::simplify::simplify_cfg; @@ -83,7 +84,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { if first_stmts.len() != scnd_stmts.len() { continue; } - for (f, s) in first_stmts.iter().zip(scnd_stmts.iter()) { + for (f, s) in iter::zip(first_stmts, scnd_stmts) { match (&f.kind, &s.kind) { // If two statements are exactly the same, we can optimize. (f_s, s_s) if f_s == s_s => {} @@ -113,7 +114,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { // and bb_idx has a different terminator from both of them. let (from, first, second) = bbs.pick3_mut(bb_idx, first, second); - let new_stmts = first.statements.iter().zip(second.statements.iter()).map(|(f, s)| { + let new_stmts = iter::zip(&first.statements, &second.statements).map(|(f, s)| { match (&f.kind, &s.kind) { (f_s, s_s) if f_s == s_s => (*f).clone(), diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index 66d2ab8a3f117..5c49ee69edc51 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -59,6 +59,7 @@ pub use rustc_middle::mir::MirSource; pub(crate) fn provide(providers: &mut Providers) { self::check_unsafety::provide(providers); + self::check_packed_ref::provide(providers); *providers = Providers { mir_keys, mir_const, diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index fbc9c30fe539c..589a4467dcae1 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -17,6 +17,8 @@ use rustc_target::abi::VariantIdx; use rustc_index::vec::Idx; +use std::iter; + /// The "outermost" place that holds this value. #[derive(Copy, Clone, Debug, PartialEq)] crate enum PlaceBase { @@ -140,7 +142,7 @@ fn is_ancestor_or_same_capture( return false; } - proj_possible_ancestor.iter().zip(proj_capture).all(|(a, b)| a == b) + iter::zip(proj_possible_ancestor, proj_capture).all(|(a, b)| a == b) } /// Computes the index of a capture within the desugared closure provided the closure's diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index fc92e8019c26e..2097f38c25d76 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -10,6 +10,7 @@ use rustc_hir as hir; use rustc_index::vec::Idx; use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; +use std::iter; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, storing the result into `destination`, which @@ -286,9 +287,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // MIR does not natively support FRU, so for each // base-supplied field, generate an operand that // reads it from the base. - field_names - .into_iter() - .zip(field_types.into_iter()) + iter::zip(field_names, *field_types) .map(|(n, ty)| match fields_map.get(&n) { Some(v) => v.clone(), None => { diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 9aca005ae9101..23bc1da09b555 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -9,6 +9,7 @@ #![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] #![feature(bool_to_option)] +#![feature(iter_zip)] #![feature(once_cell)] #![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 7512f46988c91..36a0fda645805 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -98,21 +98,46 @@ impl<'a> Parser<'a> { } impl CreateTokenStream for LazyTokenStreamImpl { fn create_token_stream(&self) -> TokenStream { - // The token produced by the final call to `next` or `next_desugared` - // was not actually consumed by the callback. The combination - // of chaining the initial token and using `take` produces the desired - // result - we produce an empty `TokenStream` if no calls were made, - // and omit the final token otherwise. + if self.num_calls == 0 { + return TokenStream::new(vec![]); + } + let mut cursor_snapshot = self.cursor_snapshot.clone(); - let tokens = std::iter::once(self.start_token.clone()) - .chain((0..self.num_calls).map(|_| { - if self.desugar_doc_comments { + // Don't skip `None` delimiters, since we want to pass them to + // proc macros. Normally, we'll end up capturing `TokenKind::Interpolated`, + // which gets converted to a `None`-delimited group when we invoke + // a proc-macro. However, it's possible to already have a `None`-delimited + // group in the stream (such as when parsing the output of a proc-macro, + // or in certain unusual cases with cross-crate `macro_rules!` macros). + cursor_snapshot.skip_none_delims = false; + + // The token produced by the final call to `next` or `next_desugared` + // was not actually consumed by the callback. + let num_calls = self.num_calls - 1; + let mut i = 0; + let tokens = + std::iter::once(self.start_token.clone()).chain(std::iter::from_fn(|| { + if i >= num_calls { + return None; + } + + let token = if self.desugar_doc_comments { cursor_snapshot.next_desugared() } else { cursor_snapshot.next() + }; + + // When the `LazyTokenStreamImpl` was original produced, we did *not* + // include `NoDelim` tokens in `num_calls`, since they are normally ignored + // by the parser. Therefore, we only increment our counter for other types of tokens. + if !matches!( + token.0.kind, + token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim) + ) { + i += 1; } - })) - .take(self.num_calls); + Some(token) + })); make_token_stream(tokens, self.append_unglued_token.clone()) } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index f0ee76d328c40..748a8e2bb490f 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -172,6 +172,13 @@ struct TokenCursor { // appended to the captured stream when // we evaluate a `LazyTokenStream` append_unglued_token: Option, + // If `true`, skip the delimiters for `None`-delimited groups, + // and just yield the inner tokens. This is `true` during + // normal parsing, since the parser code is not currently prepared + // to handle `None` delimiters. When capturing a `TokenStream`, + // however, we want to handle `None`-delimiters, since + // proc-macros always see `None`-delimited groups. + skip_none_delims: bool, } #[derive(Clone)] @@ -184,13 +191,13 @@ struct TokenCursorFrame { } impl TokenCursorFrame { - fn new(span: DelimSpan, delim: DelimToken, tts: TokenStream) -> Self { + fn new(span: DelimSpan, delim: DelimToken, tts: TokenStream, skip_none_delims: bool) -> Self { TokenCursorFrame { delim, span, - open_delim: delim == token::NoDelim, + open_delim: delim == token::NoDelim && skip_none_delims, tree_cursor: tts.into_trees(), - close_delim: delim == token::NoDelim, + close_delim: delim == token::NoDelim && skip_none_delims, } } } @@ -218,7 +225,7 @@ impl TokenCursor { return (token, spacing); } TokenTree::Delimited(sp, delim, tts) => { - let frame = TokenCursorFrame::new(sp, delim, tts); + let frame = TokenCursorFrame::new(sp, delim, tts, self.skip_none_delims); self.stack.push(mem::replace(&mut self.frame, frame)); } } @@ -276,6 +283,7 @@ impl TokenCursor { .cloned() .collect::() }, + self.skip_none_delims, ), )); @@ -371,12 +379,19 @@ impl<'a> Parser<'a> { prev_token: Token::dummy(), restrictions: Restrictions::empty(), expected_tokens: Vec::new(), + // Skip over the delimiters for `None`-delimited groups token_cursor: TokenCursor { - frame: TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens), + frame: TokenCursorFrame::new( + DelimSpan::dummy(), + token::NoDelim, + tokens, + /* skip_none_delims */ true, + ), stack: Vec::new(), num_next_calls: 0, desugar_doc_comments, append_unglued_token: None, + skip_none_delims: true, }, desugar_doc_comments, unmatched_angle_bracket_count: 0, diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 7ad6bd2bb3667..933e8ad1d727c 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -9,6 +9,7 @@ #![feature(const_panic)] #![feature(crate_visibility_modifier)] #![feature(in_band_lifetimes)] +#![feature(iter_zip)] #![feature(nll)] #![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 9aef49df7b4ff..f24309fa95021 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -103,6 +103,7 @@ use rustc_span::Span; use std::collections::VecDeque; use std::io; use std::io::prelude::*; +use std::iter; use std::rc::Rc; mod rwu_table; @@ -1093,7 +1094,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let ia = &asm.inner; let outputs = asm.outputs_exprs; let inputs = asm.inputs_exprs; - let succ = ia.outputs.iter().zip(outputs).rev().fold(succ, |succ, (o, output)| { + let succ = iter::zip(&ia.outputs, outputs).rev().fold(succ, |succ, (o, output)| { // see comment on places // in propagate_through_place_components() if o.is_indirect { @@ -1344,7 +1345,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) { } // Output operands must be places - for (o, output) in asm.inner.outputs.iter().zip(asm.outputs_exprs) { + for (o, output) in iter::zip(&asm.inner.outputs, asm.outputs_exprs) { if !o.is_indirect { this.check_place(output); } diff --git a/compiler/rustc_passes/src/liveness/rwu_table.rs b/compiler/rustc_passes/src/liveness/rwu_table.rs index a1a6f27398ec8..6d5983f53dc39 100644 --- a/compiler/rustc_passes/src/liveness/rwu_table.rs +++ b/compiler/rustc_passes/src/liveness/rwu_table.rs @@ -1,4 +1,5 @@ use crate::liveness::{LiveNode, Variable}; +use std::iter; #[derive(Clone, Copy)] pub(super) struct RWU { @@ -91,7 +92,7 @@ impl RWUTable { let mut changed = false; let (dst_row, src_row) = self.pick2_rows_mut(dst, src); - for (dst_word, src_word) in dst_row.iter_mut().zip(src_row.iter()) { + for (dst_word, src_word) in iter::zip(dst_row, &*src_row) { let old = *dst_word; let new = *dst_word | src_word; *dst_word = new; diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 8a6ac843534c6..e54b1796aaa55 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -22,6 +22,7 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use std::cmp::Ordering; +use std::iter; use std::mem::replace; use std::num::NonZeroU32; @@ -214,7 +215,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { { // Explicit version of iter::order::lt to handle parse errors properly for (dep_v, stab_v) in - dep_since.as_str().split('.').zip(stab_since.as_str().split('.')) + iter::zip(dep_since.as_str().split('.'), stab_since.as_str().split('.')) { match stab_v.parse::() { Err(_) => { diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index 26b76a9c006cd..3db57c0ab3a4c 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -3,6 +3,7 @@ #![feature(const_panic)] #![feature(core_intrinsics)] #![feature(hash_raw_entry)] +#![feature(iter_zip)] #![feature(min_specialization)] #![feature(stmt_expr_attributes)] diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 35a2ac865f259..21f580db04f28 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -22,7 +22,7 @@ use { rustc_data_structures::{jobserver, OnDrop}, rustc_rayon_core as rayon_core, rustc_span::DUMMY_SP, - std::iter::FromIterator, + std::iter::{self, FromIterator}, std::{mem, process}, }; @@ -463,7 +463,7 @@ fn remove_cycle( spans.rotate_right(1); // Zip them back together - let mut stack: Vec<_> = spans.into_iter().zip(queries).collect(); + let mut stack: Vec<_> = iter::zip(spans, queries).collect(); // Remove the queries in our cycle from the list of jobs to look at for r in &stack { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 4c0df2701f5e3..1fb07bdae9d00 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -22,6 +22,8 @@ use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; +use std::iter; + use tracing::debug; type Res = def::Res; @@ -1004,9 +1006,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { if let Some(spans) = field_spans.filter(|spans| spans.len() > 0 && fields.len() == spans.len()) { - let non_visible_spans: Vec = fields - .iter() - .zip(spans.iter()) + let non_visible_spans: Vec = iter::zip(&fields, &spans) .filter(|(vis, _)| { !self.r.is_accessible_from(**vis, self.parent_scope.module) }) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 14e3d8498b0d8..8210da7b6ce3c 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -14,6 +14,7 @@ #![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] #![feature(format_args_capture)] +#![feature(iter_zip)] #![feature(nll)] #![cfg_attr(bootstrap, feature(or_patterns))] #![recursion_limit = "256"] diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index eb5b7c4a74a1d..daecbe9225032 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -413,7 +413,7 @@ pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symb let names: Vec<_> = range_to_update.clone().map(|idx| get_name(SyntaxContext::from_u32(idx as u32))).collect(); HygieneData::with(|data| { - range_to_update.zip(names.into_iter()).for_each(|(idx, name)| { + range_to_update.zip(names).for_each(|(idx, name)| { data.syntax_context_data[idx].dollar_crate_name = name; }) }) diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index aeb7b149786e4..4097e1577e112 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -15,6 +15,7 @@ #![feature(box_patterns)] #![feature(drain_filter)] #![feature(in_band_lifetimes)] +#![feature(iter_zip)] #![feature(never_type)] #![feature(crate_visibility_modifier)] #![cfg_attr(bootstrap, feature(or_patterns))] diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 0d71fc57e394b..b38e3fbaab407 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -12,6 +12,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use std::collections::hash_map::Entry; use std::collections::VecDeque; +use std::iter; // FIXME(twk): this is obviously not nice to duplicate like that #[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)] @@ -428,7 +429,9 @@ impl AutoTraitFinder<'tcx> { return true; } - for (new_region, old_region) in new_substs.regions().zip(old_substs.regions()) { + for (new_region, old_region) in + iter::zip(new_substs.regions(), old_substs.regions()) + { match (new_region, old_region) { // If both predicates have an `ReLateBound` (a HRTB) in the // same spot, we do nothing. diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index e8ae1f44a3671..38cb4ee66cac5 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -74,23 +74,22 @@ where let impl2_ref = tcx.impl_trait_ref(impl2_def_id); // Check if any of the input types definitely do not unify. - if impl1_ref - .iter() - .flat_map(|tref| tref.substs.types()) - .zip(impl2_ref.iter().flat_map(|tref| tref.substs.types())) - .any(|(ty1, ty2)| { - let t1 = fast_reject::simplify_type(tcx, ty1, false); - let t2 = fast_reject::simplify_type(tcx, ty2, false); - if let (Some(t1), Some(t2)) = (t1, t2) { - // Simplified successfully - // Types cannot unify if they differ in their reference mutability or simplify to different types - t1 != t2 || ty1.ref_mutability() != ty2.ref_mutability() - } else { - // Types might unify - false - } - }) - { + if iter::zip( + impl1_ref.iter().flat_map(|tref| tref.substs.types()), + impl2_ref.iter().flat_map(|tref| tref.substs.types()), + ) + .any(|(ty1, ty2)| { + let t1 = fast_reject::simplify_type(tcx, ty1, false); + let t2 = fast_reject::simplify_type(tcx, ty2, false); + if let (Some(t1), Some(t2)) = (t1, t2) { + // Simplified successfully + // Types cannot unify if they differ in their reference mutability or simplify to different types + t1 != t2 || ty1.ref_mutability() != ty2.ref_mutability() + } else { + // Types might unify + false + } + }) { // Some types involved are definitely different, so the impls couldn't possibly overlap. debug!("overlapping_impls: fast_reject early-exit"); return no_overlap(); diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index ac987a9f7b384..8961cdaebf345 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -23,6 +23,7 @@ use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::Span; use std::cmp; +use std::iter; use std::ops::ControlFlow; /// Check if a given constant can be evaluated. @@ -672,9 +673,7 @@ pub(super) fn try_unify<'tcx>( if a_args.len() == b_args.len() => { try_unify(tcx, a.subtree(a_f), b.subtree(b_f)) - && a_args - .iter() - .zip(b_args) + && iter::zip(a_args, b_args) .all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn))) } _ => false, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 060e4e36dfefc..93a37bd40902d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -28,6 +28,7 @@ use rustc_session::DiagnosticMessageId; use rustc_span::symbol::{kw, sym}; use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP}; use std::fmt; +use std::iter; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::query::normalize::AtExt as _; @@ -161,7 +162,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } - for (error, suppressed) in errors.iter().zip(is_suppressed) { + for (error, suppressed) in iter::zip(errors, is_suppressed) { if !suppressed { self.report_fulfillment_error(error, body_id, fallback_has_occurred); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index cecdcc9789609..1ea34e5814e7c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -7,6 +7,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, GenericParamDefKind}; use rustc_span::symbol::sym; +use std::iter; use super::InferCtxtPrivExt; @@ -51,12 +52,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) { self_match_impls.push(def_id); - if trait_ref - .substs - .types() - .skip(1) - .zip(impl_trait_ref.substs.types().skip(1)) - .all(|(u, v)| self.fuzzy_match_tys(u, v)) + if iter::zip( + trait_ref.substs.types().skip(1), + impl_trait_ref.substs.types().skip(1), + ) + .all(|(u, v)| self.fuzzy_match_tys(u, v)) { fuzzy_match_impls.push(def_id); } @@ -163,61 +163,65 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { flags.push((sym::from_desugaring, None)); flags.push((sym::from_desugaring, Some(format!("{:?}", k)))); } - let generics = self.tcx.generics_of(def_id); - let self_ty = trait_ref.self_ty(); - // This is also included through the generics list as `Self`, - // but the parser won't allow you to use it - flags.push((sym::_Self, Some(self_ty.to_string()))); - if let Some(def) = self_ty.ty_adt_def() { - // We also want to be able to select self's original - // signature with no type arguments resolved - flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string()))); - } - for param in generics.params.iter() { - let value = match param.kind { - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { - trait_ref.substs[param.index as usize].to_string() - } - GenericParamDefKind::Lifetime => continue, - }; - let name = param.name; - flags.push((name, Some(value))); - } + // Add all types without trimmed paths. + ty::print::with_no_trimmed_paths(|| { + let generics = self.tcx.generics_of(def_id); + let self_ty = trait_ref.self_ty(); + // This is also included through the generics list as `Self`, + // but the parser won't allow you to use it + flags.push((sym::_Self, Some(self_ty.to_string()))); + if let Some(def) = self_ty.ty_adt_def() { + // We also want to be able to select self's original + // signature with no type arguments resolved + flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string()))); + } - if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) { - flags.push((sym::crate_local, None)); - } + for param in generics.params.iter() { + let value = match param.kind { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { + trait_ref.substs[param.index as usize].to_string() + } + GenericParamDefKind::Lifetime => continue, + }; + let name = param.name; + flags.push((name, Some(value))); + } - // Allow targeting all integers using `{integral}`, even if the exact type was resolved - if self_ty.is_integral() { - flags.push((sym::_Self, Some("{integral}".to_owned()))); - } + if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) { + flags.push((sym::crate_local, None)); + } - if let ty::Array(aty, len) = self_ty.kind() { - flags.push((sym::_Self, Some("[]".to_owned()))); - flags.push((sym::_Self, Some(format!("[{}]", aty)))); - if let Some(def) = aty.ty_adt_def() { - // We also want to be able to select the array's type's original - // signature with no type arguments resolved - let type_string = self.tcx.type_of(def.did).to_string(); - flags.push((sym::_Self, Some(format!("[{}]", type_string)))); + // Allow targeting all integers using `{integral}`, even if the exact type was resolved + if self_ty.is_integral() { + flags.push((sym::_Self, Some("{integral}".to_owned()))); + } - let len = len.val.try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx)); - let string = match len { - Some(n) => format!("[{}; {}]", type_string, n), - None => format!("[{}; _]", type_string), - }; - flags.push((sym::_Self, Some(string))); + if let ty::Array(aty, len) = self_ty.kind() { + flags.push((sym::_Self, Some("[]".to_owned()))); + flags.push((sym::_Self, Some(format!("[{}]", aty)))); + if let Some(def) = aty.ty_adt_def() { + // We also want to be able to select the array's type's original + // signature with no type arguments resolved + let type_string = self.tcx.type_of(def.did).to_string(); + flags.push((sym::_Self, Some(format!("[{}]", type_string)))); + + let len = len.val.try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx)); + let string = match len { + Some(n) => format!("[{}; {}]", type_string, n), + None => format!("[{}; _]", type_string), + }; + flags.push((sym::_Self, Some(string))); + } } - } - if let ty::Dynamic(traits, _) = self_ty.kind() { - for t in traits.iter() { - if let ty::ExistentialPredicate::Trait(trait_ref) = t.skip_binder() { - flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id)))) + if let ty::Dynamic(traits, _) = self_ty.kind() { + for t in traits.iter() { + if let ty::ExistentialPredicate::Trait(trait_ref) = t.skip_binder() { + flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id)))) + } } } - } + }); if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index bc8a0eae0e0ff..45680c90cdc17 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1887,7 +1887,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // substitution if we find that any of the input types, when // simplified, do not match. - obligation.predicate.skip_binder().trait_ref.substs.iter().zip(impl_trait_ref.substs).any( + iter::zip(obligation.predicate.skip_binder().trait_ref.substs, impl_trait_ref.substs).any( |(obligation_arg, impl_arg)| { match (obligation_arg.unpack(), impl_arg.unpack()) { (GenericArgKind::Type(obligation_ty), GenericArgKind::Type(impl_ty)) => { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index aee128dec7d12..3d5f8d128dc4b 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -692,11 +692,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let predicates = predicates.instantiate(self.infcx.tcx, substs); debug_assert_eq!(predicates.predicates.len(), origins.len()); - predicates - .predicates - .into_iter() - .zip(predicates.spans.into_iter()) - .zip(origins.into_iter().rev()) + iter::zip(iter::zip(predicates.predicates, predicates.spans), origins.into_iter().rev()) .map(|((pred, span), origin_def_id)| { let cause = self.cause(traits::BindingObligation(origin_def_id, span)); traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred) diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_typeck/src/astconv/errors.rs index b5404c3a15ce0..695132281c6ba 100644 --- a/compiler/rustc_typeck/src/astconv/errors.rs +++ b/compiler/rustc_typeck/src/astconv/errors.rs @@ -10,6 +10,7 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, DUMMY_SP}; use std::collections::BTreeSet; +use std::iter; impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// On missing type parameters, emit an E0393 error and provide a structured suggestion using @@ -309,7 +310,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // that the user forgot to give the associtated type's name. The canonical // example would be trying to use `Iterator` instead of // `Iterator`. - for (potential, item) in potential_assoc_types.iter().zip(assoc_items.iter()) { + for (potential, item) in iter::zip(&potential_assoc_types, assoc_items) { if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*potential) { suggestions.push((*potential, format!("{} = {}", item.ident, snippet))); } diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index a29f55180098a..b48102e0fc9b8 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -17,6 +17,7 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_target::spec::abi; use rustc_trait_selection::autoderef::Autoderef; +use std::iter; /// Checks that it is legal to call methods of the trait corresponding /// to `trait_id` (this only cares about the trait, not the specific @@ -539,7 +540,7 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> { debug!("attempt_resolution: method_callee={:?}", method_callee); for (method_arg_ty, self_arg_ty) in - method_sig.inputs().iter().skip(1).zip(self.fn_sig.inputs()) + iter::zip(method_sig.inputs().iter().skip(1), self.fn_sig.inputs()) { fcx.demand_eqtype(self.call_expr.span, &self_arg_ty, &method_arg_ty); } diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index e2fc1da5c786c..892abb5a34465 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -26,6 +26,7 @@ use rustc_trait_selection::opaque_types::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::{self, ObligationCauseCode}; +use std::iter; use std::ops::ControlFlow; pub fn check_wf_new(tcx: TyCtxt<'_>) { @@ -1472,7 +1473,7 @@ fn check_enum<'tcx>( } let mut disr_vals: Vec> = Vec::with_capacity(vs.len()); - for ((_, discr), v) in def.discriminants(tcx).zip(vs) { + for ((_, discr), v) in iter::zip(def.discriminants(tcx), vs) { // Check for duplicate discriminant values if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) { let variant_did = def.variants[VariantIdx::new(i)].def_id; diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 431e6d70ff35c..4099ecd435d51 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -492,13 +492,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The liberated version of this signature should be a subtype // of the liberated form of the expectation. - for ((hir_ty, &supplied_ty), expected_ty) in decl - .inputs - .iter() - .zip(supplied_sig.inputs().skip_binder()) // binder moved to (*) below - .zip(expected_sigs.liberated_sig.inputs()) - // `liberated_sig` is E'. - { + for ((hir_ty, &supplied_ty), expected_ty) in iter::zip( + iter::zip( + decl.inputs, + supplied_sig.inputs().skip_binder(), // binder moved to (*) below + ), + expected_sigs.liberated_sig.inputs(), // `liberated_sig` is E'. + ) { // Instantiate (this part of..) S to S', i.e., with fresh variables. let (supplied_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars( hir_ty.span, diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index ddb11b9f3b16b..70f850084a89f 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -14,6 +14,7 @@ use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; +use std::iter; use super::{potentially_plural_count, FnCtxt, Inherited}; @@ -410,8 +411,7 @@ fn extract_spans_for_error_reporting<'a, 'tcx>( _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m), }; - impl_m_iter - .zip(trait_m_iter) + iter::zip(impl_m_iter, trait_m_iter) .find(|&(ref impl_arg, ref trait_arg)| { match (&impl_arg.kind, &trait_arg.kind) { ( @@ -443,11 +443,8 @@ fn extract_spans_for_error_reporting<'a, 'tcx>( let impl_iter = impl_sig.inputs().iter(); let trait_iter = trait_sig.inputs().iter(); - impl_iter - .zip(trait_iter) - .zip(impl_m_iter) - .zip(trait_m_iter) - .find_map(|(((&impl_arg_ty, &trait_arg_ty), impl_arg), trait_arg)| match infcx + iter::zip(iter::zip(impl_iter, trait_iter), iter::zip(impl_m_iter, trait_m_iter)) + .find_map(|((&impl_arg_ty, &trait_arg_ty), (impl_arg, trait_arg))| match infcx .at(&cause, param_env) .sub(trait_arg_ty, impl_arg_ty) { @@ -799,7 +796,7 @@ fn compare_synthetic_generics<'tcx>( GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None, }); for ((impl_def_id, impl_synthetic), (trait_def_id, trait_synthetic)) in - impl_m_type_params.zip(trait_m_type_params) + iter::zip(impl_m_type_params, trait_m_type_params) { if impl_synthetic != trait_synthetic { let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_def_id.expect_local()); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 56ff9293dd87f..e64d8367676b0 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -42,6 +42,7 @@ use rustc_trait_selection::traits::{ }; use std::collections::hash_map::Entry; +use std::iter; use std::slice; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -1146,7 +1147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ( hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }), hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: exp_bounds, .. }), - ) if last_bounds.iter().zip(exp_bounds.iter()).all(|(left, right)| { + ) if iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| { match (left, right) { ( hir::GenericBound::Trait(tl, ml), diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index c92c7f7ad0b9a..80b5a9d4e621a 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -23,6 +23,7 @@ use rustc_span::{self, MultiSpan, Span}; use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpression}; use crate::structured_errors::StructuredDiagnostic; +use std::iter; use std::slice; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -108,7 +109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // All the input types from the fn signature must outlive the call // so as to validate implied bounds. - for (&fn_input_ty, arg_expr) in fn_inputs.iter().zip(args.iter()) { + for (&fn_input_ty, arg_expr) in iter::zip(fn_inputs, args) { self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation); } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index f90159efb5cd5..bd89c7274e77b 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -218,8 +218,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.is_hir_id_from_struct_pattern_shorthand_field(expr.hir_id, expr.span); let methods = self.get_conversion_methods(expr.span, expected, found, expr.hir_id); if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) { - let mut suggestions = iter::repeat(&expr_text) - .zip(methods.iter()) + let mut suggestions = iter::zip(iter::repeat(&expr_text), &methods) .filter_map(|(receiver, method)| { let method_call = format!(".{}()", method.ident); if receiver.ends_with(&method_call) { diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index 731a72ff024dc..fff659a91adfc 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -15,6 +15,7 @@ use rustc_middle::ty::{self, GenericParamDefKind, Ty}; use rustc_span::Span; use rustc_trait_selection::traits; +use std::iter; use std::ops::Deref; struct ConfirmContext<'a, 'tcx> { @@ -496,10 +497,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // We don't care about regions here. .filter_map(|obligation| match obligation.predicate.kind().skip_binder() { ty::PredicateKind::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => { - let span = predicates - .predicates - .iter() - .zip(predicates.spans.iter()) + let span = iter::zip(&predicates.predicates, &predicates.spans) .find_map( |(p, span)| { if *p == obligation.predicate { Some(*span) } else { None } diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 5a939cc24f5d6..91021b3f6f589 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -49,6 +49,8 @@ use rustc_span::{MultiSpan, Span, Symbol}; use rustc_index::vec::Idx; use rustc_target::abi::VariantIdx; +use std::iter; + /// Describe the relationship between the paths of two places /// eg: /// - `foo` is ancestor of `foo.bar.baz` @@ -1631,7 +1633,7 @@ fn determine_place_ancestry_relation( let projections_b = &place_b.projections; let same_initial_projections = - projections_a.iter().zip(projections_b.iter()).all(|(proj_a, proj_b)| proj_a == proj_b); + iter::zip(projections_a, projections_b).all(|(proj_a, proj_b)| proj_a == proj_b); if same_initial_projections { // First min(n, m) projections are the same diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 5f302f7d0a94e..e7e603c8bd510 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -24,6 +24,7 @@ use rustc_trait_selection::opaque_types::may_define_opaque_type; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; +use std::iter; use std::ops::ControlFlow; /// Helper type of a temporary returned by `.for_item(...)`. @@ -863,7 +864,7 @@ fn check_where_clauses<'tcx, 'fcx>( debug!("check_where_clauses: predicates={:?}", predicates.predicates); assert_eq!(predicates.predicates.len(), predicates.spans.len()); let wf_obligations = - predicates.predicates.iter().zip(predicates.spans.iter()).flat_map(|(&p, &sp)| { + iter::zip(&predicates.predicates, &predicates.spans).flat_map(|(&p, &sp)| { traits::wf::predicate_obligations(fcx, fcx.param_env, fcx.body_id, p, sp) }); @@ -885,8 +886,8 @@ fn check_fn_or_method<'fcx, 'tcx>( let sig = fcx.normalize_associated_types_in(span, sig); let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig); - for (&input_ty, span) in sig.inputs().iter().zip(hir_decl.inputs.iter().map(|t| t.span)) { - fcx.register_wf_obligation(input_ty.into(), span, ObligationCauseCode::MiscObligation); + for (&input_ty, ty) in iter::zip(sig.inputs(), hir_decl.inputs) { + fcx.register_wf_obligation(input_ty.into(), ty.span, ObligationCauseCode::MiscObligation); } implied_bounds.extend(sig.inputs()); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 631f2c7a69ad2..9b3a933beb13e 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -50,6 +50,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; +use std::iter; mod item_bounds; mod type_of; @@ -2439,7 +2440,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( .emit(); } }; - for (input, ty) in decl.inputs.iter().zip(fty.inputs().skip_binder()) { + for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) { check(&input, ty) } if let hir::FnRetTy::Return(ref ty) = decl.output { diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index b172cb9c44b70..ab286bacd8189 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -18,6 +18,7 @@ use rustc_middle::hir::place::ProjectionKind; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::{self, adjustment, TyCtxt}; use rustc_target::abi::VariantIdx; +use std::iter; use crate::mem_categorization as mc; @@ -333,7 +334,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } hir::ExprKind::LlvmInlineAsm(ref ia) => { - for (o, output) in ia.inner.outputs.iter().zip(ia.outputs_exprs) { + for (o, output) in iter::zip(&ia.inner.outputs, ia.outputs_exprs) { if o.is_indirect { self.consume_expr(output); } else { diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index c270a2368110a..cb442344fa21c 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -63,6 +63,7 @@ This API is completely unstable and subject to change. #![feature(format_args_capture)] #![feature(in_band_lifetimes)] #![feature(is_sorted)] +#![feature(iter_zip)] #![feature(nll)] #![cfg_attr(bootstrap, feature(or_patterns))] #![feature(try_blocks)] diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 40f2de8f70dd3..fb243100990b9 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -108,6 +108,7 @@ // that the feature-gate isn't enabled. Ideally, it wouldn't check for the feature gate for docs // from other crates, but since this can only appear for lang items, it doesn't seem worth fixing. #![feature(intra_doc_pointers)] +#![feature(iter_zip)] #![feature(lang_items)] #![feature(layout_for_ptr)] #![feature(maybe_uninit_ref)] diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index ff93c772b5b81..708898ad2e780 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -58,7 +58,7 @@ use core::convert::TryFrom; use core::fmt; use core::hash::{Hash, Hasher}; use core::intrinsics::{arith_offset, assume}; -use core::iter::FromIterator; +use core::iter::{self, FromIterator}; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop, MaybeUninit}; use core::ops::{self, Index, IndexMut, Range, RangeBounds}; @@ -2268,11 +2268,8 @@ impl ExtendFromWithinSpec for Vec { // - caller guaratees that src is a valid index let to_clone = unsafe { this.get_unchecked(src) }; - to_clone - .iter() - .cloned() - .zip(spare.iter_mut()) - .map(|(src, dst)| dst.write(src)) + iter::zip(to_clone, spare) + .map(|(src, dst)| dst.write(src.clone())) // Note: // - Element was just initialized with `MaybeUninit::write`, so it's ok to increace len // - len is increased after each element to prevent leaks (see issue #82533) diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index f82454addd09a..c36542f631488 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -2,7 +2,7 @@ use crate::{ fmt, - iter::{ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess}, + iter::{self, ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess}, mem::{self, MaybeUninit}, ops::Range, ptr, @@ -215,7 +215,7 @@ impl Clone for IntoIter { let mut new = Self { data: MaybeUninit::uninit_array(), alive: 0..0 }; // Clone all alive elements. - for (src, dst) in self.as_slice().iter().zip(&mut new.data) { + for (src, dst) in iter::zip(self.as_slice(), &mut new.data) { // Write a clone into the new array, then update its alive range. // If cloning panics, we'll correctly drop the previous items. dst.write(src.clone()); diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index d211ad4b2f7f4..d696ffa82774b 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -4,6 +4,7 @@ use crate::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell}; use crate::char::EscapeDebugExtArgs; +use crate::iter; use crate::marker::PhantomData; use crate::mem; use crate::num::flt2dec; @@ -1088,7 +1089,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { match args.fmt { None => { // We can use default formatting parameters for all arguments. - for (arg, piece) in args.args.iter().zip(args.pieces.iter()) { + for (arg, piece) in iter::zip(args.args, args.pieces) { formatter.buf.write_str(*piece)?; (arg.formatter)(arg.value, &mut formatter)?; idx += 1; @@ -1097,7 +1098,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { Some(fmt) => { // Every spec has a corresponding argument that is preceded by // a string piece. - for (arg, piece) in fmt.iter().zip(args.pieces.iter()) { + for (arg, piece) in iter::zip(fmt, args.pieces) { formatter.buf.write_str(*piece)?; // SAFETY: arg and args.args come from the same Arguments, // which guarantees the indexes are always within bounds. diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 41a7b13232adf..ba4050757cb94 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -51,6 +51,9 @@ pub use self::map_while::MapWhile; #[unstable(feature = "trusted_random_access", issue = "none")] pub use self::zip::TrustedRandomAccess; +#[unstable(feature = "iter_zip", issue = "83574")] +pub use self::zip::zip; + /// This trait provides transitive access to source-stage in an interator-adapter pipeline /// under the conditions that /// * the iterator source `S` itself implements `SourceIter` diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index ea7a809c6badb..2f8f504d8fcaa 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -5,8 +5,8 @@ use crate::iter::{InPlaceIterable, SourceIter, TrustedLen}; /// An iterator that iterates two other iterators simultaneously. /// -/// This `struct` is created by [`Iterator::zip`]. See its documentation -/// for more. +/// This `struct` is created by [`zip`] or [`Iterator::zip`]. +/// See their documentation for more. #[derive(Clone)] #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -33,6 +33,37 @@ impl Zip { } } +/// Converts the arguments to iterators and zips them. +/// +/// See the documentation of [`Iterator::zip`] for more. +/// +/// # Examples +/// +/// ``` +/// #![feature(iter_zip)] +/// use std::iter::zip; +/// +/// let xs = [1, 2, 3]; +/// let ys = [4, 5, 6]; +/// for (x, y) in zip(&xs, &ys) { +/// println!("x:{}, y:{}", x, y); +/// } +/// +/// // Nested zips are also possible: +/// let zs = [7, 8, 9]; +/// for ((x, y), z) in zip(zip(&xs, &ys), &zs) { +/// println!("x:{}, y:{}, z:{}", x, y, z); +/// } +/// ``` +#[unstable(feature = "iter_zip", issue = "83574")] +pub fn zip(a: A, b: B) -> Zip +where + A: IntoIterator, + B: IntoIterator, +{ + ZipImpl::new(a.into_iter(), b.into_iter()) +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Zip where diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index c57ba2bf62645..2a179f0b1d77b 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -389,6 +389,8 @@ pub use self::traits::{ DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, IntoIterator, Product, Sum, }; +#[unstable(feature = "iter_zip", issue = "83574")] +pub use self::adapters::zip; #[stable(feature = "iter_cloned", since = "1.1.0")] pub use self::adapters::Cloned; #[stable(feature = "iter_copied", since = "1.36.0")] diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 46e1a3a4aa2fe..e75a36477188c 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -81,8 +81,8 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} ), on( _Self = "[]", - label = "borrow the array with `&` or call `.iter()` on it to iterate over it", - note = "arrays are not iterators, but slices like the following are: `&[1, 2, 3]`" + label = "arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)`", + note = "see for more details" ), on( _Self = "{integral}", diff --git a/library/core/src/num/bignum.rs b/library/core/src/num/bignum.rs index 6a1a1e1976160..197b85fba1fd7 100644 --- a/library/core/src/num/bignum.rs +++ b/library/core/src/num/bignum.rs @@ -181,11 +181,12 @@ macro_rules! define_bignum { /// Adds `other` to itself and returns its own mutable reference. pub fn add<'a>(&'a mut self, other: &$name) -> &'a mut $name { use crate::cmp; + use crate::iter; use crate::num::bignum::FullOps; let mut sz = cmp::max(self.size, other.size); let mut carry = false; - for (a, b) in self.base[..sz].iter_mut().zip(&other.base[..sz]) { + for (a, b) in iter::zip(&mut self.base[..sz], &other.base[..sz]) { let (c, v) = (*a).full_add(*b, carry); *a = v; carry = c; @@ -219,11 +220,12 @@ macro_rules! define_bignum { /// Subtracts `other` from itself and returns its own mutable reference. pub fn sub<'a>(&'a mut self, other: &$name) -> &'a mut $name { use crate::cmp; + use crate::iter; use crate::num::bignum::FullOps; let sz = cmp::max(self.size, other.size); let mut noborrow = true; - for (a, b) in self.base[..sz].iter_mut().zip(&other.base[..sz]) { + for (a, b) in iter::zip(&mut self.base[..sz], &other.base[..sz]) { let (c, v) = (*a).full_add(!*b, noborrow); *a = v; noborrow = c; diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 7e4f8d570a73b..2392f0174b6f0 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -767,6 +767,7 @@ pub const unsafe fn read(src: *const T) -> T { /// unaligned: 0x01020304, /// }; /// +/// #[allow(unaligned_references)] /// let v = unsafe { /// // Here we attempt to take the address of a 32-bit integer which is not aligned. /// let unaligned = @@ -960,6 +961,7 @@ pub const unsafe fn write(dst: *mut T, src: T) { /// let v = 0x01020304; /// let mut packed: Packed = unsafe { std::mem::zeroed() }; /// +/// #[allow(unaligned_references)] /// let v = unsafe { /// // Here we attempt to take the address of a 32-bit integer which is not aligned. /// let unaligned = diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 42032bc9035bc..009ef9e0a9c1f 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -1,5 +1,6 @@ //! Operations on ASCII `[u8]`. +use crate::iter; use crate::mem; #[lang = "slice_u8"] @@ -19,7 +20,7 @@ impl [u8] { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool { - self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a.eq_ignore_ascii_case(b)) + self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b)) } /// Converts this slice to its ASCII upper case equivalent in-place. diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 2122aa755e157..97c92aa350696 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -269,6 +269,7 @@ impl Error { /// This function should maybe change to /// `new_const(kind: ErrorKind)` /// in the future, when const generics allow that. + #[inline] pub(crate) const fn new_const(kind: ErrorKind, message: &'static &'static str) -> Error { Self { repr: Repr::SimpleMessage(kind, message) } } @@ -287,6 +288,7 @@ impl Error { /// println!("last OS error: {:?}", Error::last_os_error()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn last_os_error() -> Error { Error::from_raw_os_error(sys::os::errno() as i32) } @@ -317,6 +319,7 @@ impl Error { /// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn from_raw_os_error(code: i32) -> Error { Error { repr: Repr::Os(code) } } @@ -351,6 +354,7 @@ impl Error { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn raw_os_error(&self) -> Option { match self.repr { Repr::Os(i) => Some(i), @@ -388,6 +392,7 @@ impl Error { /// } /// ``` #[stable(feature = "io_error_inner", since = "1.3.0")] + #[inline] pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> { match self.repr { Repr::Os(..) => None, @@ -460,6 +465,7 @@ impl Error { /// } /// ``` #[stable(feature = "io_error_inner", since = "1.3.0")] + #[inline] pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'static)> { match self.repr { Repr::Os(..) => None, @@ -497,6 +503,7 @@ impl Error { /// } /// ``` #[stable(feature = "io_error_inner", since = "1.3.0")] + #[inline] pub fn into_inner(self) -> Option> { match self.repr { Repr::Os(..) => None, @@ -525,6 +532,7 @@ impl Error { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn kind(&self) -> ErrorKind { match self.repr { Repr::Os(code) => sys::decode_error_kind(code), diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 8b34fb0505517..3719eeb1840be 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -278,6 +278,7 @@ #![feature(integer_atomics)] #![feature(into_future)] #![feature(intra_doc_pointers)] +#![feature(iter_zip)] #![feature(lang_items)] #![feature(link_args)] #![feature(linkage)] diff --git a/library/std/src/sys/unix/ext/net/addr.rs b/library/std/src/sys/unix/ext/net/addr.rs index 6e7d1f1678a9e..459f3590e6470 100644 --- a/library/std/src/sys/unix/ext/net/addr.rs +++ b/library/std/src/sys/unix/ext/net/addr.rs @@ -2,7 +2,7 @@ use crate::ffi::OsStr; use crate::os::unix::ffi::OsStrExt; use crate::path::Path; use crate::sys::cvt; -use crate::{ascii, fmt, io, mem}; +use crate::{ascii, fmt, io, iter, mem}; // FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here? #[cfg(not(unix))] @@ -41,7 +41,7 @@ pub(super) unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, &"path must be shorter than SUN_LEN", )); } - for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) { + for (dst, src) in iter::zip(&mut addr.sun_path, bytes) { *dst = *src as libc::c_char; } // null byte for pathname addresses is already there because we zeroed the diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index f25a6280cd076..759565bab73f3 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -2,7 +2,7 @@ use crate::os::unix::prelude::*; use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; -use crate::io::{self, Error, ErrorKind, IoSlice, IoSliceMut, SeekFrom}; +use crate::io::{self, Error, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::path::{Path, PathBuf}; use crate::ptr; @@ -1152,14 +1152,12 @@ pub fn canonicalize(p: &Path) -> io::Result { fn open_from(from: &Path) -> io::Result<(crate::fs::File, crate::fs::Metadata)> { use crate::fs::File; + use crate::sys_common::fs::NOT_FILE_ERROR; let reader = File::open(from)?; let metadata = reader.metadata()?; if !metadata.is_file() { - return Err(Error::new_const( - ErrorKind::InvalidInput, - &"the source path is not an existing regular file", - )); + return Err(NOT_FILE_ERROR); } Ok((reader, metadata)) } diff --git a/library/std/src/sys_common/fs.rs b/library/std/src/sys_common/fs.rs index 92d0cc60850c6..30908824dd663 100644 --- a/library/std/src/sys_common/fs.rs +++ b/library/std/src/sys_common/fs.rs @@ -4,15 +4,17 @@ use crate::fs; use crate::io::{self, Error, ErrorKind}; use crate::path::Path; +pub(crate) const NOT_FILE_ERROR: Error = Error::new_const( + ErrorKind::InvalidInput, + &"the source path is neither a regular file nor a symlink to a regular file", +); + pub fn copy(from: &Path, to: &Path) -> io::Result { let mut reader = fs::File::open(from)?; let metadata = reader.metadata()?; if !metadata.is_file() { - return Err(Error::new_const( - ErrorKind::InvalidInput, - &"the source path is not an existing regular file", - )); + return Err(NOT_FILE_ERROR); } let mut writer = fs::File::create(to)?; diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 1b6a82fed1170..001c8b090448b 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -54,12 +54,10 @@ impl DocFolder for SourceCollector<'_, '_> { self.scx.include_sources = match self.emit_source(&filename) { Ok(()) => true, Err(e) => { - println!( - "warning: source code was requested to be rendered, \ - but processing `{}` had an error: {}", - filename, e + self.scx.tcx.sess.span_err( + item.span.inner(), + &format!("failed to render source code for `{}`: {}", filename, e), ); - println!(" skipping rendering of source code"); false } }; diff --git a/src/test/ui/binding/issue-53114-safety-checks.rs b/src/test/ui/binding/issue-53114-safety-checks.rs index 28adb7571a98b..ca4f0efd2392b 100644 --- a/src/test/ui/binding/issue-53114-safety-checks.rs +++ b/src/test/ui/binding/issue-53114-safety-checks.rs @@ -20,13 +20,13 @@ fn let_wild_gets_unsafe_field() { let u1 = U { a: I(0) }; let u2 = U { a: I(1) }; let p = P { a: &2, b: &3 }; - let _ = &p.b; //~ WARN E0133 + let _ = &p.b; //~ WARN reference to packed field //~^ WARN will become a hard error let _ = u1.a; // #53114: should eventually signal error as well let _ = &u2.a; //~ ERROR [E0133] // variation on above with `_` in substructure - let (_,) = (&p.b,); //~ WARN E0133 + let (_,) = (&p.b,); //~ WARN reference to packed field //~^ WARN will become a hard error let (_,) = (u1.a,); //~ ERROR [E0133] let (_,) = (&u2.a,); //~ ERROR [E0133] @@ -36,13 +36,13 @@ fn match_unsafe_field_to_wild() { let u1 = U { a: I(0) }; let u2 = U { a: I(1) }; let p = P { a: &2, b: &3 }; - match &p.b { _ => { } } //~ WARN E0133 + match &p.b { _ => { } } //~ WARN reference to packed field //~^ WARN will become a hard error match u1.a { _ => { } } //~ ERROR [E0133] match &u2.a { _ => { } } //~ ERROR [E0133] // variation on above with `_` in substructure - match (&p.b,) { (_,) => { } } //~ WARN E0133 + match (&p.b,) { (_,) => { } } //~ WARN reference to packed field //~^ WARN will become a hard error match (u1.a,) { (_,) => { } } //~ ERROR [E0133] match (&u2.a,) { (_,) => { } } //~ ERROR [E0133] diff --git a/src/test/ui/binding/issue-53114-safety-checks.stderr b/src/test/ui/binding/issue-53114-safety-checks.stderr index d4b8dfbade5d6..9e7deea4524cb 100644 --- a/src/test/ui/binding/issue-53114-safety-checks.stderr +++ b/src/test/ui/binding/issue-53114-safety-checks.stderr @@ -1,13 +1,43 @@ -warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133) +warning: reference to packed field is unaligned --> $DIR/issue-53114-safety-checks.rs:23:13 | LL | let _ = &p.b; | ^^^^ | - = note: `#[warn(safe_packed_borrows)]` on by default + = note: `#[warn(unaligned_references)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #46043 - = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + +warning: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:29:17 + | +LL | let (_,) = (&p.b,); + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + +warning: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:39:11 + | +LL | match &p.b { _ => { } } + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + +warning: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:45:12 + | +LL | match (&p.b,) { (_,) => { } } + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) error[E0133]: access to union field is unsafe and requires unsafe function or block --> $DIR/issue-53114-safety-checks.rs:26:13 @@ -17,16 +47,6 @@ LL | let _ = &u2.a; | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133) - --> $DIR/issue-53114-safety-checks.rs:29:17 - | -LL | let (_,) = (&p.b,); - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #46043 - = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior - error[E0133]: access to union field is unsafe and requires unsafe function or block --> $DIR/issue-53114-safety-checks.rs:31:17 | @@ -43,16 +63,6 @@ LL | let (_,) = (&u2.a,); | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133) - --> $DIR/issue-53114-safety-checks.rs:39:11 - | -LL | match &p.b { _ => { } } - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #46043 - = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior - error[E0133]: access to union field is unsafe and requires unsafe function or block --> $DIR/issue-53114-safety-checks.rs:41:11 | @@ -69,16 +79,6 @@ LL | match &u2.a { _ => { } } | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133) - --> $DIR/issue-53114-safety-checks.rs:45:12 - | -LL | match (&p.b,) { (_,) => { } } - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #46043 - = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior - error[E0133]: access to union field is unsafe and requires unsafe function or block --> $DIR/issue-53114-safety-checks.rs:47:12 | diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs index 6fce295150582..82ec60a2e790a 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs @@ -23,7 +23,7 @@ fn test_missing_unsafe_warning_on_repr_packed() { let c = || { println!("{}", foo.x); - //~^ WARNING: borrow of packed field is unsafe and requires unsafe function or block + //~^ WARNING: reference to packed field is unaligned //~| WARNING: this was previously accepted by the compiler but is being phased out let _z = foo.x; }; diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr index 440b2c54c0a01..e8cc164be8754 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr @@ -7,16 +7,16 @@ LL | #![feature(capture_disjoint_fields)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #53488 for more information -warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133) +warning: reference to packed field is unaligned --> $DIR/repr_packed.rs:25:24 | LL | println!("{}", foo.x); | ^^^^^ | - = note: `#[warn(safe_packed_borrows)]` on by default + = note: `#[warn(unaligned_references)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #46043 - = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) warning: 2 warnings emitted diff --git a/src/test/ui/const-generics/issues/issue-69654-run-pass.rs b/src/test/ui/const-generics/issues/issue-69654-run-pass.rs index bbfd2183b06e3..45318ca68fcc5 100644 --- a/src/test/ui/const-generics/issues/issue-69654-run-pass.rs +++ b/src/test/ui/const-generics/issues/issue-69654-run-pass.rs @@ -1,4 +1,3 @@ -// run-pass #![feature(const_generics)] #![allow(incomplete_features, unused_braces)] @@ -15,4 +14,5 @@ where fn main() { Foo::foo(); + //~^ ERROR the function or associated item } diff --git a/src/test/ui/const-generics/issues/issue-69654-run-pass.stderr b/src/test/ui/const-generics/issues/issue-69654-run-pass.stderr new file mode 100644 index 0000000000000..a82a60696b36b --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-69654-run-pass.stderr @@ -0,0 +1,15 @@ +error[E0599]: the function or associated item `foo` exists for struct `Foo<{_: usize}>`, but its trait bounds were not satisfied + --> $DIR/issue-69654-run-pass.rs:16:10 + | +LL | struct Foo {} + | -------------------------- function or associated item `foo` not found for this +... +LL | Foo::foo(); + | ^^^ function or associated item cannot be called on `Foo<{_: usize}>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `[u8; _]: Bar<[(); _]>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/const-generics/issues/issue-69654.rs b/src/test/ui/const-generics/issues/issue-69654.rs index 7e775999ebd10..b1214b12a1440 100644 --- a/src/test/ui/const-generics/issues/issue-69654.rs +++ b/src/test/ui/const-generics/issues/issue-69654.rs @@ -15,4 +15,5 @@ where fn main() { Foo::foo(); + //~^ ERROR the function or associated item } diff --git a/src/test/ui/const-generics/issues/issue-69654.stderr b/src/test/ui/const-generics/issues/issue-69654.stderr index 70af7bf25d849..0ce7640f68577 100644 --- a/src/test/ui/const-generics/issues/issue-69654.stderr +++ b/src/test/ui/const-generics/issues/issue-69654.stderr @@ -4,6 +4,19 @@ error[E0423]: expected value, found type parameter `T` LL | impl Bar for [u8; T] {} | ^ not a value -error: aborting due to previous error +error[E0599]: the function or associated item `foo` exists for struct `Foo<{_: usize}>`, but its trait bounds were not satisfied + --> $DIR/issue-69654.rs:17:10 + | +LL | struct Foo {} + | -------------------------- function or associated item `foo` not found for this +... +LL | Foo::foo(); + | ^^^ function or associated item cannot be called on `Foo<{_: usize}>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `[u8; _]: Bar<[(); _]>` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0423`. +Some errors have detailed explanations: E0423, E0599. +For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-1.rs b/src/test/ui/const-generics/occurs-check/unused-substs-1.rs index f56687ecd9329..6ded9f13bc4fa 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-1.rs +++ b/src/test/ui/const-generics/occurs-check/unused-substs-1.rs @@ -1,4 +1,3 @@ -// build-pass #![feature(const_generics)] #![allow(incomplete_features)] @@ -10,5 +9,5 @@ where A: Bar; fn main() { - let _ = A; + let _ = A; //~ERROR the trait bound } diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr new file mode 100644 index 0000000000000..6830288acc0ad --- /dev/null +++ b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `A<{_: usize}>: Bar<{_: usize}>` is not satisfied + --> $DIR/unused-substs-1.rs:12:13 + | +LL | / struct A +LL | | where +LL | | A: Bar; + | |_________________- required by `A` +... +LL | let _ = A; + | ^ the trait `Bar<{_: usize}>` is not implemented for `A<{_: usize}>` + | + = help: the following implementations were found: + as Bar> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-2.rs b/src/test/ui/const-generics/occurs-check/unused-substs-2.rs index 12444ec5312d9..2d00141fbf70b 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-2.rs +++ b/src/test/ui/const-generics/occurs-check/unused-substs-2.rs @@ -1,4 +1,3 @@ -// check-pass #![feature(const_generics)] #![allow(incomplete_features)] @@ -24,4 +23,6 @@ fn main() { // `t` is `ty::Infer(TyVar(_#1t))` // `foo` contains `ty::Infer(TyVar(_#1t))` in its substs t = foo; + //~^ ERROR mismatched types + //~| NOTE cyclic type } diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-2.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-2.stderr new file mode 100644 index 0000000000000..9532fc21a31b7 --- /dev/null +++ b/src/test/ui/const-generics/occurs-check/unused-substs-2.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-2.rs:25:9 + | +LL | t = foo; + | ^^^ cyclic type of infinite size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-3.rs b/src/test/ui/const-generics/occurs-check/unused-substs-3.rs index 187e27382fcf2..2e306f8c4c88f 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-3.rs +++ b/src/test/ui/const-generics/occurs-check/unused-substs-3.rs @@ -1,4 +1,3 @@ -// check-pass #![feature(const_generics)] #![allow(incomplete_features)] @@ -15,4 +14,6 @@ fn main() { // `t` is `ty::Infer(TyVar(_#1t))` // `foo` contains `ty::Infer(TyVar(_#1t))` in its substs t = foo; + //~^ ERROR mismatched types + //~| NOTE cyclic type } diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-3.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-3.stderr new file mode 100644 index 0000000000000..2551d68f97474 --- /dev/null +++ b/src/test/ui/const-generics/occurs-check/unused-substs-3.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-3.rs:16:9 + | +LL | t = foo; + | ^^^ + | | + | cyclic type of infinite size + | help: try using a conversion method: `foo.to_vec()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-4.rs b/src/test/ui/const-generics/occurs-check/unused-substs-4.rs index 8e42ceb6d70e9..9c7f5ab91edb1 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-4.rs +++ b/src/test/ui/const-generics/occurs-check/unused-substs-4.rs @@ -1,4 +1,3 @@ -// build-pass #![feature(const_generics)] #![allow(incomplete_features)] @@ -8,5 +7,5 @@ fn bind(value: [u8; N]) -> [u8; 3 + 4] { fn main() { let mut arr = Default::default(); - arr = bind(arr); + arr = bind(arr); //~ ERROR mismatched type } diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-4.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-4.stderr new file mode 100644 index 0000000000000..5685eedbdeca8 --- /dev/null +++ b/src/test/ui/const-generics/occurs-check/unused-substs-4.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-4.rs:10:11 + | +LL | arr = bind(arr); + | ^^^^^^^^^ encountered a self-referencing constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/derives/deriving-with-repr-packed.rs b/src/test/ui/derives/deriving-with-repr-packed.rs index d354cef66bc06..b78eeaa90551b 100644 --- a/src/test/ui/derives/deriving-with-repr-packed.rs +++ b/src/test/ui/derives/deriving-with-repr-packed.rs @@ -1,4 +1,4 @@ -#![deny(safe_packed_borrows)] +#![deny(unaligned_references)] // check that derive on a packed struct with non-Copy fields // correctly. This can't be made to work perfectly because diff --git a/src/test/ui/derives/deriving-with-repr-packed.stderr b/src/test/ui/derives/deriving-with-repr-packed.stderr index d739257c8de63..3caa563a08560 100644 --- a/src/test/ui/derives/deriving-with-repr-packed.stderr +++ b/src/test/ui/derives/deriving-with-repr-packed.stderr @@ -7,10 +7,10 @@ LL | #[derive(Copy, Clone, PartialEq, Eq)] note: the lint level is defined here --> $DIR/deriving-with-repr-packed.rs:1:9 | -LL | #![deny(safe_packed_borrows)] - | ^^^^^^^^^^^^^^^^^^^ +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #46043 + = note: for more information, see issue #82523 = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133) @@ -20,7 +20,7 @@ LL | #[derive(Copy, Clone, PartialEq, Eq)] | ^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #46043 + = note: for more information, see issue #82523 = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133) @@ -30,7 +30,7 @@ LL | #[derive(PartialEq, Eq)] | ^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #46043 + = note: for more information, see issue #82523 = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133) @@ -40,7 +40,7 @@ LL | #[derive(PartialEq)] | ^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #46043 + = note: for more information, see issue #82523 = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-27060-rpass.rs b/src/test/ui/issues/issue-27060-rpass.rs index b20d614b3036b..d9159f6669d60 100644 --- a/src/test/ui/issues/issue-27060-rpass.rs +++ b/src/test/ui/issues/issue-27060-rpass.rs @@ -8,14 +8,12 @@ pub struct Good { } // kill this test when that turns to a hard error -#[allow(safe_packed_borrows)] +#[allow(unaligned_references)] fn main() { let good = Good { data: &0, data2: [&0, &0], aligned: [0; 32] }; - unsafe { - let _ = &good.data; // ok - let _ = &good.data2[0]; // ok - } + let _ = &good.data; // ok + let _ = &good.data2[0]; // ok let _ = &good.data; let _ = &good.data2[0]; diff --git a/src/test/ui/issues/issue-27060.rs b/src/test/ui/issues/issue-27060.rs index 78f2022ed38df..5317a61671945 100644 --- a/src/test/ui/issues/issue-27060.rs +++ b/src/test/ui/issues/issue-27060.rs @@ -5,7 +5,7 @@ pub struct Good { aligned: [u8; 32], } -#[deny(safe_packed_borrows)] +#[deny(unaligned_references)] fn main() { let good = Good { data: &0, @@ -13,14 +13,14 @@ fn main() { aligned: [0; 32] }; - unsafe { - let _ = &good.data; // ok - let _ = &good.data2[0]; // ok - } + let _ = &good.data; //~ ERROR reference to packed field + //~| hard error + let _ = &good.data2[0]; //~ ERROR reference to packed field + //~| hard error - let _ = &good.data; //~ ERROR borrow of packed field is unsafe + let _ = &good.data; //~ ERROR reference to packed field //~| hard error - let _ = &good.data2[0]; //~ ERROR borrow of packed field is unsafe + let _ = &good.data2[0]; //~ ERROR reference to packed field //~| hard error let _ = &*good.data; // ok, behind a pointer let _ = &good.aligned; // ok, has align 1 diff --git a/src/test/ui/issues/issue-27060.stderr b/src/test/ui/issues/issue-27060.stderr index d14ae4d41d5c5..09297884ed377 100644 --- a/src/test/ui/issues/issue-27060.stderr +++ b/src/test/ui/issues/issue-27060.stderr @@ -1,5 +1,5 @@ -error: borrow of packed field is unsafe and requires unsafe function or block (error E0133) - --> $DIR/issue-27060.rs:21:13 +error: reference to packed field is unaligned + --> $DIR/issue-27060.rs:16:13 | LL | let _ = &good.data; | ^^^^^^^^^^ @@ -7,21 +7,41 @@ LL | let _ = &good.data; note: the lint level is defined here --> $DIR/issue-27060.rs:8:8 | -LL | #[deny(safe_packed_borrows)] - | ^^^^^^^^^^^^^^^^^^^ +LL | #[deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + +error: reference to packed field is unaligned + --> $DIR/issue-27060.rs:18:13 + | +LL | let _ = &good.data2[0]; + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + +error: reference to packed field is unaligned + --> $DIR/issue-27060.rs:21:13 + | +LL | let _ = &good.data; + | ^^^^^^^^^^ + | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #46043 - = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) -error: borrow of packed field is unsafe and requires unsafe function or block (error E0133) +error: reference to packed field is unaligned --> $DIR/issue-27060.rs:23:13 | LL | let _ = &good.data2[0]; | ^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #46043 - = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors diff --git a/src/test/ui/iterators/array-of-ranges.stderr b/src/test/ui/iterators/array-of-ranges.stderr index 601983a6153fd..7d58eb948ea81 100644 --- a/src/test/ui/iterators/array-of-ranges.stderr +++ b/src/test/ui/iterators/array-of-ranges.stderr @@ -13,10 +13,10 @@ error[E0277]: `[RangeInclusive<{integer}>; 1]` is not an iterator --> $DIR/array-of-ranges.rs:4:14 | LL | for _ in [0..=1] {} - | ^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^^^^^^^ if you meant to iterate between two values, remove the square brackets | = help: the trait `Iterator` is not implemented for `[RangeInclusive<{integer}>; 1]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: `[start..=end]` is an array of one `RangeInclusive`; you might have meant to have a `RangeInclusive` without the brackets: `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `[RangeInclusive<{integer}>; 1]` = note: required by `into_iter` @@ -24,10 +24,10 @@ error[E0277]: `[RangeFrom<{integer}>; 1]` is not an iterator --> $DIR/array-of-ranges.rs:6:14 | LL | for _ in [0..] {} - | ^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^^^^^ if you meant to iterate from a value onwards, remove the square brackets | = help: the trait `Iterator` is not implemented for `[RangeFrom<{integer}>; 1]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: `[start..]` is an array of one `RangeFrom`; you might have meant to have a `RangeFrom` without the brackets: `start..`, keeping in mind that iterating over an unbounded iterator will run forever unless you `break` or `return` from within the loop = note: required because of the requirements on the impl of `IntoIterator` for `[RangeFrom<{integer}>; 1]` = note: required by `into_iter` @@ -35,10 +35,10 @@ error[E0277]: `[RangeTo<{integer}>; 1]` is not an iterator --> $DIR/array-of-ranges.rs:8:14 | LL | for _ in [..1] {} - | ^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^^^^^ if you meant to iterate until a value, remove the square brackets and add a starting value | = help: the trait `Iterator` is not implemented for `[RangeTo<{integer}>; 1]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: `[..end]` is an array of one `RangeTo`; you might have meant to have a bounded `Range` without the brackets: `0..end` = note: required because of the requirements on the impl of `IntoIterator` for `[RangeTo<{integer}>; 1]` = note: required by `into_iter` @@ -46,10 +46,10 @@ error[E0277]: `[RangeToInclusive<{integer}>; 1]` is not an iterator --> $DIR/array-of-ranges.rs:10:14 | LL | for _ in [..=1] {} - | ^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^^^^^^ if you meant to iterate until a value (including it), remove the square brackets and add a starting value | = help: the trait `Iterator` is not implemented for `[RangeToInclusive<{integer}>; 1]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: `[..=end]` is an array of one `RangeToInclusive`; you might have meant to have a bounded `RangeInclusive` without the brackets: `0..=end` = note: required because of the requirements on the impl of `IntoIterator` for `[RangeToInclusive<{integer}>; 1]` = note: required by `into_iter` @@ -79,10 +79,10 @@ error[E0277]: `[std::ops::Range<{integer}>; 2]` is not an iterator --> $DIR/array-of-ranges.rs:19:14 | LL | for _ in [0..1, 2..3] {} - | ^^^^^^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^^^^^^^^^^^^ arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)` | = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 2]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: see for more details = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 2]` = note: required by `into_iter` @@ -90,10 +90,10 @@ error[E0277]: `[RangeInclusive<{integer}>; 1]` is not an iterator --> $DIR/array-of-ranges.rs:21:14 | LL | for _ in [0..=1] {} - | ^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^^^^^^^ if you meant to iterate between two values, remove the square brackets | = help: the trait `Iterator` is not implemented for `[RangeInclusive<{integer}>; 1]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: `[start..=end]` is an array of one `RangeInclusive`; you might have meant to have a `RangeInclusive` without the brackets: `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `[RangeInclusive<{integer}>; 1]` = note: required by `into_iter` diff --git a/src/test/ui/iterators/array.stderr b/src/test/ui/iterators/array.stderr index 68c6de5493f13..7e2b600fb7af2 100644 --- a/src/test/ui/iterators/array.stderr +++ b/src/test/ui/iterators/array.stderr @@ -2,10 +2,10 @@ error[E0277]: `[{integer}; 2]` is not an iterator --> $DIR/array.rs:2:14 | LL | for _ in [1, 2] {} - | ^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^^^^^^ arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)` | = help: the trait `Iterator` is not implemented for `[{integer}; 2]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: see for more details = note: required because of the requirements on the impl of `IntoIterator` for `[{integer}; 2]` = note: required by `into_iter` @@ -13,10 +13,10 @@ error[E0277]: `[{integer}; 2]` is not an iterator --> $DIR/array.rs:5:14 | LL | for _ in x {} - | ^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^ arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)` | = help: the trait `Iterator` is not implemented for `[{integer}; 2]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: see for more details = note: required because of the requirements on the impl of `IntoIterator` for `[{integer}; 2]` = note: required by `into_iter` @@ -24,10 +24,10 @@ error[E0277]: `[{float}; 2]` is not an iterator --> $DIR/array.rs:7:14 | LL | for _ in [1.0, 2.0] {} - | ^^^^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^^^^^^^^^^ arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)` | = help: the trait `Iterator` is not implemented for `[{float}; 2]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: see for more details = note: required because of the requirements on the impl of `IntoIterator` for `[{float}; 2]` = note: required by `into_iter` diff --git a/src/test/ui/iterators/ranges.stderr b/src/test/ui/iterators/ranges.stderr index 4678bafd196b5..73844329e361d 100644 --- a/src/test/ui/iterators/ranges.stderr +++ b/src/test/ui/iterators/ranges.stderr @@ -2,9 +2,10 @@ error[E0277]: `RangeTo<{integer}>` is not an iterator --> $DIR/ranges.rs:2:14 | LL | for _ in ..10 {} - | ^^^^ `RangeTo<{integer}>` is not an iterator + | ^^^^ if you meant to iterate until a value, add a starting value | = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>` + = note: `..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a bounded `Range`: `0..end` = note: required because of the requirements on the impl of `IntoIterator` for `RangeTo<{integer}>` = note: required by `into_iter` @@ -12,9 +13,10 @@ error[E0277]: `RangeToInclusive<{integer}>` is not an iterator --> $DIR/ranges.rs:4:14 | LL | for _ in ..=10 {} - | ^^^^^ `RangeToInclusive<{integer}>` is not an iterator + | ^^^^^ if you meant to iterate until a value (including it), add a starting value | = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>` + = note: `..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant to have a bounded `RangeInclusive`: `0..=end` = note: required because of the requirements on the impl of `IntoIterator` for `RangeToInclusive<{integer}>` = note: required by `into_iter` diff --git a/src/test/ui/iterators/string.stderr b/src/test/ui/iterators/string.stderr index 1653006682427..1d77bcb753630 100644 --- a/src/test/ui/iterators/string.stderr +++ b/src/test/ui/iterators/string.stderr @@ -2,7 +2,7 @@ error[E0277]: `String` is not an iterator --> $DIR/string.rs:2:14 | LL | for _ in "".to_owned() {} - | ^^^^^^^^^^^^^ `String` is not an iterator + | ^^^^^^^^^^^^^ `String` is not an iterator; try calling `.chars()` or `.bytes()` | = help: the trait `Iterator` is not implemented for `String` = note: required because of the requirements on the impl of `IntoIterator` for `String` diff --git a/src/test/ui/lint/unaligned_references.rs b/src/test/ui/lint/unaligned_references.rs index c4e5d065643c8..ad38c21d96cf9 100644 --- a/src/test/ui/lint/unaligned_references.rs +++ b/src/test/ui/lint/unaligned_references.rs @@ -13,14 +13,20 @@ fn main() { let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] }; let _ = &good.ptr; //~ ERROR reference to packed field + //~^ previously accepted let _ = &good.data; //~ ERROR reference to packed field + //~^ previously accepted // Error even when turned into raw pointer immediately. let _ = &good.data as *const _; //~ ERROR reference to packed field + //~^ previously accepted let _: *const _ = &good.data; //~ ERROR reference to packed field + //~^ previously accepted // Error on method call. let _ = good.data.clone(); //~ ERROR reference to packed field + //~^ previously accepted // Error for nested fields. let _ = &good.data2[0]; //~ ERROR reference to packed field + //~^ previously accepted let _ = &*good.ptr; // ok, behind a pointer let _ = &good.aligned; // ok, has align 1 diff --git a/src/test/ui/lint/unaligned_references.stderr b/src/test/ui/lint/unaligned_references.stderr index 8786b9c05db27..9ae25f5b59ed1 100644 --- a/src/test/ui/lint/unaligned_references.stderr +++ b/src/test/ui/lint/unaligned_references.stderr @@ -9,46 +9,58 @@ note: the lint level is defined here | LL | #![deny(unaligned_references)] | ^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) error: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:16:17 + --> $DIR/unaligned_references.rs:17:17 | LL | let _ = &good.data; | ^^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) error: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:18:17 + --> $DIR/unaligned_references.rs:20:17 | LL | let _ = &good.data as *const _; | ^^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) error: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:19:27 + --> $DIR/unaligned_references.rs:22:27 | LL | let _: *const _ = &good.data; | ^^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) error: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:21:17 + --> $DIR/unaligned_references.rs:25:17 | LL | let _ = good.data.clone(); | ^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) error: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:23:17 + --> $DIR/unaligned_references.rs:28:17 | LL | let _ = &good.data2[0]; | ^^^^^^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) error: aborting due to 6 previous errors diff --git a/src/test/ui/lint/unaligned_references_external_macro.rs b/src/test/ui/lint/unaligned_references_external_macro.rs index 6ac501fb0e0db..cb597c38e7792 100644 --- a/src/test/ui/lint/unaligned_references_external_macro.rs +++ b/src/test/ui/lint/unaligned_references_external_macro.rs @@ -1,10 +1,9 @@ // aux-build:unaligned_references_external_crate.rs -#![allow(safe_packed_borrows)] - extern crate unaligned_references_external_crate; unaligned_references_external_crate::mac! { //~ERROR reference to packed field is unaligned + //~^ previously accepted #[repr(packed)] pub struct X { pub field: u16 diff --git a/src/test/ui/lint/unaligned_references_external_macro.stderr b/src/test/ui/lint/unaligned_references_external_macro.stderr index 140294b65ccd8..4e7c6bfc98d9d 100644 --- a/src/test/ui/lint/unaligned_references_external_macro.stderr +++ b/src/test/ui/lint/unaligned_references_external_macro.stderr @@ -1,7 +1,8 @@ error: reference to packed field is unaligned - --> $DIR/unaligned_references_external_macro.rs:7:1 + --> $DIR/unaligned_references_external_macro.rs:5:1 | LL | / unaligned_references_external_crate::mac! { +LL | | LL | | #[repr(packed)] LL | | pub struct X { LL | | pub field: u16 @@ -10,15 +11,18 @@ LL | | } | |_^ | note: the lint level is defined here - --> $DIR/unaligned_references_external_macro.rs:7:1 + --> $DIR/unaligned_references_external_macro.rs:5:1 | LL | / unaligned_references_external_crate::mac! { +LL | | LL | | #[repr(packed)] LL | | pub struct X { LL | | pub field: u16 LL | | } LL | | } | |_^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/packed/packed-struct-address-of-element.rs b/src/test/ui/packed/packed-struct-address-of-element.rs index 812d23fb58023..fb3875e680496 100644 --- a/src/test/ui/packed/packed-struct-address-of-element.rs +++ b/src/test/ui/packed/packed-struct-address-of-element.rs @@ -1,6 +1,6 @@ // run-pass #![allow(dead_code)] -#![deny(safe_packed_borrows)] +#![deny(unaligned_references)] #![feature(raw_ref_op)] // ignore-emscripten weird assertion? diff --git a/src/test/ui/packed/packed-struct-borrow-element.rs b/src/test/ui/packed/packed-struct-borrow-element.rs index 0072b6191ebb0..5dad084eecf6d 100644 --- a/src/test/ui/packed/packed-struct-borrow-element.rs +++ b/src/test/ui/packed/packed-struct-borrow-element.rs @@ -22,14 +22,17 @@ struct Foo4C { pub fn main() { let foo = Foo1 { bar: 1, baz: 2 }; - let brw = unsafe { &foo.baz }; + let brw = &foo.baz; //~WARN reference to packed field is unaligned + //~^ previously accepted assert_eq!(*brw, 2); let foo = Foo2 { bar: 1, baz: 2 }; - let brw = unsafe { &foo.baz }; + let brw = &foo.baz; //~WARN reference to packed field is unaligned + //~^ previously accepted assert_eq!(*brw, 2); let foo = Foo4C { bar: 1, baz: 2 }; - let brw = unsafe { &foo.baz }; + let brw = &foo.baz; //~WARN reference to packed field is unaligned + //~^ previously accepted assert_eq!(*brw, 2); } diff --git a/src/test/ui/packed/packed-struct-borrow-element.stderr b/src/test/ui/packed/packed-struct-borrow-element.stderr new file mode 100644 index 0000000000000..d9d9a71ff58e9 --- /dev/null +++ b/src/test/ui/packed/packed-struct-borrow-element.stderr @@ -0,0 +1,33 @@ +warning: reference to packed field is unaligned + --> $DIR/packed-struct-borrow-element.rs:25:15 + | +LL | let brw = &foo.baz; + | ^^^^^^^^ + | + = note: `#[warn(unaligned_references)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + +warning: reference to packed field is unaligned + --> $DIR/packed-struct-borrow-element.rs:30:15 + | +LL | let brw = &foo.baz; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + +warning: reference to packed field is unaligned + --> $DIR/packed-struct-borrow-element.rs:35:15 + | +LL | let brw = &foo.baz; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + +warning: 3 warnings emitted + diff --git a/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs b/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs index 52ebe8e7fb2ef..27676a5cb8112 100644 --- a/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs +++ b/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs @@ -2,14 +2,15 @@ pub struct FirstStruct; #[macro_export] macro_rules! outer_macro { - ($name:ident) => { + ($name:ident, $attr_struct_name:ident) => { #[macro_export] macro_rules! inner_macro { - ($wrapper:ident) => { - $wrapper!($name) + ($bang_macro:ident, $attr_macro:ident) => { + $bang_macro!($name); + #[$attr_macro] struct $attr_struct_name {} } } } } -outer_macro!(FirstStruct); +outer_macro!(FirstStruct, FirstAttrStruct); diff --git a/src/test/ui/proc-macro/nested-macro-rules.rs b/src/test/ui/proc-macro/nested-macro-rules.rs index 2fef0e5fad074..25ffcfad7c7ea 100644 --- a/src/test/ui/proc-macro/nested-macro-rules.rs +++ b/src/test/ui/proc-macro/nested-macro-rules.rs @@ -1,7 +1,7 @@ // run-pass // aux-build:nested-macro-rules.rs // aux-build:test-macros.rs -// compile-flags: -Z span-debug +// compile-flags: -Z span-debug -Z macro-backtrace // edition:2018 #![no_std] // Don't load unnecessary hygiene information from std @@ -10,14 +10,14 @@ extern crate std; extern crate nested_macro_rules; extern crate test_macros; -use test_macros::print_bang; +use test_macros::{print_bang, print_attr}; use nested_macro_rules::FirstStruct; struct SecondStruct; fn main() { - nested_macro_rules::inner_macro!(print_bang); + nested_macro_rules::inner_macro!(print_bang, print_attr); - nested_macro_rules::outer_macro!(SecondStruct); - inner_macro!(print_bang); + nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct); + inner_macro!(print_bang, print_attr); } diff --git a/src/test/ui/proc-macro/nested-macro-rules.stdout b/src/test/ui/proc-macro/nested-macro-rules.stdout index dcafe3b4bda60..8292617fc1675 100644 --- a/src/test/ui/proc-macro/nested-macro-rules.stdout +++ b/src/test/ui/proc-macro/nested-macro-rules.stdout @@ -5,10 +5,32 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "FirstStruct", - span: $DIR/auxiliary/nested-macro-rules.rs:15:14: 15:25 (#7), + span: $DIR/auxiliary/nested-macro-rules.rs:16:14: 16:25 (#7), }, ], - span: $DIR/auxiliary/nested-macro-rules.rs:9:27: 9:32 (#6), + span: $DIR/auxiliary/nested-macro-rules.rs:9:30: 9:35 (#6), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct FirstAttrStruct { } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/auxiliary/nested-macro-rules.rs:10:32: 10:38 (#6), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "FirstAttrStruct", + span: $DIR/auxiliary/nested-macro-rules.rs:16:27: 16:42 (#7), + }, + ], + span: $DIR/auxiliary/nested-macro-rules.rs:10:39: 10:56 (#6), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/auxiliary/nested-macro-rules.rs:10:57: 10:59 (#6), }, ] PRINT-BANG INPUT (DISPLAY): SecondStruct @@ -18,9 +40,31 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "SecondStruct", - span: $DIR/nested-macro-rules.rs:21:38: 21:50 (#13), + span: $DIR/nested-macro-rules.rs:21:38: 21:50 (#16), }, ], - span: $DIR/auxiliary/nested-macro-rules.rs:9:27: 9:32 (#12), + span: $DIR/auxiliary/nested-macro-rules.rs:9:30: 9:35 (#15), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct SecondAttrStruct { } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/auxiliary/nested-macro-rules.rs:10:32: 10:38 (#15), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "SecondAttrStruct", + span: $DIR/nested-macro-rules.rs:21:52: 21:68 (#16), + }, + ], + span: $DIR/auxiliary/nested-macro-rules.rs:10:39: 10:56 (#15), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/auxiliary/nested-macro-rules.rs:10:57: 10:59 (#15), }, ] diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr index 32961b7f87be0..3786457fb1ae3 100644 --- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr +++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr @@ -46,6 +46,7 @@ error[E0277]: `dyn Future + Send` cannot be unpinned LL | Pin::new(x) | ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future + Send` | + = note: consider using `Box::pin` = note: required by `Pin::

::new` error[E0277]: `dyn Future + Send` cannot be unpinned @@ -54,6 +55,7 @@ error[E0277]: `dyn Future + Send` cannot be unpinned LL | Pin::new(Box::new(x)) | ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future + Send` | + = note: consider using `Box::pin` = note: required by `Pin::

::new` error[E0308]: mismatched types diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr index 2854b830ba822..26efd50bb8fd3 100644 --- a/src/test/ui/suggestions/into-str.stderr +++ b/src/test/ui/suggestions/into-str.stderr @@ -7,6 +7,7 @@ LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {} LL | foo(String::new()); | ^^^ the trait `From` is not implemented for `&str` | + = note: to coerce a `String` into a `&str`, use `&*` as a prefix = note: required because of the requirements on the impl of `Into<&str>` for `String` error: aborting due to previous error diff --git a/src/test/ui/suggestions/path-display.stderr b/src/test/ui/suggestions/path-display.stderr index b08e22eaab7bb..3ee2860b4ffc7 100644 --- a/src/test/ui/suggestions/path-display.stderr +++ b/src/test/ui/suggestions/path-display.stderr @@ -2,10 +2,10 @@ error[E0277]: `Path` doesn't implement `std::fmt::Display` --> $DIR/path-display.rs:5:20 | LL | println!("{}", path); - | ^^^^ `Path` cannot be formatted with the default formatter + | ^^^^ `Path` cannot be formatted with the default formatter; call `.display()` on it | = help: the trait `std::fmt::Display` is not implemented for `Path` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data = note: required because of the requirements on the impl of `std::fmt::Display` for `&Path` = note: required by `std::fmt::Display::fmt` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs b/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs deleted file mode 100644 index 540612a7dce05..0000000000000 --- a/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs +++ /dev/null @@ -1,67 +0,0 @@ -#![feature(unsafe_block_in_unsafe_fn)] - -#[repr(packed)] -pub struct Packed { - data: &'static u32, -} - -const PACKED: Packed = Packed { data: &0 }; - -#[allow(safe_packed_borrows)] -#[allow(unsafe_op_in_unsafe_fn)] -unsafe fn allow_allow() { - &PACKED.data; // allowed -} - -#[allow(safe_packed_borrows)] -#[warn(unsafe_op_in_unsafe_fn)] -unsafe fn allow_warn() { - &PACKED.data; // allowed -} - -#[allow(safe_packed_borrows)] -#[deny(unsafe_op_in_unsafe_fn)] -unsafe fn allow_deny() { - &PACKED.data; // allowed -} - -#[warn(safe_packed_borrows)] -#[allow(unsafe_op_in_unsafe_fn)] -unsafe fn warn_allow() { - &PACKED.data; // allowed -} - -#[warn(safe_packed_borrows)] -#[warn(unsafe_op_in_unsafe_fn)] -unsafe fn warn_warn() { - &PACKED.data; //~ WARN - //~| WARNING this was previously accepted by the compiler but is being phased out -} - -#[warn(safe_packed_borrows)] -#[deny(unsafe_op_in_unsafe_fn)] -unsafe fn warn_deny() { - &PACKED.data; //~ WARN - //~| WARNING this was previously accepted by the compiler but is being phased out -} - -#[deny(safe_packed_borrows)] -#[allow(unsafe_op_in_unsafe_fn)] -unsafe fn deny_allow() { - &PACKED.data; // allowed -} - -#[deny(safe_packed_borrows)] -#[warn(unsafe_op_in_unsafe_fn)] -unsafe fn deny_warn() { - &PACKED.data; //~ WARN -} - -#[deny(safe_packed_borrows)] -#[deny(unsafe_op_in_unsafe_fn)] -unsafe fn deny_deny() { - &PACKED.data; //~ ERROR - //~| WARNING this was previously accepted by the compiler but is being phased out -} - -fn main() {} diff --git a/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.stderr b/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.stderr deleted file mode 100644 index fda15159643b6..0000000000000 --- a/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.stderr +++ /dev/null @@ -1,60 +0,0 @@ -warning: borrow of packed field is unsafe and requires unsafe block (error E0133) - --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:37:5 - | -LL | &PACKED.data; - | ^^^^^^^^^^^^ borrow of packed field - | -note: the lint level is defined here - --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:34:8 - | -LL | #[warn(safe_packed_borrows)] - | ^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #46043 - = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior - -warning: borrow of packed field is unsafe and requires unsafe block (error E0133) - --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:44:5 - | -LL | &PACKED.data; - | ^^^^^^^^^^^^ borrow of packed field - | -note: the lint level is defined here - --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:41:8 - | -LL | #[warn(safe_packed_borrows)] - | ^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #46043 - = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior - -warning: borrow of packed field is unsafe and requires unsafe block (error E0133) - --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:57:5 - | -LL | &PACKED.data; - | ^^^^^^^^^^^^ borrow of packed field - | -note: the lint level is defined here - --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:55:8 - | -LL | #[warn(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior - -error: borrow of packed field is unsafe and requires unsafe block (error E0133) - --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:63:5 - | -LL | &PACKED.data; - | ^^^^^^^^^^^^ borrow of packed field - | -note: the lint level is defined here - --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:60:8 - | -LL | #[deny(safe_packed_borrows)] - | ^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #46043 - = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior - -error: aborting due to previous error; 3 warnings emitted - diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs index d136db9373c2d..73f71d88b0525 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -13,6 +13,7 @@ use rustc_middle::{ ty::{self, FloatTy, IntTy, PolyFnSig, Ty}, }; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use std::iter; declare_clippy_lint! { /// **What it does:** Checks for usage of unconstrained numeric literals which may cause default numeric fallback in type @@ -107,7 +108,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> { match &expr.kind { ExprKind::Call(func, args) => { if let Some(fn_sig) = fn_sig_opt(self.cx, func.hir_id) { - for (expr, bound) in args.iter().zip(fn_sig.skip_binder().inputs().iter()) { + for (expr, bound) in iter::zip(*args, fn_sig.skip_binder().inputs()) { // Push found arg type, then visit arg. self.ty_bounds.push(TyBound::Ty(bound)); self.visit_expr(expr); @@ -120,7 +121,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> { ExprKind::MethodCall(_, _, args, _) => { if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(expr.hir_id) { let fn_sig = self.cx.tcx.fn_sig(def_id).skip_binder(); - for (expr, bound) in args.iter().zip(fn_sig.inputs().iter()) { + for (expr, bound) in iter::zip(*args, fn_sig.inputs()) { self.ty_bounds.push(TyBound::Ty(bound)); self.visit_expr(expr); self.ty_bounds.pop(); diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 1c3841f8efd6f..a99ed7656bfb3 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -4,6 +4,7 @@ #![feature(box_syntax)] #![feature(drain_filter)] #![feature(in_band_lifetimes)] +#![feature(iter_zip)] #![feature(once_cell)] #![cfg_attr(bootstrap, feature(or_patterns))] #![feature(rustc_private)] diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs index 7fd55151226b4..5447051926060 100644 --- a/src/tools/clippy/clippy_lints/src/literal_representation.rs +++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs @@ -13,6 +13,7 @@ use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; +use std::iter; declare_clippy_lint! { /// **What it does:** Warns if a long integral or floating-point constant does @@ -349,7 +350,7 @@ impl LiteralDigitGrouping { let group_sizes: Vec = num_lit.integer.split('_').map(str::len).collect(); if UUID_GROUP_LENS.len() == group_sizes.len() { - UUID_GROUP_LENS.iter().zip(&group_sizes).all(|(&a, &b)| a == b) + iter::zip(&UUID_GROUP_LENS, &group_sizes).all(|(&a, &b)| a == b) } else { false } diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs index 3c40d54cb4210..64ab3b6bfec02 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs @@ -17,7 +17,7 @@ use rustc_middle::hir::map::Map; use rustc_middle::middle::region; use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::{sym, Symbol}; -use std::iter::Iterator; +use std::iter::{self, Iterator}; use std::mem; /// Checks for looping over a range and then indexing a sequence with it. @@ -369,7 +369,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { }, ExprKind::MethodCall(_, _, args, _) => { let def_id = self.cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap(); - for (ty, expr) in self.cx.tcx.fn_sig(def_id).inputs().skip_binder().iter().zip(args) { + for (ty, expr) in iter::zip(self.cx.tcx.fn_sig(def_id).inputs().skip_binder(), args) { self.prefer_mutable = false; if let ty::Ref(_, _, mutbl) = *ty.kind() { if mutbl == Mutability::Mut { diff --git a/src/tools/clippy/clippy_lints/src/matches.rs b/src/tools/clippy/clippy_lints/src/matches.rs index 3680429fed7d8..2f2dc4cfc6b03 100644 --- a/src/tools/clippy/clippy_lints/src/matches.rs +++ b/src/tools/clippy/clippy_lints/src/matches.rs @@ -29,6 +29,7 @@ use rustc_span::source_map::{Span, Spanned}; use rustc_span::sym; use std::cmp::Ordering; use std::collections::hash_map::Entry; +use std::iter; use std::ops::Bound; declare_clippy_lint! { @@ -1668,7 +1669,7 @@ where values.sort(); - for (a, b) in values.iter().zip(values.iter().skip(1)) { + for (a, b) in iter::zip(&values, &values[1..]) { match (a, b) { (&Kind::Start(_, ra), &Kind::End(_, rb)) => { if ra.node != rb.node { diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index 41bd07bcf1ea2..4d3dff36a2069 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -6,6 +6,7 @@ use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::{Adt, Array, RawPtr, Ref, Slice, Tuple, Ty, TypeAndMut}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; +use std::iter; declare_clippy_lint! { /// **What it does:** Checks for sets/maps with mutable key types. @@ -87,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType { fn check_sig<'tcx>(cx: &LateContext<'tcx>, item_hir_id: hir::HirId, decl: &hir::FnDecl<'_>) { let fn_def_id = cx.tcx.hir().local_def_id(item_hir_id); let fn_sig = cx.tcx.fn_sig(fn_def_id); - for (hir_ty, ty) in decl.inputs.iter().zip(fn_sig.inputs().skip_binder().iter()) { + for (hir_ty, ty) in iter::zip(decl.inputs, fn_sig.inputs().skip_binder()) { check_ty(cx, hir_ty.span, ty); } check_ty(cx, decl.output.span(), cx.tcx.erase_late_bound_regions(fn_sig.output())); diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs index 0c09ddb80733d..05457e80d52c9 100644 --- a/src/tools/clippy/clippy_lints/src/mut_reference.rs +++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs @@ -4,6 +4,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use std::iter; declare_clippy_lint! { /// **What it does:** Detects passing a mutable reference to a function that only @@ -64,7 +65,7 @@ fn check_arguments<'tcx>( match type_definition.kind() { ty::FnDef(..) | ty::FnPtr(_) => { let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs(); - for (argument, parameter) in arguments.iter().zip(parameters.iter()) { + for (argument, parameter) in iter::zip(arguments, parameters) { match parameter.kind() { ty::Ref(_, _, Mutability::Not) | ty::RawPtr(ty::TypeAndMut { diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 9a5b1c3b9442a..e151f85a39137 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -1,4 +1,5 @@ use std::cmp; +use std::iter; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_self_ty; @@ -122,7 +123,7 @@ impl<'tcx> PassByRefOrValue { let fn_body = cx.enclosing_body.map(|id| cx.tcx.hir().body(id)); - for (index, (input, &ty)) in decl.inputs.iter().zip(fn_sig.inputs()).enumerate() { + for (index, (input, &ty)) in iter::zip(decl.inputs, fn_sig.inputs()).enumerate() { // All spans generated from a proc-macro invocation are the same... match span { Some(s) if s == input.span => return, diff --git a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs index 4550b367da4bf..c0c2ab67e382e 100644 --- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs +++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs @@ -10,6 +10,7 @@ use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{AdtDef, FieldDef, Ty, TyKind, VariantDef}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; +use std::iter; declare_clippy_lint! { /// **What it does:** Checks for patterns that aren't exact representations of the types @@ -134,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch { hir_id: HirId, ) { if let Some(fn_sig) = cx.typeck_results().liberated_fn_sigs().get(hir_id) { - for (param, ty) in body.params.iter().zip(fn_sig.inputs().iter()) { + for (param, ty) in iter::zip(body.params, fn_sig.inputs()) { apply_lint(cx, ¶m.pat, ty, DerefPossible::Impossible); } } diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs index e23bab5eba03f..6becff9662a76 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs @@ -9,6 +9,7 @@ use rustc_middle::ty::{self, subst::GenericArgKind}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; use rustc_span::symbol::Ident; +use std::iter; declare_clippy_lint! { /// **What it does:** @@ -79,17 +80,15 @@ fn mirrored_exprs( mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident) }, // Two arrays with mirrored contents - (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => left_exprs - .iter() - .zip(right_exprs.iter()) - .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)), + (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => { + iter::zip(*left_exprs, *right_exprs) + .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)) + } // The two exprs are function calls. // Check to see that the function itself and its arguments are mirrored (ExprKind::Call(left_expr, left_args), ExprKind::Call(right_expr, right_args)) => { mirrored_exprs(cx, left_expr, a_ident, right_expr, b_ident) - && left_args - .iter() - .zip(right_args.iter()) + && iter::zip(*left_args, *right_args) .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)) }, // The two exprs are method calls. @@ -100,16 +99,14 @@ fn mirrored_exprs( ExprKind::MethodCall(right_segment, _, right_args, _), ) => { left_segment.ident == right_segment.ident - && left_args - .iter() - .zip(right_args.iter()) + && iter::zip(*left_args, *right_args) .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)) - }, + } // Two tuples with mirrored contents - (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => left_exprs - .iter() - .zip(right_exprs.iter()) - .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)), + (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => { + iter::zip(*left_exprs, *right_exprs) + .all(|(left, right)| mirrored_exprs(cx, left, a_ident, right, b_ident)) + } // Two binary ops, which are the same operation and which have mirrored arguments (ExprKind::Binary(left_op, left_left, left_right), ExprKind::Binary(right_op, right_left, right_right)) => { left_op.node == right_op.node @@ -146,9 +143,7 @@ fn mirrored_exprs( }, )), ) => { - (left_segments - .iter() - .zip(right_segments.iter()) + (iter::zip(*left_segments, *right_segments) .all(|(left, right)| left.ident == right.ident) && left_segments .iter() diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index ebe896b7ae867..8af10ebe777ea 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -15,6 +15,7 @@ use rustc_span::symbol::Symbol; use std::cmp::Ordering::{self, Equal}; use std::convert::TryInto; use std::hash::{Hash, Hasher}; +use std::iter; /// A `LitKind`-like enum to fold constant `Expr`s into. #[derive(Debug, Clone)] @@ -139,12 +140,12 @@ impl Constant { (&Self::F64(l), &Self::F64(r)) => l.partial_cmp(&r), (&Self::F32(l), &Self::F32(r)) => l.partial_cmp(&r), (&Self::Bool(ref l), &Self::Bool(ref r)) => Some(l.cmp(r)), - (&Self::Tuple(ref l), &Self::Tuple(ref r)) | (&Self::Vec(ref l), &Self::Vec(ref r)) => l - .iter() - .zip(r.iter()) - .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri)) - .find(|r| r.map_or(true, |o| o != Ordering::Equal)) - .unwrap_or_else(|| Some(l.len().cmp(&r.len()))), + (&Self::Tuple(ref l), &Self::Tuple(ref r)) | (&Self::Vec(ref l), &Self::Vec(ref r)) => { + iter::zip(l, r) + .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri)) + .find(|r| r.map_or(true, |o| o != Ordering::Equal)) + .unwrap_or_else(|| Some(l.len().cmp(&r.len()))) + } (&Self::Repeat(ref lv, ref ls), &Self::Repeat(ref rv, ref rs)) => { match Self::partial_cmp(tcx, cmp_type, lv, rv) { Some(Equal) => Some(ls.cmp(rs)), diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index b613ae9b91806..b2655f8d797b1 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1,5 +1,6 @@ #![feature(box_patterns)] #![feature(in_band_lifetimes)] +#![feature(iter_zip)] #![cfg_attr(bootstrap, feature(or_patterns))] #![feature(rustc_private)] #![recursion_limit = "512"] diff --git a/src/tools/clippy/clippy_utils/src/numeric_literal.rs b/src/tools/clippy/clippy_utils/src/numeric_literal.rs index d02603d7702c7..268bc5b320533 100644 --- a/src/tools/clippy/clippy_utils/src/numeric_literal.rs +++ b/src/tools/clippy/clippy_utils/src/numeric_literal.rs @@ -1,4 +1,5 @@ use rustc_ast::ast::{Lit, LitFloatType, LitIntType, LitKind}; +use std::iter; #[derive(Debug, PartialEq, Copy, Clone)] pub enum Radix { @@ -192,7 +193,7 @@ impl<'a> NumericLiteral<'a> { } } - for (c, i) in digits.zip((0..group_size).cycle()) { + for (c, i) in iter::zip(digits, (0..group_size).cycle()) { if i == 0 { output.push('_'); }