From a9c1ab82f5f58a8459fc5f1f2d13021e80f23421 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 7 Feb 2022 16:05:17 +0100 Subject: [PATCH 1/7] safely `transmute<&List>, &List>>` --- compiler/rustc_middle/src/ty/context.rs | 35 ++++++++++++++++++---- compiler/rustc_middle/src/ty/impls_ty.rs | 22 ++++++++++++++ compiler/rustc_middle/src/ty/subst.rs | 38 +++++++++++++++++++++++- 3 files changed, 89 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index bb8566ea4df..925ef9a2ea4 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -101,7 +101,6 @@ pub struct CtxtInterners<'tcx> { // Specifically use a speedy hash algorithm for these hash sets, since // they're accessed quite often. type_: InternedSet<'tcx, TyS<'tcx>>, - type_list: InternedSet<'tcx, List>>, substs: InternedSet<'tcx, InternalSubsts<'tcx>>, canonical_var_infos: InternedSet<'tcx, List>>, region: InternedSet<'tcx, RegionKind>, @@ -129,7 +128,6 @@ impl<'tcx> CtxtInterners<'tcx> { CtxtInterners { arena, type_: Default::default(), - type_list: Default::default(), substs: Default::default(), region: Default::default(), poly_existential_predicates: Default::default(), @@ -1666,6 +1664,23 @@ macro_rules! nop_lift { }; } +// Can't use the macros as we have reuse the `substs` here. +// +// See `intern_type_list` for more info. +impl<'a, 'tcx> Lift<'tcx> for &'a List> { + type Lifted = &'tcx List>; + fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { + if self.is_empty() { + return Some(List::empty()); + } + if tcx.interners.substs.contains_pointer_to(&InternedInSet(self.as_substs())) { + Some(unsafe { mem::transmute(self) }) + } else { + None + } + } +} + macro_rules! nop_list_lift { ($set:ident; $ty:ty => $lifted:ty) => { impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> { @@ -1690,7 +1705,6 @@ nop_lift! {const_; Const<'a> => Const<'tcx>} nop_lift_old! {const_allocation; &'a Allocation => &'tcx Allocation} nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>} -nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>} nop_list_lift! {poly_existential_predicates; ty::Binder<'a, ExistentialPredicate<'a>> => ty::Binder<'tcx, ExistentialPredicate<'tcx>>} nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>} nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>} @@ -2189,7 +2203,6 @@ macro_rules! slice_interners { } slice_interners!( - type_list: _intern_type_list(Ty<'tcx>), substs: _intern_substs(GenericArg<'tcx>), canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo<'tcx>), poly_existential_predicates: @@ -2611,7 +2624,19 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List> { - if ts.is_empty() { List::empty() } else { self._intern_type_list(ts) } + if ts.is_empty() { + List::empty() + } else { + // Actually intern type lists as lists of `GenericArg`s. + // + // Transmuting from `Ty<'tcx>` to `GenericArg<'tcx>` is sound + // as explained in ty_slice_as_generic_arg`. With this, + // we guarantee that even when transmuting between `List>` + // and `List>`, the uniqueness requirement for + // lists is upheld. + let substs = self._intern_substs(ty::subst::ty_slice_as_generic_args(ts)); + substs.try_as_type_list().unwrap() + } } pub fn intern_substs(self, ts: &[GenericArg<'tcx>]) -> &'tcx List> { diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index 00ce15bea3f..4e3661dda17 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -61,6 +61,28 @@ impl<'a, 'tcx> HashStable> for ty::subst::GenericArg<'t } } +impl<'a, 'tcx> HashStable> for ty::subst::GenericArgKind<'tcx> { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + match self { + // WARNING: We dedup cache the `HashStable` results for `List` + // while ignoring types and freely transmute + // between `List>` and `List>`. + // See `fn intern_type_list` for more details. + // + // We therefore hash types without adding a hash for their discriminant. + ty::subst::GenericArgKind::Type(ty) => ty.hash_stable(hcx, hasher), + ty::subst::GenericArgKind::Const(ct) => { + mem::discriminant(self).hash_stable(hcx, hasher); + ct.hash_stable(hcx, hasher); + } + ty::subst::GenericArgKind::Lifetime(lt) => { + mem::discriminant(self).hash_stable(hcx, hasher); + lt.hash_stable(hcx, hasher); + } + } + } +} + impl<'a> HashStable> for ty::RegionKind { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 7dccef5e3ef..7085168781c 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -20,6 +20,7 @@ use std::marker::PhantomData; use std::mem; use std::num::NonZeroUsize; use std::ops::ControlFlow; +use std::slice; /// An entity in the Rust type system, which can be one of /// several kinds (types, lifetimes, and consts). @@ -40,13 +41,37 @@ const TYPE_TAG: usize = 0b00; const REGION_TAG: usize = 0b01; const CONST_TAG: usize = 0b10; -#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord, HashStable)] +#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord)] pub enum GenericArgKind<'tcx> { Lifetime(ty::Region<'tcx>), Type(Ty<'tcx>), Const(ty::Const<'tcx>), } +/// This function goes from `&'a [Ty<'tcx>]` to `&'a [GenericArg<'tcx>]` +/// +/// This is sound as, for types, `GenericArg` is just +/// `NonZeroUsize::new_unchecked(ty as *const _ as usize)`. +pub fn ty_slice_as_generic_args<'a, 'tcx>(ts: &'a [Ty<'tcx>]) -> &'a [GenericArg<'tcx>] { + assert_eq!(TYPE_TAG, 0); + // SAFETY: the whole slice is valid and immutable. + // `Ty` and `GenericArg` is explained above. + unsafe { slice::from_raw_parts(ts.as_ptr().cast(), ts.len()) } +} + +impl<'tcx> List> { + /// Allows to freely switch betwen `List>` and `List>`. + /// + /// As lists are interned, `List>` and `List>` have + /// be interned together, see `intern_type_list` for more details. + #[inline] + pub fn as_substs(&'tcx self) -> SubstsRef<'tcx> { + assert_eq!(TYPE_TAG, 0); + // SAFETY: `List` is `#[repr(C)]`. `Ty` and `GenericArg` is explained above. + unsafe { &*(self as *const List> as *const List>) } + } +} + impl<'tcx> GenericArgKind<'tcx> { #[inline] fn pack(self) -> GenericArg<'tcx> { @@ -208,6 +233,17 @@ pub type InternalSubsts<'tcx> = List>; pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>; impl<'a, 'tcx> InternalSubsts<'tcx> { + /// Checks whether all elements of this list are types, if so, transmute. + pub fn try_as_type_list(&'tcx self) -> Option<&'tcx List>> { + if self.iter().all(|arg| matches!(arg.unpack(), GenericArgKind::Type(_))) { + assert_eq!(TYPE_TAG, 0); + // SAFETY: All elements are types, see `List>::as_substs`. + Some(unsafe { &*(self as *const List> as *const List>) }) + } else { + None + } + } + /// Interpret these substitutions as the substitutions of a closure type. /// Closure substitutions have a particular structure controlled by the /// compiler that encodes information like the signature and closure kind; From 1245131a118ee08a38cfd3a90952a0168d65cae2 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 7 Feb 2022 16:06:31 +0100 Subject: [PATCH 2/7] use `List>` for tuples --- .../src/diagnostics/conflict_errors.rs | 2 +- .../src/diagnostics/region_name.rs | 7 +++---- compiler/rustc_borrowck/src/type_check/mod.rs | 7 ++++--- .../rustc_borrowck/src/universal_regions.rs | 6 ++---- .../rustc_codegen_cranelift/src/abi/mod.rs | 4 ++-- compiler/rustc_codegen_cranelift/src/common.rs | 7 +++---- .../src/debuginfo/metadata.rs | 5 ++--- .../src/debuginfo/type_names.rs | 2 +- .../src/infer/error_reporting/mod.rs | 15 +++++++-------- .../infer/error_reporting/need_type_info.rs | 4 +++- compiler/rustc_lint/src/builtin.rs | 4 ++-- compiler/rustc_lint/src/unused.rs | 2 +- compiler/rustc_middle/src/mir/pretty.rs | 2 +- compiler/rustc_middle/src/mir/tcx.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 10 +++------- compiler/rustc_middle/src/ty/diagnostics.rs | 3 ++- compiler/rustc_middle/src/ty/flags.rs | 4 ++-- .../rustc_middle/src/ty/inhabitedness/mod.rs | 7 +++---- compiler/rustc_middle/src/ty/instance.rs | 2 +- compiler/rustc_middle/src/ty/layout.rs | 14 ++++++-------- compiler/rustc_middle/src/ty/print/mod.rs | 1 - compiler/rustc_middle/src/ty/print/pretty.rs | 7 +++---- compiler/rustc_middle/src/ty/relate.rs | 4 +--- compiler/rustc_middle/src/ty/sty.rs | 18 ++++-------------- compiler/rustc_middle/src/ty/util.rs | 16 ++++++++-------- compiler/rustc_middle/src/ty/walk.rs | 2 +- .../rustc_mir_build/src/build/expr/as_place.rs | 2 +- .../src/thir/pattern/deconstruct_pat.rs | 9 +++------ .../rustc_mir_dataflow/src/elaborate_drops.rs | 5 +---- compiler/rustc_mir_transform/src/const_prop.rs | 6 ++---- compiler/rustc_mir_transform/src/inline.rs | 3 +-- .../src/remove_uninit_drops.rs | 4 ++-- compiler/rustc_mir_transform/src/shim.rs | 4 ++-- compiler/rustc_symbol_mangling/src/v0.rs | 2 +- .../src/traits/error_reporting/mod.rs | 7 +++---- .../src/traits/error_reporting/suggestions.rs | 2 +- .../src/traits/query/dropck_outlives.rs | 2 +- .../src/traits/select/confirmation.rs | 10 ++++------ .../src/traits/select/mod.rs | 8 +++----- .../rustc_trait_selection/src/traits/wf.rs | 4 ++-- compiler/rustc_traits/src/chalk/db.rs | 2 +- compiler/rustc_traits/src/chalk/lowering.rs | 8 ++++++-- compiler/rustc_traits/src/dropck_outlives.rs | 9 +-------- .../rustc_ty_utils/src/representability.rs | 4 ++-- compiler/rustc_ty_utils/src/ty.rs | 6 +++--- compiler/rustc_typeck/src/check/cast.rs | 2 +- compiler/rustc_typeck/src/check/closure.rs | 4 ++-- compiler/rustc_typeck/src/check/expr.rs | 6 +++--- .../rustc_typeck/src/check/fn_ctxt/checks.rs | 9 ++++----- .../src/check/generator_interior.rs | 6 +++--- compiler/rustc_typeck/src/check/pat.rs | 11 +++++------ compiler/rustc_typeck/src/check/upvar.rs | 4 ++-- .../rustc_typeck/src/variance/constraints.rs | 2 +- 53 files changed, 128 insertions(+), 170 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 6988fbf8336..baa59efbf8d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2298,7 +2298,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Closure arguments are wrapped in a tuple, so we need to get the first // from that. if let ty::Tuple(elems) = argument_ty.kind() { - let argument_ty = elems.first()?.expect_ty(); + let &argument_ty = elems.first()?; if let ty::Ref(_, _, _) = argument_ty.kind() { return Some(AnnotatedBorrowFnSignature::Closure { argument_ty, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 3bcc9f7be38..5d1d291d3b4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -480,7 +480,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty<'_>)> = &mut vec![(ty, hir_ty)]; while let Some((ty, hir_ty)) = search_stack.pop() { - match (&ty.kind(), &hir_ty.kind) { + match (ty.kind(), &hir_ty.kind) { // Check if the `ty` is `&'X ..` where `'X` // is the region we are looking for -- if so, and we have a `&T` // on the RHS, then we want to highlight the `&` like so: @@ -532,9 +532,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // The following cases don't have lifetimes, so we // 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(iter::zip(elem_tys.iter().map(|k| k.expect_ty()), *elem_hir_tys)); + (&ty::Tuple(elem_tys), hir::TyKind::Tup(elem_hir_tys)) => { + search_stack.extend(iter::zip(elem_tys, *elem_hir_tys)); } (ty::Slice(elem_ty), hir::TyKind::Slice(elem_hir_ty)) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 89b14129d01..b87a9e6567b 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -832,9 +832,10 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { return match substs .as_closure() .tupled_upvars_ty() - .tuple_element_ty(field.index()) + .tuple_fields() + .get(field.index()) { - Some(ty) => Ok(ty), + Some(&ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { field_count: substs.as_closure().upvar_tys().count(), }), @@ -852,7 +853,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } ty::Tuple(tys) => { return match tys.get(field.index()) { - Some(&ty) => Ok(ty.expect_ty()), + Some(&ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { field_count: tys.len() }), }; } diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 33e65439fd7..d21a9d86e5b 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -641,15 +641,13 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let (&output, tuplized_inputs) = inputs_and_output.skip_binder().split_last().unwrap(); assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs"); - let ty::Tuple(inputs) = tuplized_inputs[0].kind() else { + let &ty::Tuple(inputs) = tuplized_inputs[0].kind() else { bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]); }; ty::Binder::bind_with_vars( tcx.mk_type_list( - iter::once(closure_ty) - .chain(inputs.iter().map(|k| k.expect_ty())) - .chain(iter::once(output)), + iter::once(closure_ty).chain(inputs).chain(iter::once(output)), ), bound_vars, ) diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index a0550860fa5..a249e5fa8ac 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -117,7 +117,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { .unzip(); let return_layout = self.layout_of(return_ty); let return_tys = if let ty::Tuple(tup) = return_ty.kind() { - tup.types().map(|ty| AbiParam::new(self.clif_type(ty).unwrap())).collect() + tup.iter().map(|ty| AbiParam::new(self.clif_type(ty).unwrap())).collect() } else { vec![AbiParam::new(self.clif_type(return_ty).unwrap())] }; @@ -199,7 +199,7 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_ }; let mut params = Vec::new(); - for (i, _arg_ty) in tupled_arg_tys.types().enumerate() { + for (i, _arg_ty) in tupled_arg_tys.iter().enumerate() { let arg_abi = arg_abis_iter.next().unwrap(); let param = cvalue_for_param(fx, Some(local), Some(i), arg_abi, &mut block_params_iter); diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 50f98965ab5..d3e36be3244 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -90,10 +90,9 @@ fn clif_pair_type_from_ty<'tcx>( ty: Ty<'tcx>, ) -> Option<(types::Type, types::Type)> { Some(match ty.kind() { - ty::Tuple(substs) if substs.len() == 2 => { - let mut types = substs.types(); - let a = clif_type_from_ty(tcx, types.next().unwrap())?; - let b = clif_type_from_ty(tcx, types.next().unwrap())?; + ty::Tuple(types) if types.len() == 2 => { + let a = clif_type_from_ty(tcx, types[0])?; + let b = clif_type_from_ty(tcx, types[1])?; if a.is_vector() || b.is_vector() { return None; } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index fd1e61f2b8a..ef87b7b1a7e 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -752,9 +752,8 @@ pub fn type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll prepare_enum_metadata(cx, t, def.did, unique_type_id, vec![]).finalize(cx) } }, - ty::Tuple(elements) => { - let tys: Vec<_> = elements.iter().map(|k| k.expect_ty()).collect(); - prepare_tuple_metadata(cx, t, &tys, unique_type_id, NO_SCOPE_METADATA).finalize(cx) + ty::Tuple(tys) => { + prepare_tuple_metadata(cx, t, tys, unique_type_id, NO_SCOPE_METADATA).finalize(cx) } // Type parameters from polymorphized functions. ty::Param(_) => MetadataCreationResult::new(param_type_metadata(cx, t), false), diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index b63851c195d..1561277b704 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -86,7 +86,7 @@ fn push_debuginfo_type_name<'tcx>( } for component_type in component_types { - push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited); + push_debuginfo_type_name(tcx, component_type, true, output, visited); push_arg_separator(cpp_like_debuginfo, output); } if !component_types.is_empty() { diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index d900379c44c..c42ff168d8c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -69,7 +69,7 @@ use rustc_middle::ty::{ self, error::TypeError, subst::{GenericArgKind, Subst, SubstsRef}, - Binder, Region, Ty, TyCtxt, TypeFoldable, + Binder, List, Region, Ty, TyCtxt, TypeFoldable, }; use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span}; use rustc_target::spec::abi; @@ -1361,7 +1361,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let mut values = (DiagnosticStyledString::normal("("), DiagnosticStyledString::normal("(")); let len = substs1.len(); - for (i, (left, right)) in substs1.types().zip(substs2.types()).enumerate() { + for (i, (left, right)) in substs1.iter().zip(substs2).enumerate() { let (x1, x2) = self.cmp(left, right); (values.0).0.extend(x1.0); (values.1).0.extend(x2.0); @@ -2042,8 +2042,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // If a tuple of length one was expected and the found expression has // parentheses around it, perhaps the user meant to write `(expr,)` to // build a tuple (issue #86100) - (ty::Tuple(_), _) => { - self.emit_tuple_wrap_err(&mut err, span, found, expected) + (ty::Tuple(fields), _) => { + self.emit_tuple_wrap_err(&mut err, span, found, fields) } // If a character was expected and the found expression is a string literal // containing a single character, perhaps the user meant to write `'c'` to @@ -2111,12 +2111,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'tcx>, span: Span, found: Ty<'tcx>, - expected: Ty<'tcx>, + expected_fields: &List>, ) { - let [expected_tup_elem] = &expected.tuple_fields().collect::>()[..] - else { return }; + let [expected_tup_elem] = expected_fields[..] else { return }; - if !same_type_modulo_infer(*expected_tup_elem, found) { + if !same_type_modulo_infer(expected_tup_elem, found) { return; } diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 205ad044554..1f504130130 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -254,7 +254,9 @@ fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String { .skip_binder() .iter() .next() - .map(|args| args.tuple_fields().map(|arg| arg.to_string()).collect::>().join(", ")) + .map(|args| { + args.tuple_fields().iter().map(|arg| arg.to_string()).collect::>().join(", ") + }) .unwrap_or_default() } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index a9530cd1bbf..30b5f9b34d0 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2621,7 +2621,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { } Tuple(..) => { // Proceed recursively, check all fields. - ty.tuple_fields().find_map(|field| ty_find_init_error(tcx, field, init)) + ty.tuple_fields().iter().find_map(|field| ty_find_init_error(tcx, field, init)) } // Conservative fallback. _ => None, @@ -2934,7 +2934,7 @@ impl ClashingExternDeclarations { ) } (Tuple(a_substs), Tuple(b_substs)) => { - a_substs.types().eq_by(b_substs.types(), |a_ty, b_ty| { + a_substs.iter().eq_by(b_substs.iter(), |a_ty, b_ty| { structurally_same_type_impl(seen_types, cx, a_ty, b_ty, ckind) }) } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 755e24d5413..b71ffa43d85 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -246,7 +246,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { } else { vec![] }; - for (i, ty) in tys.iter().map(|k| k.expect_ty()).enumerate() { + for (i, ty) in tys.iter().enumerate() { let descr_post = &format!(" in tuple element {}", i); let span = *spans.get(i).unwrap_or(&span); if check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, plural_len) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index d1c27c84dd5..12f9b9b97c0 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -427,7 +427,7 @@ fn use_verbose<'tcx>(ty: Ty<'tcx>, fn_def: bool) -> bool { ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_) => false, // Unit type ty::Tuple(g_args) if g_args.is_empty() => false, - ty::Tuple(g_args) => g_args.iter().any(|g_arg| use_verbose(g_arg.expect_ty(), fn_def)), + ty::Tuple(g_args) => g_args.iter().any(|g_arg| use_verbose(g_arg, fn_def)), ty::Array(ty, _) => use_verbose(ty, fn_def), ty::FnDef(..) => fn_def, _ => true, diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 302921cc4aa..23f9849e831 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -46,7 +46,7 @@ impl<'tcx> PlaceTy<'tcx> { let field_def = &variant_def.fields[f.index()]; field_def.ty(tcx, substs) } - ty::Tuple(ref tys) => tys[f.index()].expect_ty(), + ty::Tuple(tys) => tys[f.index()], _ => bug!("extracting field of non-tuple non-adt: {:?}", self), }; debug!("field_ty self: {:?} f: {:?} yields: {:?}", self, f, answer); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 925ef9a2ea4..7b208db81fc 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2272,7 +2272,7 @@ impl<'tcx> TyCtxt<'tcx> { ) -> PolyFnSig<'tcx> { sig.map_bound(|s| { let params_iter = match s.inputs()[0].kind() { - ty::Tuple(params) => params.into_iter().map(|k| k.expect_ty()), + ty::Tuple(params) => params.into_iter(), _ => bug!(), }; self.mk_fn_sig(params_iter, s.output(), s.c_variadic, unsafety, abi::Abi::Rust) @@ -2434,15 +2434,11 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> { - let kinds: Vec<_> = ts.iter().map(|&t| GenericArg::from(t)).collect(); - self.mk_ty(Tuple(self.intern_substs(&kinds))) + self.mk_ty(Tuple(self.intern_type_list(&ts))) } pub fn mk_tup], Ty<'tcx>>>(self, iter: I) -> I::Output { - iter.intern_with(|ts| { - let kinds: Vec<_> = ts.iter().map(|&t| GenericArg::from(t)).collect(); - self.mk_ty(Tuple(self.intern_substs(&kinds))) - }) + iter.intern_with(|ts| self.mk_ty(Tuple(self.intern_type_list(&ts)))) } #[inline] diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 64b2edd2c3f..934a6a878fe 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -116,9 +116,10 @@ impl<'tcx> Ty<'tcx> { } _ => true, }), - Projection(ProjectionTy { substs: args, .. }) | Adt(_, args) | Tuple(args) => { + Projection(ProjectionTy { substs: args, .. }) | Adt(_, args) => { args.iter().all(generic_arg_is_suggestible) } + Tuple(args) => args.iter().all(|ty| ty.is_suggestable()), Slice(ty) | RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => ty.is_suggestable(), Array(ty, c) => ty.is_suggestable() && const_is_suggestable(c.val()), _ => true, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 948a48c0826..7a3d615862c 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -201,8 +201,8 @@ impl FlagComputation { self.add_ty(ty); } - &ty::Tuple(ref substs) => { - self.add_substs(substs); + &ty::Tuple(types) => { + self.add_tys(types); } &ty::FnDef(_, substs) => { diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index f2682b8bcd8..e2289b44b5c 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -207,10 +207,9 @@ pub(crate) fn type_uninhabited_from<'tcx>( Never => DefIdForest::full(), - Tuple(ref tys) => DefIdForest::union( - tcx, - tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx, param_env)), - ), + Tuple(ref tys) => { + DefIdForest::union(tcx, tys.iter().map(|ty| ty.uninhabited_from(tcx, param_env))) + } Array(ty, len) => match len.try_eval_usize(tcx, param_env) { Some(0) | None => DefIdForest::empty(), diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 99c595fcdf1..4c427166203 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -628,7 +628,7 @@ fn polymorphize<'tcx>( } else { None }; - let has_upvars = upvars_ty.map_or(false, |ty| ty.tuple_fields().count() > 0); + let has_upvars = upvars_ty.map_or(false, |ty| !ty.tuple_fields().is_empty()); debug!("polymorphize: upvars_ty={:?} has_upvars={:?}", upvars_ty, has_upvars); struct PolymorphizationFolder<'tcx> { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 4996a13bd8c..b7b36c49459 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -712,9 +712,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized }; univariant( - &tys.iter() - .map(|k| self.layout_of(k.expect_ty())) - .collect::, _>>()?, + &tys.iter().map(|k| self.layout_of(k)).collect::, _>>()?, &ReprOptions::default(), kind, )? @@ -2382,7 +2380,7 @@ where } }, - ty::Tuple(tys) => TyMaybeWithLayout::Ty(tys[i].expect_ty()), + ty::Tuple(tys) => TyMaybeWithLayout::Ty(tys[i]), // ADTs. ty::Adt(def, substs) => { @@ -3012,7 +3010,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { if let Some(input) = sig.inputs().last() { if let ty::Tuple(tupled_arguments) = input.kind() { inputs = &sig.inputs()[0..sig.inputs().len() - 1]; - tupled_arguments.iter().map(|k| k.expect_ty()).collect() + tupled_arguments } else { bug!( "argument to function with \"rust-call\" ABI \ @@ -3027,7 +3025,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } } else { assert!(sig.c_variadic || extra_args.is_empty()); - extra_args.to_vec() + extra_args }; let target = &self.tcx.sess.target; @@ -3155,8 +3153,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { ret: arg_of(sig.output(), None)?, args: inputs .iter() - .cloned() - .chain(extra_args) + .copied() + .chain(extra_args.iter().copied()) .chain(caller_location) .enumerate() .map(|(i, ty)| arg_of(ty, Some(i))) diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 94cea505c32..8d7f6d84c7c 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -287,7 +287,6 @@ fn characteristic_def_id_of_type_cached<'a>( ty::Ref(_, ty, _) => characteristic_def_id_of_type_cached(ty, visited), ty::Tuple(ref tys) => tys.iter().find_map(|ty| { - let ty = ty.expect_ty(); if visited.insert(ty) { return characteristic_def_id_of_type_cached(ty, visited); } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index befd9ebb477..5c5d0598781 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -845,7 +845,7 @@ pub trait PrettyPrinter<'tcx>: write("{}{}(", if paren_needed { "(" } else { "" }, name) ); - for (idx, ty) in arg_tys.tuple_fields().enumerate() { + for (idx, ty) in arg_tys.tuple_fields().iter().enumerate() { if idx > 0 { p!(", "); } @@ -1032,12 +1032,11 @@ pub trait PrettyPrinter<'tcx>: // Special-case `Fn(...) -> ...` and resugar it. let fn_trait_kind = cx.tcx().fn_trait_kind_from_lang_item(principal.def_id); if !cx.tcx().sess.verbose() && fn_trait_kind.is_some() { - if let ty::Tuple(ref args) = principal.substs.type_at(0).kind() { + if let ty::Tuple(tys) = principal.substs.type_at(0).kind() { let mut projections = predicates.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { - let tys: Vec<_> = args.iter().map(|k| k.expect_ty()).collect(); p!(pretty_fn_sig( - &tys, + tys, false, proj.skip_binder().term.ty().expect("Return type was a const") )); diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 7c57d42631a..42ddbcc1e2f 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -501,9 +501,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( (&ty::Tuple(as_), &ty::Tuple(bs)) => { if as_.len() == bs.len() { - Ok(tcx.mk_tup( - iter::zip(as_, bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())), - )?) + Ok(tcx.mk_tup(iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)))?) } else if !(as_.is_empty() || bs.is_empty()) { Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len()))) } else { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 7c6d6ea1cb6..02a4df637d8 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -200,8 +200,7 @@ pub enum TyKind<'tcx> { Never, /// A tuple type. For example, `(i32, bool)`. - /// Use `Ty::tuple_fields` to iterate over the field types. - Tuple(SubstsRef<'tcx>), + Tuple(&'tcx List>), /// The projection of an associated type. For example, /// `>::N`. @@ -2155,18 +2154,9 @@ impl<'tcx> Ty<'tcx> { /// Iterates over tuple fields. /// Panics when called on anything but a tuple. - pub fn tuple_fields(self) -> impl DoubleEndedIterator> { + pub fn tuple_fields(self) -> &'tcx List> { match self.kind() { - Tuple(substs) => substs.iter().map(|field| field.expect_ty()), - _ => bug!("tuple_fields called on non-tuple"), - } - } - - /// Get the `i`-th element of a tuple. - /// Panics when called on anything but a tuple. - pub fn tuple_element_ty(self, i: usize) -> Option> { - match self.kind() { - Tuple(substs) => substs.iter().nth(i).map(|field| field.expect_ty()), + Tuple(substs) => substs, _ => bug!("tuple_fields called on non-tuple"), } } @@ -2367,7 +2357,7 @@ impl<'tcx> Ty<'tcx> { ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => false, - ty::Tuple(tys) => tys.iter().all(|ty| ty.expect_ty().is_trivially_sized(tcx)), + ty::Tuple(tys) => tys.iter().all(|ty| ty.is_trivially_sized(tcx)), ty::Adt(def, _substs) => def.sized_constraint(tcx).is_empty(), diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 92d9cb2fc1b..c13aecd1b14 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -248,7 +248,7 @@ impl<'tcx> TyCtxt<'tcx> { } ty::Tuple(tys) if let Some((&last_ty, _)) = tys.split_last() => { - ty = last_ty.expect_ty(); + ty = last_ty; } ty::Tuple(_) => break, @@ -319,9 +319,9 @@ impl<'tcx> TyCtxt<'tcx> { } } (&Tuple(a_tys), &Tuple(b_tys)) if a_tys.len() == b_tys.len() => { - if let Some(a_last) = a_tys.last() { - a = a_last.expect_ty(); - b = b_tys.last().unwrap().expect_ty(); + if let Some(&a_last) = a_tys.last() { + a = a_last; + b = *b_tys.last().unwrap(); } else { break; } @@ -746,7 +746,7 @@ impl<'tcx> Ty<'tcx> { | ty::FnDef(..) | ty::Error(_) | ty::FnPtr(_) => true, - ty::Tuple(_) => self.tuple_fields().all(|f| Self::is_trivially_freeze(f)), + ty::Tuple(fields) => fields.iter().all(Self::is_trivially_freeze), ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_freeze(), ty::Adt(..) | ty::Bound(..) @@ -786,7 +786,7 @@ impl<'tcx> Ty<'tcx> { | ty::FnDef(..) | ty::Error(_) | ty::FnPtr(_) => true, - ty::Tuple(_) => self.tuple_fields().all(|f| Self::is_trivially_unpin(f)), + ty::Tuple(fields) => fields.iter().all(Self::is_trivially_unpin), ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_unpin(), ty::Adt(..) | ty::Bound(..) @@ -1042,7 +1042,7 @@ pub fn needs_drop_components<'tcx>( } } // If any field needs drop, then the whole tuple does. - ty::Tuple(..) => ty.tuple_fields().try_fold(SmallVec::new(), move |mut acc, elem| { + ty::Tuple(fields) => fields.iter().try_fold(SmallVec::new(), move |mut acc, elem| { acc.extend(needs_drop_components(elem, target_layout)?); Ok(acc) }), @@ -1092,7 +1092,7 @@ pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool { ty::Array(ty, _) | ty::Slice(ty) => is_trivially_const_drop(ty), - ty::Tuple(tys) => tys.iter().all(|ty| is_trivially_const_drop(ty.expect_ty())), + ty::Tuple(tys) => tys.iter().all(|ty| is_trivially_const_drop(ty)), } } diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index ab70c15160c..9f57e1a977a 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -175,10 +175,10 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::Opaque(_, substs) | ty::Closure(_, substs) | ty::Generator(_, substs, _) - | ty::Tuple(substs) | ty::FnDef(_, substs) => { stack.extend(substs.iter().rev()); } + ty::Tuple(ts) => stack.extend(ts.as_substs().iter().rev()), ty::GeneratorWitness(ts) => { stack.extend(ts.skip_binder().iter().rev().map(|ty| ty.into())); } 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 1e94c41d88d..389f711099b 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -256,7 +256,7 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>( // We must have inferred the capture types since we are building MIR, therefore // it's safe to call `tuple_element_ty` and we can unwrap here because // we know that the capture exists and is the `capture_index`-th capture. - let var_ty = substs.tupled_upvars_ty().tuple_element_ty(capture_index).unwrap(); + let var_ty = substs.tupled_upvars_ty().tuple_fields()[capture_index]; upvar_resolved_place_builder = upvar_resolved_place_builder.field(Field::new(capture_index), var_ty); diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index 1d31516e246..1c4c668c0f2 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -1209,7 +1209,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { ) -> Self { let ret = match constructor { Single | Variant(_) => match ty.kind() { - ty::Tuple(fs) => Fields::wildcards_from_tys(cx, fs.iter().map(|ty| ty.expect_ty())), + ty::Tuple(fs) => Fields::wildcards_from_tys(cx, fs.iter()), ty::Ref(_, rty, _) => Fields::wildcards_from_tys(cx, once(*rty)), ty::Adt(adt, substs) => { if adt.is_box() { @@ -1315,11 +1315,8 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { match pat.ty.kind() { ty::Tuple(fs) => { ctor = Single; - let mut wilds: SmallVec<[_; 2]> = fs - .iter() - .map(|ty| ty.expect_ty()) - .map(DeconstructedPat::wildcard) - .collect(); + let mut wilds: SmallVec<[_; 2]> = + fs.iter().map(DeconstructedPat::wildcard).collect(); for pat in subpatterns { wilds[pat.field.index()] = mkpat(&pat.pattern); } diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 3e1013b0351..774df752113 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -866,10 +866,7 @@ where let tys: Vec<_> = substs.as_generator().upvar_tys().collect(); self.open_drop_for_tuple(&tys) } - ty::Tuple(..) => { - let tys: Vec<_> = ty.tuple_fields().collect(); - self.open_drop_for_tuple(&tys) - } + ty::Tuple(fields) => self.open_drop_for_tuple(fields), ty::Adt(def, substs) => { if def.is_box() { self.open_drop_for_box(def, substs) diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 5810ce6edc9..6075f572a65 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -843,12 +843,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // FIXME: enable the general case stated above ^. let ty = value.layout.ty; // Only do it for tuples - if let ty::Tuple(substs) = ty.kind() { + if let ty::Tuple(types) = ty.kind() { // Only do it if tuple is also a pair with two scalars - if substs.len() == 2 { + if let [ty1, ty2] = types[..] { let alloc = self.use_ecx(|this| { - let ty1 = substs[0].expect_ty(); - let ty2 = substs[1].expect_ty(); let ty_is_scalar = |ty| { this.ecx.layout_of(ty).ok().map(|layout| layout.abi.is_scalar()) == Some(true) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index a00262a2201..6078abcbb8f 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -692,8 +692,7 @@ impl<'tcx> Inliner<'tcx> { // The `tmp0`, `tmp1`, and `tmp2` in our example abonve. let tuple_tmp_args = tuple_tys.iter().enumerate().map(|(i, ty)| { // This is e.g., `tuple_tmp.0` in our example above. - let tuple_field = - Operand::Move(tcx.mk_place_field(tuple, Field::new(i), ty.expect_ty())); + let tuple_field = Operand::Move(tcx.mk_place_field(tuple, Field::new(i), ty)); // Spill to a local to make e.g., `tmp0`. self.create_temp_if_necessary(tuple_field, callsite, caller_body) diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index fc5ac97e3e1..6d082748939 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -148,8 +148,8 @@ fn is_needs_drop_and_init<'tcx>( }) } - ty::Tuple(_) => ty - .tuple_fields() + ty::Tuple(fields) => fields + .iter() .enumerate() .map(|(f, f_ty)| (Field::from_usize(f), f_ty, mpi)) .any(field_needs_drop_and_init), diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 837295292b9..9533e869bc5 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -461,10 +461,10 @@ impl<'tcx> CloneShimBuilder<'tcx> { fn tuple_like_shim(&mut self, dest: Place<'tcx>, src: Place<'tcx>, tys: I) where - I: Iterator>, + I: IntoIterator>, { let mut previous_field = None; - for (i, ity) in tys.enumerate() { + for (i, ity) in tys.into_iter().enumerate() { let field = Field::new(i); let src_field = self.tcx.mk_place_field(src, field, ity); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index c21c3d3ac33..62b5436142f 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -446,7 +446,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { ty::Tuple(tys) => { self.push("T"); - for ty in tys.iter().map(|k| k.expect_ty()) { + for ty in tys.iter() { self = ty.print(self)?; } self.push("E"); 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 c3df17c83bb..8746d66ebb6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -834,10 +834,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1); let expected = match expected_ty.kind() { - ty::Tuple(ref tys) => tys - .iter() - .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span))) - .collect(), + ty::Tuple(ref tys) => { + tys.iter().map(|t| ArgKind::from_expected_ty(t, Some(span))).collect() + } _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())], }; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index e2b0c9f6248..e162e943e36 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1301,7 +1301,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if tcx.fn_trait_kind_from_lang_item(trait_ref.def_id()).is_some() => { tcx.mk_fn_sig( - inputs.iter().map(|k| k.expect_ty()), + inputs.iter(), tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))), false, hir::Unsafety::Normal, diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 55903a3c36a..066f3ffada5 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -108,7 +108,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { // (T1..Tn) and closures have same properties as T1..Tn -- // check if *any* of those are trivial. - ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())), + ty::Tuple(tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t)), ty::Closure(_, ref substs) => { trivial_dropck_outlives(tcx, substs.as_closure().tupled_upvars_ty()) } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 84bc7cdff28..da9b50ba2e6 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1058,9 +1058,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Check that the source tuple with the target's // last element is equal to the target. - let new_tuple = tcx.mk_tup( - a_mid.iter().map(|k| k.expect_ty()).chain(iter::once(b_last.expect_ty())), - ); + let new_tuple = tcx.mk_tup(a_mid.iter().copied().chain(iter::once(b_last))); let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) @@ -1076,8 +1074,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.cause.clone(), obligation.predicate.def_id(), obligation.recursion_depth + 1, - a_last.expect_ty(), - &[b_last], + a_last, + &[b_last.into()], ) })); } @@ -1140,7 +1138,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { stack.push(ty); } ty::Tuple(tys) => { - stack.extend(tys.iter().map(|ty| ty.expect_ty())); + stack.extend(tys.iter()); } ty::Closure(_, substs) => { stack.push(substs.as_closure().tupled_upvars_ty()); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index ad31751e6bb..0ed29036e4b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1852,9 +1852,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => None, ty::Tuple(tys) => Where( - obligation - .predicate - .rebind(tys.last().into_iter().map(|k| k.expect_ty()).collect()), + obligation.predicate.rebind(tys.last().map_or_else(Vec::new, |&last| vec![last])), ), ty::Adt(def, substs) => { @@ -1917,7 +1915,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Tuple(tys) => { // (*) binder moved here - Where(obligation.predicate.rebind(tys.iter().map(|k| k.expect_ty()).collect())) + Where(obligation.predicate.rebind(tys.iter().collect())) } ty::Closure(_, substs) => { @@ -1997,7 +1995,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Tuple(ref tys) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet - t.rebind(tys.iter().map(|k| k.expect_ty()).collect()) + t.rebind(tys.iter().collect()) } ty::Closure(_, ref substs) => { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 2dd3b77a73c..7da5c50d230 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -529,8 +529,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { ty::Tuple(ref tys) => { if let Some((_last, rest)) = tys.split_last() { - for elem in rest { - self.require_sized(elem.expect_ty(), traits::TupleElem); + for &elem in rest { + self.require_sized(elem, traits::TupleElem); } } } diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index fee014ea7ef..8d4b97571a6 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -565,7 +565,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t // FIXME(chalk): actually get hidden ty self.interner .tcx - .mk_ty(ty::Tuple(self.interner.tcx.intern_substs(&[]))) + .mk_ty(ty::Tuple(self.interner.tcx.intern_type_list(&[]))) .lower_into(self.interner) } diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 9d810d0881b..2cd179526bf 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -326,7 +326,9 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { ty::Generator(_def_id, _substs, _) => unimplemented!(), ty::GeneratorWitness(_) => unimplemented!(), ty::Never => chalk_ir::TyKind::Never, - ty::Tuple(substs) => chalk_ir::TyKind::Tuple(substs.len(), substs.lower_into(interner)), + ty::Tuple(types) => { + chalk_ir::TyKind::Tuple(types.len(), types.as_substs().lower_into(interner)) + } ty::Projection(proj) => chalk_ir::TyKind::Alias(proj.lower_into(interner)), ty::Opaque(def_id, substs) => { chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { @@ -398,7 +400,9 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty> { TyKind::Generator(..) => unimplemented!(), TyKind::GeneratorWitness(..) => unimplemented!(), TyKind::Never => ty::Never, - TyKind::Tuple(_len, substitution) => ty::Tuple(substitution.lower_into(interner)), + TyKind::Tuple(_len, substitution) => { + ty::Tuple(substitution.lower_into(interner).try_as_type_list().unwrap()) + } TyKind::Slice(ty) => ty::Slice(ty.lower_into(interner)), TyKind::Raw(mutbl, ty) => ty::RawPtr(ty::TypeAndMut { ty: ty.lower_into(interner), diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index 455fc46a42e..3658f8e5735 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -198,14 +198,7 @@ fn dtorck_constraint_for_ty<'tcx>( ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| { for ty in tys.iter() { - dtorck_constraint_for_ty( - tcx, - span, - for_ty, - depth + 1, - ty.expect_ty(), - constraints, - )?; + dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty, constraints)?; } Ok::<_, NoSolution>(()) })?, diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs index b08f8f62308..11a57688580 100644 --- a/compiler/rustc_ty_utils/src/representability.rs +++ b/compiler/rustc_ty_utils/src/representability.rs @@ -70,9 +70,9 @@ fn are_inner_types_recursive<'tcx>( ) -> Representability { debug!("are_inner_types_recursive({:?}, {:?}, {:?})", ty, seen, shadow_seen); match ty.kind() { - ty::Tuple(..) => { + ty::Tuple(fields) => { // Find non representable - fold_repr(ty.tuple_fields().map(|ty| { + fold_repr(fields.iter().map(|ty| { is_type_structurally_recursive( tcx, sp, diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 20ae986ffa4..e6ce3447548 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -24,7 +24,7 @@ fn sized_constraint_for_ty<'tcx>( Tuple(ref tys) => match tys.last() { None => vec![], - Some(ty) => sized_constraint_for_ty(tcx, adtdef, ty.expect_ty()), + Some(&ty) => sized_constraint_for_ty(tcx, adtdef, ty), }, Adt(adt, substs) => { @@ -461,9 +461,9 @@ pub fn conservative_is_privately_uninhabited_raw<'tcx>( }) }) } - ty::Tuple(..) => { + ty::Tuple(fields) => { debug!("ty::Tuple(..) =>"); - ty.tuple_fields().any(|ty| tcx.conservative_is_privately_uninhabited(param_env.and(ty))) + fields.iter().any(|ty| tcx.conservative_is_privately_uninhabited(param_env.and(ty))) } ty::Array(ty, len) => { debug!("ty::Array(ty, len) =>"); diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index a5e1b2579f8..57076d97246 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -111,7 +111,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, ty::Tuple(fields) => match fields.last() { None => Some(PointerKind::Thin), - Some(f) => self.pointer_kind(f.expect_ty(), span)?, + Some(&f) => self.pointer_kind(f, span)?, }, // Pointers to foreign types are thin, despite being unsized diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 966ef8baedd..59c8febdc30 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -270,7 +270,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("deduce_sig_from_projection: arg_param_ty={:?}", arg_param_ty); match arg_param_ty.kind() { - ty::Tuple(tys) => tys.into_iter().map(|k| k.expect_ty()).collect::>(), + &ty::Tuple(tys) => tys, _ => return None, } } else { @@ -286,7 +286,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sig = projection.rebind(self.tcx.mk_fn_sig( input_tys.iter(), - &ret_param_ty, + ret_param_ty, false, hir::Unsafety::Normal, Abi::Rust, diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index be9bf6399d7..b08ee414fa7 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1291,7 +1291,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| match flds { Some(fs) if i < fs.len() => { - let ety = fs[i].expect_ty(); + let ety = fs[i]; self.check_expr_coercable_to_type(&e, ety, None); ety } @@ -1877,13 +1877,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let fstr = field.as_str(); if let Ok(index) = fstr.parse::() { if fstr == index.to_string() { - if let Some(field_ty) = tys.get(index) { + if let Some(&field_ty) = tys.get(index) { let adjustments = self.adjust_steps(&autoderef); self.apply_adjustments(base, adjustments); self.register_predicates(autoderef.into_obligations()); self.write_field_index(expr.hir_id, index); - return field_ty.expect_ty(); + return field_ty; } } } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index d05dd517f1e..d3d42a1f37c 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -147,12 +147,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let expected_input_tys = match expected_input_tys.get(0) { Some(&ty) => match ty.kind() { - ty::Tuple(ref tys) => tys.iter().map(|k| k.expect_ty()).collect(), + ty::Tuple(tys) => tys.iter().collect(), _ => vec![], }, None => vec![], }; - (arg_types.iter().map(|k| k.expect_ty()).collect(), expected_input_tys) + (arg_types.iter().collect(), expected_input_tys) } _ => { // Otherwise, there's a mismatch, so clear out what we're expecting, and set @@ -495,12 +495,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_input_tys: &[Ty<'tcx>], provided_args: &'tcx [hir::Expr<'tcx>], ) -> Option> { - let [expected_arg_type] = &expected_input_tys[..] else { return None }; + let [expected_arg_type] = expected_input_tys[..] else { return None }; - let ty::Tuple(expected_elems) = self.resolve_vars_if_possible(*expected_arg_type).kind() + let &ty::Tuple(expected_types) = self.resolve_vars_if_possible(expected_arg_type).kind() else { return None }; - let expected_types: Vec<_> = expected_elems.iter().map(|k| k.expect_ty()).collect(); let supplied_types: Vec<_> = provided_args.iter().map(|arg| self.check_expr(arg)).collect(); let all_match = iter::zip(expected_types, supplied_types) diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index d360f34ae70..9684237be83 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -539,16 +539,16 @@ pub fn check_must_not_suspend_ty<'tcx>( } has_emitted } - ty::Tuple(_) => { + ty::Tuple(fields) => { let mut has_emitted = false; let comps = match data.expr.map(|e| &e.kind) { Some(hir::ExprKind::Tup(comps)) => { - debug_assert_eq!(comps.len(), ty.tuple_fields().count()); + debug_assert_eq!(comps.len(), fields.len()); Some(comps) } _ => None, }; - for (i, ty) in ty.tuple_fields().enumerate() { + for (i, ty) in fields.iter().enumerate() { let descr_post = &format!(" in tuple element {}", i); let span = comps.and_then(|c| c.get(i)).map(|e| e.span).unwrap_or(data.source_span); if check_must_not_suspend_ty( diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 767979c3912..77ab1d1de42 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -9,7 +9,6 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{HirId, Pat, PatKind}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_middle::ty::subst::GenericArg; use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeFoldable}; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::hygiene::DesugaringKind; @@ -1072,7 +1071,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (ty::Adt(_, substs), [field], false) => { let field_ty = self.field_ty(pat_span, field, substs); match field_ty.kind() { - ty::Tuple(_) => field_ty.tuple_fields().count() == subpats.len(), + ty::Tuple(fields) => fields.len() == subpats.len(), _ => false, } } @@ -1183,13 +1182,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let max_len = cmp::max(expected_len, elements.len()); let element_tys_iter = (0..max_len).map(|_| { - GenericArg::from(self.next_ty_var( + self.next_ty_var( // FIXME: `MiscVariable` for now -- obtaining the span and name information // from all tuple elements isn't trivial. TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }, - )) + ) }); - let element_tys = tcx.mk_substs(element_tys_iter); + let element_tys = tcx.mk_type_list(element_tys_iter); let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); if let Some(mut err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, ti) { err.emit(); @@ -1202,7 +1201,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.mk_tup(element_tys_iter) } else { for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat(elem, element_tys[i].expect_ty(), def_bm, ti); + self.check_pat(elem, element_tys[i], def_bm, ti); } pat_ty } diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 73f7cafa162..257846324b8 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -1448,7 +1448,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } - ty::Tuple(..) => { + ty::Tuple(fields) => { // Only Field projections can be applied to a tuple. assert!( captured_by_move_projs.iter().all(|projs| matches!( @@ -1457,7 +1457,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )) ); - base_path_ty.tuple_fields().enumerate().any(|(i, element_ty)| { + fields.iter().enumerate().any(|(i, element_ty)| { let paths_using_field = captured_by_move_projs .iter() .filter_map(|projs| { diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs index 1c8f848cf28..196e476b0e3 100644 --- a/compiler/rustc_typeck/src/variance/constraints.rs +++ b/compiler/rustc_typeck/src/variance/constraints.rs @@ -278,7 +278,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { ty::Tuple(subtys) => { for subty in subtys { - self.add_constraints_from_ty(current, subty.expect_ty(), variance); + self.add_constraints_from_ty(current, subty, variance); } } From 880343c61feb5e7c09c27e9851413d71b0f6a3dd Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 7 Feb 2022 16:06:55 +0100 Subject: [PATCH 3/7] update clippy --- .../clippy_lints/src/functions/must_use.rs | 2 +- .../src/matches/redundant_pattern_match.rs | 4 ++-- src/tools/clippy/clippy_lints/src/mut_key.rs | 2 +- .../src/non_send_fields_in_send_ty.rs | 4 ++-- .../src/transmute/transmute_undefined_repr.rs | 7 +++---- src/tools/clippy/clippy_utils/src/ty.rs | 18 +++++++++--------- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index 3e3718b9445..ea9b68d1a40 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -193,7 +193,7 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &m || KNOWN_WRAPPER_TYS.iter().any(|path| match_def_path(cx, adt.did, path)) && substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys)) }, - ty::Tuple(substs) => substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys)), + ty::Tuple(substs) => substs.iter().any(|ty| is_mutable_ty(cx, ty, span, tys)), ty::Array(ty, _) | ty::Slice(ty) => is_mutable_ty(cx, ty, span, tys), ty::RawPtr(ty::TypeAndMut { ty, mutbl }) | ty::Ref(_, ty, mutbl) => { mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, span, tys) diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs index e195fddefab..677b8cdf2ba 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs @@ -58,8 +58,8 @@ fn type_needs_ordered_drop_inner<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, see // This type doesn't implement drop, so no side effects here. // Check if any component type has any. match ty.kind() { - ty::Tuple(_) => ty.tuple_fields().any(|ty| type_needs_ordered_drop_inner(cx, ty, seen)), - ty::Array(ty, _) => type_needs_ordered_drop_inner(cx, *ty, seen), + ty::Tuple(fields) => fields.iter().any(|ty| type_needs_ordered_drop_inner(cx, ty, seen)), + &ty::Array(ty, _) => type_needs_ordered_drop_inner(cx, ty, seen), ty::Adt(adt, subs) => adt .all_fields() .map(|f| f.ty(cx.tcx, subs)) diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index b4e29101b39..ce9ca15430e 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -142,7 +142,7 @@ fn is_interior_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Sp size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0) && is_interior_mutable_type(cx, inner_ty, span) }, - Tuple(..) => ty.tuple_fields().any(|ty| is_interior_mutable_type(cx, ty, span)), + Tuple(fields) => fields.iter().any(|ty| is_interior_mutable_type(cx, ty, span)), Adt(def, substs) => { // Special case for collections in `std` who's impl of `Hash` or `Ord` delegates to // that of their type parameters. Note: we don't include `HashSet` and `HashMap` diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs index f4de999a928..5168ca67b6a 100644 --- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -202,8 +202,8 @@ fn ty_allowed_with_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t // The type is known to be `!Send` and `!Copy` match ty.kind() { - ty::Tuple(_) => ty - .tuple_fields() + ty::Tuple(fields) => fields + .iter() .all(|ty| ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait)), ty::Array(ty, _) | ty::Slice(ty) => ty_allowed_with_raw_pointer_heuristic(cx, *ty, send_trait), ty::Adt(_, substs) => { diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs index 9ed5952a109..a57c819cb22 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -2,7 +2,7 @@ use super::TRANSMUTE_UNDEFINED_REPR; use clippy_utils::diagnostics::span_lint_and_then; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty::subst::{GenericArg, Subst}; +use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, Ty, TypeAndMut}; use rustc_span::Span; @@ -246,11 +246,10 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> continue; }, ty::Tuple(args) => { - let mut iter = args.iter().map(GenericArg::expect_ty); - let Some(sized_ty) = iter.find(|ty| !is_zero_sized_ty(cx, *ty)) else { + let Some(sized_ty) = args.iter().find(|&ty| !is_zero_sized_ty(cx, ty)) else { return ReducedTy::OrderedFields(ty); }; - if iter.all(|ty| is_zero_sized_ty(cx, ty)) { + if args.iter().all(|ty| is_zero_sized_ty(cx, ty)) { ty = sized_ty; continue; } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index b44899e6bd5..0d39226d970 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -169,7 +169,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { // because we don't want to lint functions returning empty arrays is_must_use_ty(cx, *ty) }, - ty::Tuple(substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)), + ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)), ty::Opaque(ref def_id, _) => { for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { if let ty::PredicateKind::Trait(trait_predicate) = predicate.kind().skip_binder() { @@ -249,11 +249,11 @@ pub fn is_non_aggregate_primitive_type(ty: Ty<'_>) -> bool { /// Returns `true` if the given type is a primitive (a `bool` or `char`, any integer or /// floating-point number type, a `str`, or an array, slice, or tuple of those types). pub fn is_recursively_primitive_type(ty: Ty<'_>) -> bool { - match ty.kind() { + match *ty.kind() { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => true, ty::Ref(_, inner, _) if *inner.kind() == ty::Str => true, - ty::Array(inner_type, _) | ty::Slice(inner_type) => is_recursively_primitive_type(*inner_type), - ty::Tuple(inner_types) => inner_types.types().all(is_recursively_primitive_type), + ty::Array(inner_type, _) | ty::Slice(inner_type) => is_recursively_primitive_type(inner_type), + ty::Tuple(inner_types) => inner_types.iter().all(is_recursively_primitive_type), _ => false, } } @@ -393,9 +393,9 @@ pub fn same_type_and_consts<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { /// Checks if a given type looks safe to be uninitialized. pub fn is_uninit_value_valid_for_ty(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { - match ty.kind() { - ty::Array(component, _) => is_uninit_value_valid_for_ty(cx, *component), - ty::Tuple(types) => types.types().all(|ty| is_uninit_value_valid_for_ty(cx, ty)), + match *ty.kind() { + ty::Array(component, _) => is_uninit_value_valid_for_ty(cx, component), + ty::Tuple(types) => types.iter().all(|ty| is_uninit_value_valid_for_ty(cx, ty)), ty::Adt(adt, _) => cx.tcx.lang_items().maybe_uninit() == Some(adt.did), _ => false, } @@ -426,8 +426,8 @@ impl<'tcx> ExprFnSig<'tcx> { pub fn input(self, i: usize) -> Binder<'tcx, Ty<'tcx>> { match self { Self::Sig(sig) => sig.input(i), - Self::Closure(sig) => sig.input(0).map_bound(|ty| ty.tuple_element_ty(i).unwrap()), - Self::Trait(inputs, _) => inputs.map_bound(|ty| ty.tuple_element_ty(i).unwrap()), + Self::Closure(sig) => sig.input(0).map_bound(|ty| ty.tuple_fields()[i]), + Self::Trait(inputs, _) => inputs.map_bound(|ty| ty.tuple_fields()[i]), } } From 7d5d6c055b5d8008764a04e98c63ac1711a0a25a Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 7 Feb 2022 16:07:12 +0100 Subject: [PATCH 4/7] update rustdoc --- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/clean/utils.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 187bc13357a..76994f2ee17 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1543,7 +1543,7 @@ impl<'tcx> Clean for Ty<'tcx> { DynTrait(bounds, lifetime) } - ty::Tuple(t) => Tuple(t.iter().map(|t| t.expect_ty().clean(cx)).collect()), + ty::Tuple(t) => Tuple(t.iter().map(|t| t.clean(cx)).collect()), ty::Projection(ref data) => data.clean(cx), diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index fe1992a5d7e..c2d1d4756fd 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -109,7 +109,7 @@ fn external_generic_args( if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() { let inputs = match ty_kind.unwrap() { - ty::Tuple(tys) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(), + ty::Tuple(tys) => tys.iter().map(|t| t.clean(cx)).collect(), _ => return GenericArgs::AngleBracketed { args, bindings: bindings.into() }, }; let output = None; From 758f4e715867573a4c56f6b92e96d6c4960bc2e8 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 7 Feb 2022 16:08:04 +0100 Subject: [PATCH 5/7] optimize `TypeFoldable` for 2 element tuples --- .../rustc_middle/src/ty/structural_impls.rs | 13 ------- compiler/rustc_middle/src/ty/subst.rs | 39 +++++++++++++++++++ 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 8711216b042..42d7b141166 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -889,19 +889,6 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List TypeFoldable<'tcx> for &'tcx ty::List> { - fn try_super_fold_with>( - self, - folder: &mut F, - ) -> Result { - ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v)) - } - - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) - } -} - impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List { fn try_super_fold_with>( self, diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 7085168781c..59a560f7342 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -458,6 +458,45 @@ impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> { } } +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + // This code is fairly hot, though not as hot as `SubstsRef`. + // + // When compiling stage 2, I get the following results: + // + // len | total | % + // --- | --------- | ----- + // 2 | 15083590 | 48.1 + // 3 | 7540067 | 24.0 + // 1 | 5300377 | 16.9 + // 4 | 1351897 | 4.3 + // 0 | 1256849 | 4.0 + // + // I've tried it with some private repositories and got + // close to the same result, with 4 and 0 swapping places + // sometimes. + match self.len() { + 2 => { + let param0 = self[0].try_fold_with(folder)?; + let param1 = self[1].try_fold_with(folder)?; + if param0 == self[0] && param1 == self[1] { + Ok(self) + } else { + Ok(folder.tcx().intern_type_list(&[param0, param1])) + } + } + _ => ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v)), + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { + self.iter().try_for_each(|t| t.visit_with(visitor)) + } +} + /////////////////////////////////////////////////////////////////////////// // Public trait `Subst` // From c909b6dc2254b1ceca049f878e67a8ab86118d37 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 11 Feb 2022 13:20:38 +0100 Subject: [PATCH 6/7] add comment to `Lift` impls --- compiler/rustc_middle/src/ty/context.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 7b208db81fc..4b4fcaa9c18 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1655,6 +1655,8 @@ macro_rules! nop_lift { type Lifted = $lifted; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { if tcx.interners.$set.contains_pointer_to(&InternedInSet(self.0.0)) { + // SAFETY: `self` is interned and therefore valid + // for the entire lifetime of the `TyCtxt`. Some(unsafe { mem::transmute(self) }) } else { None @@ -1674,7 +1676,9 @@ impl<'a, 'tcx> Lift<'tcx> for &'a List> { return Some(List::empty()); } if tcx.interners.substs.contains_pointer_to(&InternedInSet(self.as_substs())) { - Some(unsafe { mem::transmute(self) }) + // SAFETY: `self` is interned and therefore valid + // for the entire lifetime of the `TyCtxt`. + Some(unsafe { mem::transmute::<&'a List>, &'tcx List>>(self) }) } else { None } From 80f56cdc2a749f1262518d2aa7597cf908b9e059 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 18 Feb 2022 12:31:12 +0100 Subject: [PATCH 7/7] review --- compiler/rustc_middle/src/ty/impls_ty.rs | 8 ++++++++ compiler/rustc_middle/src/ty/subst.rs | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index 4e3661dda17..54a345daec8 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -70,12 +70,20 @@ impl<'a, 'tcx> HashStable> for ty::subst::GenericArgKin // See `fn intern_type_list` for more details. // // We therefore hash types without adding a hash for their discriminant. + // + // In order to make it very unlikely for the sequence of bytes being hashed for + // a `GenericArgKind::Type` to be the same as the sequence of bytes being + // hashed for one of the other variants, we hash a `0xFF` byte before hashing + // their discriminant (since the discriminant of `TyKind` is unlikely to ever start + // with 0xFF). ty::subst::GenericArgKind::Type(ty) => ty.hash_stable(hcx, hasher), ty::subst::GenericArgKind::Const(ct) => { + 0xFFu8.hash_stable(hcx, hasher); mem::discriminant(self).hash_stable(hcx, hasher); ct.hash_stable(hcx, hasher); } ty::subst::GenericArgKind::Lifetime(lt) => { + 0xFFu8.hash_stable(hcx, hasher); mem::discriminant(self).hash_stable(hcx, hasher); lt.hash_stable(hcx, hasher); } diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 59a560f7342..364ba07a441 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -51,7 +51,8 @@ pub enum GenericArgKind<'tcx> { /// This function goes from `&'a [Ty<'tcx>]` to `&'a [GenericArg<'tcx>]` /// /// This is sound as, for types, `GenericArg` is just -/// `NonZeroUsize::new_unchecked(ty as *const _ as usize)`. +/// `NonZeroUsize::new_unchecked(ty as *const _ as usize)` as +/// long as we use `0` for the `TYPE_TAG`. pub fn ty_slice_as_generic_args<'a, 'tcx>(ts: &'a [Ty<'tcx>]) -> &'a [GenericArg<'tcx>] { assert_eq!(TYPE_TAG, 0); // SAFETY: the whole slice is valid and immutable.