diff options
Diffstat (limited to 'compiler/rustc_middle/src')
35 files changed, 543 insertions, 293 deletions
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index be8a3403ba9..bd315577efb 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -47,10 +47,10 @@ pub struct UnsupportedUnion { // FIXME(autodiff): I should get used somewhere #[derive(Diagnostic)] #[diag(middle_autodiff_unsafe_inner_const_ref)] -pub struct AutodiffUnsafeInnerConstRef { +pub struct AutodiffUnsafeInnerConstRef<'tcx> { #[primary_span] pub span: Span, - pub ty: String, + pub ty: Ty<'tcx>, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index 171542d1279..d0dbf64dc59 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -1,8 +1,9 @@ +use std::sync::OnceLock; + use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph; use rustc_data_structures::graph::dominators::{Dominators, dominators}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::sync::OnceLock; use rustc_index::{IndexSlice, IndexVec}; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 95bc9b71fe0..ba65a711815 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -222,7 +222,7 @@ impl AllocError { } /// The information that makes up a memory access: offset and size. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone)] pub struct AllocRange { pub start: Size, pub size: Size, @@ -470,7 +470,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> // Find the provenance. let (offset, _prov) = self .provenance - .range_get_ptrs(range, cx) + .range_ptrs_get(range, cx) .first() .copied() .expect("there must be provenance somewhere here"); diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs index 2f13f963578..c9525df1f79 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs @@ -2,6 +2,7 @@ //! representation for the common case where PTR_SIZE consecutive bytes have the same provenance. use std::cmp; +use std::ops::Range; use rustc_abi::{HasDataLayout, Size}; use rustc_data_structures::sorted_map::SortedMap; @@ -66,24 +67,33 @@ impl ProvenanceMap { } impl<Prov: Provenance> ProvenanceMap<Prov> { + fn adjusted_range_ptrs(range: AllocRange, cx: &impl HasDataLayout) -> Range<Size> { + // We have to go back `pointer_size - 1` bytes, as that one would still overlap with + // the beginning of this range. + let adjusted_start = Size::from_bytes( + range.start.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1), + ); + adjusted_start..range.end() + } + /// Returns all ptr-sized provenance in the given range. /// If the range has length 0, returns provenance that crosses the edge between `start-1` and /// `start`. - pub(super) fn range_get_ptrs( + pub(super) fn range_ptrs_get( &self, range: AllocRange, cx: &impl HasDataLayout, ) -> &[(Size, Prov)] { - // We have to go back `pointer_size - 1` bytes, as that one would still overlap with - // the beginning of this range. - let adjusted_start = Size::from_bytes( - range.start.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1), - ); - self.ptrs.range(adjusted_start..range.end()) + self.ptrs.range(Self::adjusted_range_ptrs(range, cx)) + } + + /// `pm.range_ptrs_is_empty(r, cx)` == `pm.range_ptrs_get(r, cx).is_empty()`, but is faster. + pub(super) fn range_ptrs_is_empty(&self, range: AllocRange, cx: &impl HasDataLayout) -> bool { + self.ptrs.range_is_empty(Self::adjusted_range_ptrs(range, cx)) } /// Returns all byte-wise provenance in the given range. - fn range_get_bytes(&self, range: AllocRange) -> &[(Size, Prov)] { + fn range_bytes_get(&self, range: AllocRange) -> &[(Size, Prov)] { if let Some(bytes) = self.bytes.as_ref() { bytes.range(range.start..range.end()) } else { @@ -91,9 +101,14 @@ impl<Prov: Provenance> ProvenanceMap<Prov> { } } + /// Same as `range_bytes_get(range).is_empty()`, but faster. + fn range_bytes_is_empty(&self, range: AllocRange) -> bool { + self.bytes.as_ref().is_none_or(|bytes| bytes.range_is_empty(range.start..range.end())) + } + /// Get the provenance of a single byte. pub fn get(&self, offset: Size, cx: &impl HasDataLayout) -> Option<Prov> { - let prov = self.range_get_ptrs(alloc_range(offset, Size::from_bytes(1)), cx); + let prov = self.range_ptrs_get(alloc_range(offset, Size::from_bytes(1)), cx); debug_assert!(prov.len() <= 1); if let Some(entry) = prov.first() { // If it overlaps with this byte, it is on this byte. @@ -117,7 +132,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> { /// limit access to provenance outside of the `Allocation` abstraction. /// pub fn range_empty(&self, range: AllocRange, cx: &impl HasDataLayout) -> bool { - self.range_get_ptrs(range, cx).is_empty() && self.range_get_bytes(range).is_empty() + self.range_ptrs_is_empty(range, cx) && self.range_bytes_is_empty(range) } /// Yields all the provenances stored in this map. @@ -149,12 +164,14 @@ impl<Prov: Provenance> ProvenanceMap<Prov> { // provenance that overlaps with the given range. let (first, last) = { // Find all provenance overlapping the given range. - let provenance = self.range_get_ptrs(range, cx); - if provenance.is_empty() { - // No provenance in this range, we are done. + if self.range_ptrs_is_empty(range, cx) { + // No provenance in this range, we are done. This is the common case. return Ok(()); } + // This redoes some of the work of `range_get_ptrs_is_empty`, but this path is much + // colder than the early return above, so it's worth it. + let provenance = self.range_ptrs_get(range, cx); ( provenance.first().unwrap().0, provenance.last().unwrap().0 + cx.data_layout().pointer_size, @@ -267,8 +284,8 @@ impl<Prov: Provenance> ProvenanceMap<Prov> { // This includes the existing bytewise provenance in the range, and ptr provenance // that overlaps with the begin/end of the range. let mut dest_bytes_box = None; - let begin_overlap = self.range_get_ptrs(alloc_range(src.start, Size::ZERO), cx).first(); - let end_overlap = self.range_get_ptrs(alloc_range(src.end(), Size::ZERO), cx).first(); + let begin_overlap = self.range_ptrs_get(alloc_range(src.start, Size::ZERO), cx).first(); + let end_overlap = self.range_ptrs_get(alloc_range(src.end(), Size::ZERO), cx).first(); if !Prov::OFFSET_IS_ADDR { // There can't be any bytewise provenance, and we cannot split up the begin/end overlap. if let Some(entry) = begin_overlap { @@ -291,10 +308,10 @@ impl<Prov: Provenance> ProvenanceMap<Prov> { } else { trace!("no start overlapping entry"); } + // Then the main part, bytewise provenance from `self.bytes`. - if let Some(all_bytes) = self.bytes.as_ref() { - bytes.extend(all_bytes.range(src.start..src.end())); - } + bytes.extend(self.range_bytes_get(src)); + // And finally possibly parts of a pointer at the end. if let Some(entry) = end_overlap { trace!("end overlapping entry: {entry:?}"); diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 743812e3a20..890756a17ca 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -248,7 +248,7 @@ pub enum InvalidMetaKind { } impl IntoDiagArg for InvalidMetaKind { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue { DiagArgValue::Str(Cow::Borrowed(match self { InvalidMetaKind::SliceTooBig => "slice_too_big", InvalidMetaKind::TooBig => "too_big", @@ -282,7 +282,7 @@ pub struct Misalignment { macro_rules! impl_into_diag_arg_through_debug { ($($ty:ty),*$(,)?) => {$( impl IntoDiagArg for $ty { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue { DiagArgValue::Str(Cow::Owned(format!("{self:?}"))) } } @@ -401,7 +401,7 @@ pub enum PointerKind { } impl IntoDiagArg for PointerKind { - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue { DiagArgValue::Str( match self { Self::Ref(_) => "ref", @@ -666,7 +666,7 @@ macro_rules! err_ub_custom { msg: || $msg, add_args: Box::new(move |mut set_arg| { $($( - set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name)); + set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name, &mut None)); )*)? }) } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 875f5282bf2..f880b1364c2 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -319,6 +319,7 @@ pub fn write_mir_pretty<'tcx>( writeln!(w, "// WARNING: This output format is intended for human consumers only")?; writeln!(w, "// and is subject to change without notice. Knock yourself out.")?; + writeln!(w, "// HINT: See also -Z dump-mir for MIR at specific points during compilation.")?; let mut first = true; for def_id in dump_mir_def_ids(tcx, single) { diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index b887370fd69..bc77f22af67 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -357,7 +357,7 @@ impl<O> AssertKind<O> { macro_rules! add { ($name: expr, $value: expr) => { - adder($name.into(), $value.into_diag_arg()); + adder($name.into(), $value.into_diag_arg(&mut None)); }; } diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 5950ac295af..9308570d89d 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -23,19 +23,13 @@ pub struct Preorder<'a, 'tcx> { body: &'a Body<'tcx>, visited: DenseBitSet<BasicBlock>, worklist: Vec<BasicBlock>, - root_is_start_block: bool, } impl<'a, 'tcx> Preorder<'a, 'tcx> { pub fn new(body: &'a Body<'tcx>, root: BasicBlock) -> Preorder<'a, 'tcx> { let worklist = vec![root]; - Preorder { - body, - visited: DenseBitSet::new_empty(body.basic_blocks.len()), - worklist, - root_is_start_block: root == START_BLOCK, - } + Preorder { body, visited: DenseBitSet::new_empty(body.basic_blocks.len()), worklist } } } @@ -71,15 +65,11 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> { } fn size_hint(&self) -> (usize, Option<usize>) { - // All the blocks, minus the number of blocks we've visited. - let upper = self.body.basic_blocks.len() - self.visited.count(); + // The worklist might be only things already visited. + let lower = 0; - let lower = if self.root_is_start_block { - // We will visit all remaining blocks exactly once. - upper - } else { - self.worklist.len() - }; + // This is extremely loose, but it's not worth a popcnt loop to do better. + let upper = self.body.basic_blocks.len(); (lower, Some(upper)) } @@ -108,7 +98,6 @@ pub struct Postorder<'a, 'tcx> { basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>, visited: DenseBitSet<BasicBlock>, visit_stack: Vec<(BasicBlock, Successors<'a>)>, - root_is_start_block: bool, /// A non-empty `extra` allows for a precise calculation of the successors. extra: Option<(TyCtxt<'tcx>, Instance<'tcx>)>, } @@ -123,7 +112,6 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { basic_blocks, visited: DenseBitSet::new_empty(basic_blocks.len()), visit_stack: Vec::new(), - root_is_start_block: root == START_BLOCK, extra, }; @@ -211,16 +199,13 @@ impl<'tcx> Iterator for Postorder<'_, 'tcx> { } fn size_hint(&self) -> (usize, Option<usize>) { - // All the blocks, minus the number of blocks we've visited. - let upper = self.basic_blocks.len() - self.visited.count(); - - let lower = if self.root_is_start_block { - // We will visit all remaining blocks exactly once. - upper - } else { - self.visit_stack.len() - }; + // These bounds are not at all tight, but that's fine. + // It's not worth a popcnt loop in `DenseBitSet` to improve the upper, + // and in mono-reachable we can't be precise anyway. + // Leaning on amortized growth is fine. + let lower = self.visit_stack.len(); + let upper = self.basic_blocks.len(); (lower, Some(upper)) } } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 1489d57aba6..98314b5abfd 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -508,6 +508,14 @@ impl<'tcx, T: Clone> Key for CanonicalQueryInput<'tcx, T> { } } +impl<'tcx, T: Clone> Key for (CanonicalQueryInput<'tcx, T>, bool) { + type Cache<V> = DefaultCache<Self, V>; + + fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + impl Key for (Symbol, u32, u32) { type Cache<V> = DefaultCache<Self, V>; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 7c4ea06a746..4ad4427594c 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -143,11 +143,11 @@ rustc_queries! { /// Represents crate as a whole (as distinct from the top-level crate module). /// - /// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir().krate()`), + /// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir_crate()`), /// we will have to assume that any change means that you need to be recompiled. /// This is because the `hir_crate` query gives you access to all other items. - /// To avoid this fate, do not call `tcx.hir().krate()`; instead, - /// prefer wrappers like `tcx.visit_all_items_in_krate()`. + /// To avoid this fate, do not call `tcx.hir_crate()`; instead, + /// prefer wrappers like [`TyCtxt::hir_visit_all_item_likes_in_crate`]. query hir_crate(key: ()) -> &'tcx Crate<'tcx> { arena_cache eval_always @@ -748,6 +748,15 @@ rustc_queries! { } } + /// Compute the conditions that need to hold for a conditionally-const item to be const. + /// That is, compute the set of `~const` where clauses for a given item. + /// + /// This can be thought of as the `~const` equivalent of `predicates_of`. These are the + /// predicates that need to be proven at usage sites, and can be assumed at definition. + /// + /// This query also computes the `~const` where clauses for associated types, which are + /// not "const", but which have item bounds which may be `~const`. These must hold for + /// the `~const` item bound to hold. query const_conditions( key: DefId ) -> ty::ConstConditions<'tcx> { @@ -757,6 +766,11 @@ rustc_queries! { separate_provide_extern } + /// Compute the const bounds that are implied for a conditionally-const item. + /// + /// This can be though of as the `~const` equivalent of `explicit_item_bounds`. These + /// are the predicates that need to proven at definition sites, and can be assumed at + /// usage sites. query explicit_implied_const_bounds( key: DefId ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> { @@ -2248,22 +2262,13 @@ rustc_queries! { desc { "normalizing `{}`", goal.value } } - query implied_outlives_bounds_compat( - goal: CanonicalImpliedOutlivesBoundsGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>, - NoSolution, - > { - desc { "computing implied outlives bounds for `{}`", goal.canonical.value.value.ty } - } - query implied_outlives_bounds( - goal: CanonicalImpliedOutlivesBoundsGoal<'tcx> + key: (CanonicalImpliedOutlivesBoundsGoal<'tcx>, bool) ) -> Result< &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>, NoSolution, > { - desc { "computing implied outlives bounds v2 for `{}`", goal.canonical.value.value.ty } + desc { "computing implied outlives bounds for `{}` (hack disabled = {:?})", key.0.canonical.value.value.ty, key.1 } } /// Do not call this query directly: diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 690b8128b1a..66a9e5fed4c 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -258,7 +258,7 @@ macro_rules! query_if_arena { }; } -/// If `separate_provide_if_extern`, then the key can be projected to its +/// If `separate_provide_extern`, then the key can be projected to its /// local key via `<$K as AsLocalKey>::LocalKey`. macro_rules! local_key_if_separate_extern { ([] $($K:tt)*) => { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index e5592de81cd..72f31cec008 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -19,7 +19,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd}; use rustc_index::{IndexVec, newtype_index}; -use rustc_macros::{HashStable, TypeVisitable}; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeVisitable}; use rustc_span::def_id::LocalDefId; use rustc_span::{ErrorGuaranteed, Span, Symbol}; use rustc_target::asm::InlineAsmRegOrRegClass; @@ -49,10 +49,13 @@ macro_rules! thir_with_elements { } )* + // Note: Making `Thir` implement `Clone` is useful for external tools that need access to + // THIR bodies even after the `Steal` query result has been stolen. + // One such tool is https://github.com/rust-corpus/qrates/. /// A container for a THIR body. /// /// This can be indexed directly by any THIR index (e.g. [`ExprId`]). - #[derive(Debug, HashStable)] + #[derive(Debug, HashStable, Clone)] pub struct Thir<'tcx> { pub body_type: BodyTy<'tcx>, $( @@ -90,7 +93,7 @@ thir_with_elements! { params: ParamId => Param<'tcx> => "p{}", } -#[derive(Debug, HashStable)] +#[derive(Debug, HashStable, Clone)] pub enum BodyTy<'tcx> { Const(Ty<'tcx>), Fn(FnSig<'tcx>), @@ -98,7 +101,7 @@ pub enum BodyTy<'tcx> { } /// Description of a type-checked function parameter. -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct Param<'tcx> { /// The pattern that appears in the parameter list, or None for implicit parameters. pub pat: Option<Box<Pat<'tcx>>>, @@ -118,7 +121,7 @@ pub enum LintLevel { Explicit(HirId), } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct Block { /// Whether the block itself has a label. Used by `label: {}` /// and `try` blocks. @@ -138,7 +141,7 @@ pub struct Block { type UserTy<'tcx> = Option<Box<CanonicalUserType<'tcx>>>; -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct AdtExpr<'tcx> { /// The ADT we're constructing. pub adt_def: AdtDef<'tcx>, @@ -155,7 +158,7 @@ pub struct AdtExpr<'tcx> { pub base: AdtExprBase<'tcx>, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub enum AdtExprBase<'tcx> { /// A struct expression where all the fields are explicitly enumerated: `Foo { a, b }`. None, @@ -168,7 +171,7 @@ pub enum AdtExprBase<'tcx> { DefaultFields(Box<[Ty<'tcx>]>), } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct ClosureExpr<'tcx> { pub closure_id: LocalDefId, pub args: UpvarArgs<'tcx>, @@ -177,7 +180,7 @@ pub struct ClosureExpr<'tcx> { pub fake_reads: Vec<(ExprId, FakeReadCause, HirId)>, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct InlineAsmExpr<'tcx> { pub asm_macro: AsmMacro, pub template: &'tcx [InlineAsmTemplatePiece], @@ -195,12 +198,12 @@ pub enum BlockSafety { ExplicitUnsafe(HirId), } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct Stmt<'tcx> { pub kind: StmtKind<'tcx>, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub enum StmtKind<'tcx> { /// An expression with a trailing semicolon. Expr { @@ -240,11 +243,11 @@ pub enum StmtKind<'tcx> { }, } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, HashStable)] +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] pub struct LocalVarId(pub HirId); /// A THIR expression. -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct Expr<'tcx> { /// kind of expression pub kind: ExprKind<'tcx>, @@ -271,7 +274,7 @@ pub struct TempLifetime { pub backwards_incompatible: Option<region::Scope>, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub enum ExprKind<'tcx> { /// `Scope`s are used to explicitly mark destruction scopes, /// and to track the `HirId` of the expressions within the scope. @@ -548,20 +551,20 @@ pub enum ExprKind<'tcx> { /// Represents the association of a field identifier and an expression. /// /// This is used in struct constructors. -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct FieldExpr { pub name: FieldIdx, pub expr: ExprId, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct FruInfo<'tcx> { pub base: ExprId, pub field_types: Box<[Ty<'tcx>]>, } /// A `match` arm. -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct Arm<'tcx> { pub pattern: Box<Pat<'tcx>>, pub guard: Option<ExprId>, @@ -579,7 +582,7 @@ pub enum LogicalOp { Or, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub enum InlineAsmOperand<'tcx> { In { reg: InlineAsmRegOrRegClass, @@ -616,13 +619,13 @@ pub enum InlineAsmOperand<'tcx> { }, } -#[derive(Debug, HashStable, TypeVisitable)] +#[derive(Clone, Debug, HashStable, TypeVisitable)] pub struct FieldPat<'tcx> { pub field: FieldIdx, pub pattern: Pat<'tcx>, } -#[derive(Debug, HashStable, TypeVisitable)] +#[derive(Clone, Debug, HashStable, TypeVisitable)] pub struct Pat<'tcx> { pub ty: Ty<'tcx>, pub span: Span, @@ -729,7 +732,7 @@ impl<'tcx> Pat<'tcx> { } } -#[derive(Debug, HashStable, TypeVisitable)] +#[derive(Clone, Debug, HashStable, TypeVisitable)] pub struct Ascription<'tcx> { pub annotation: CanonicalUserTypeAnnotation<'tcx>, /// Variance to use when relating the `user_ty` to the **type of the value being @@ -753,7 +756,7 @@ pub struct Ascription<'tcx> { pub variance: ty::Variance, } -#[derive(Debug, HashStable, TypeVisitable)] +#[derive(Clone, Debug, HashStable, TypeVisitable)] pub enum PatKind<'tcx> { /// A wildcard pattern: `_`. Wild, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index d033ecc75db..53f233f20eb 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -266,7 +266,7 @@ pub enum ObligationCauseCode<'tcx> { }, /// Constant expressions must be sized. - ConstSized, + SizedConstOrStatic, /// `static` items must have `Sync` type. SharedStatic, @@ -397,9 +397,9 @@ pub enum ObligationCauseCode<'tcx> { RustCall, - /// Obligations to prove that a `std::ops::Drop` impl is not stronger than + /// Obligations to prove that a `Drop` or negative auto trait impl is not stronger than /// the ADT it's being implemented for. - DropImpl, + AlwaysApplicableImpl, /// Requirement for a `const N: Ty` to implement `Ty: ConstParamTy` ConstParam(Ty<'tcx>), diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 6309dd2e490..ce4c08aa485 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -3,7 +3,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace}; use rustc_hir::def_id::DefId; use rustc_macros::{Decodable, Encodable, HashStable}; -use rustc_span::{Ident, Symbol}; +use rustc_span::{Ident, Symbol, sym}; use super::{TyCtxt, Visibility}; use crate::ty; @@ -108,6 +108,24 @@ impl AssocItem { pub fn is_impl_trait_in_trait(&self) -> bool { self.opt_rpitit_info.is_some() } + + /// Returns true if: + /// - This trait associated item has the `#[type_const]` attribute, + /// - If it is in a trait impl, the item from the original trait has this attribute, or + /// - It is an inherent assoc const. + pub fn is_type_const_capable(&self, tcx: TyCtxt<'_>) -> bool { + if self.kind != ty::AssocKind::Const { + return false; + } + + let def_id = match (self.container, self.trait_item_def_id) { + (AssocItemContainer::Trait, _) => self.def_id, + (AssocItemContainer::Impl, Some(trait_item_did)) => trait_item_did, + // Inherent impl but this attr is only applied to trait assoc items. + (AssocItemContainer::Impl, None) => return true, + }; + tcx.has_attr(def_id, sym::type_const) + } } #[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)] diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 41958949836..fe42a224d9f 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -224,7 +224,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for Ty<'tcx> { }) } else { let tcx = decoder.interner(); - tcx.mk_ty_from_kind(rustc_type_ir::TyKind::decode(decoder)) + tcx.mk_ty_from_kind(ty::TyKind::decode(decoder)) } } } diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index b72edc1c532..7c9280fae16 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -118,7 +118,7 @@ impl std::fmt::Debug for ConstInt { impl IntoDiagArg for ConstInt { // FIXME this simply uses the Debug impl, but we could probably do better by converting both // to an inherent method that returns `Cow`. - fn into_diag_arg(self) -> DiagArgValue { + fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue { DiagArgValue::Str(format!("{self:?}").into()) } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 62a384af12f..4013f7b2c85 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -324,11 +324,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.features() } - fn bound_coroutine_hidden_types( + fn coroutine_hidden_types( self, def_id: DefId, - ) -> impl IntoIterator<Item = ty::EarlyBinder<'tcx, ty::Binder<'tcx, Ty<'tcx>>>> { - self.bound_coroutine_hidden_types(def_id) + ) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>>> { + self.coroutine_hidden_types(def_id) } fn fn_sig(self, def_id: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> { @@ -594,6 +594,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.trait_is_auto(trait_def_id) } + fn trait_is_coinductive(self, trait_def_id: DefId) -> bool { + self.trait_is_coinductive(trait_def_id) + } + fn trait_is_alias(self, trait_def_id: DefId) -> bool { self.trait_is_alias(trait_def_id) } @@ -812,32 +816,38 @@ pub struct CtxtInterners<'tcx> { impl<'tcx> CtxtInterners<'tcx> { fn new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx> { + // Default interner size - this value has been chosen empirically, and may need to be adjusted + // as the compiler evolves. + const N: usize = 2048; CtxtInterners { arena, - type_: Default::default(), - const_lists: Default::default(), - args: Default::default(), - type_lists: Default::default(), - region: Default::default(), - poly_existential_predicates: Default::default(), - canonical_var_infos: Default::default(), - predicate: Default::default(), - clauses: Default::default(), - projs: Default::default(), - place_elems: Default::default(), - const_: Default::default(), - pat: Default::default(), - const_allocation: Default::default(), - bound_variable_kinds: Default::default(), - layout: Default::default(), - adt_def: Default::default(), - external_constraints: Default::default(), - predefined_opaques_in_body: Default::default(), - fields: Default::default(), - local_def_ids: Default::default(), - captures: Default::default(), - offset_of: Default::default(), - valtree: Default::default(), + // The factors have been chosen by @FractalFir based on observed interner sizes, and local perf runs. + // To get the interner sizes, insert `eprintln` printing the size of the interner in functions like `intern_ty`. + // Bigger benchmarks tend to give more accurate ratios, so use something like `x perf eprintln --includes cargo`. + type_: InternedSet::with_capacity(N * 16), + const_lists: InternedSet::with_capacity(N * 4), + args: InternedSet::with_capacity(N * 4), + type_lists: InternedSet::with_capacity(N * 4), + region: InternedSet::with_capacity(N * 4), + poly_existential_predicates: InternedSet::with_capacity(N / 4), + canonical_var_infos: InternedSet::with_capacity(N / 2), + predicate: InternedSet::with_capacity(N), + clauses: InternedSet::with_capacity(N), + projs: InternedSet::with_capacity(N * 4), + place_elems: InternedSet::with_capacity(N * 2), + const_: InternedSet::with_capacity(N * 2), + pat: InternedSet::with_capacity(N), + const_allocation: InternedSet::with_capacity(N), + bound_variable_kinds: InternedSet::with_capacity(N * 2), + layout: InternedSet::with_capacity(N), + adt_def: InternedSet::with_capacity(N), + external_constraints: InternedSet::with_capacity(N), + predefined_opaques_in_body: InternedSet::with_capacity(N), + fields: InternedSet::with_capacity(N * 4), + local_def_ids: InternedSet::with_capacity(N), + captures: InternedSet::with_capacity(N), + offset_of: InternedSet::with_capacity(N), + valtree: InternedSet::with_capacity(N), } } @@ -1317,6 +1327,11 @@ pub struct TyCtxt<'tcx> { gcx: &'tcx GlobalCtxt<'tcx>, } +// Explicitly implement `DynSync` and `DynSend` for `TyCtxt` to short circuit trait resolution. Its +// field are asserted to implement these traits below, so this is trivially safe, and it greatly +// speeds-up compilation of this crate and its dependents. +unsafe impl DynSend for TyCtxt<'_> {} +unsafe impl DynSync for TyCtxt<'_> {} fn _assert_tcx_fields() { sync::assert_dyn_sync::<&'_ GlobalCtxt<'_>>(); sync::assert_dyn_send::<&'_ GlobalCtxt<'_>>(); diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index cb218a27e62..881381a5ee6 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -19,8 +19,16 @@ use crate::ty::{ TypeSuperVisitable, TypeVisitable, TypeVisitor, }; +impl IntoDiagArg for Ty<'_> { + fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue { + ty::tls::with(|tcx| { + let ty = tcx.short_string(self, path); + rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(ty)) + }) + } +} + into_diag_arg_using_display! { - Ty<'_>, ty::Region<'_>, } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 8c1991ddb36..a0e67929c52 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -213,10 +213,9 @@ impl<'tcx> Ty<'tcx> { } impl<'tcx> TyCtxt<'tcx> { - pub fn string_with_limit<'a, T>(self, p: T, length_limit: usize) -> String + pub fn string_with_limit<T>(self, p: T, length_limit: usize) -> String where - T: Print<'tcx, FmtPrinter<'a, 'tcx>> + Lift<TyCtxt<'tcx>> + Copy, - <T as Lift<TyCtxt<'tcx>>>::Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>, + T: Copy + for<'a, 'b> Lift<TyCtxt<'b>, Lifted: Print<'b, FmtPrinter<'a, 'b>>>, { let mut type_limit = 50; let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| { @@ -253,10 +252,9 @@ impl<'tcx> TyCtxt<'tcx> { /// `tcx.short_string(ty, diag.long_ty_path())`. The diagnostic itself is the one that keeps /// the existence of a "long type" anywhere in the diagnostic, so the note telling the user /// where we wrote the file to is only printed once. - pub fn short_string<'a, T>(self, p: T, path: &mut Option<PathBuf>) -> String + pub fn short_string<T>(self, p: T, path: &mut Option<PathBuf>) -> String where - T: Print<'tcx, FmtPrinter<'a, 'tcx>> + Lift<TyCtxt<'tcx>> + Copy + Hash, - <T as Lift<TyCtxt<'tcx>>>::Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>, + T: Copy + Hash + for<'a, 'b> Lift<TyCtxt<'b>, Lifted: Print<'b, FmtPrinter<'a, 'b>>>, { let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| { self.lift(p).expect("could not lift for printing").print(cx) diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index ec0498b168c..0b8f0e8cd41 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -220,13 +220,9 @@ impl FlagComputation { &ty::Pat(ty, pat) => { self.add_ty(ty); match *pat { - ty::PatternKind::Range { start, end, include_end: _ } => { - if let Some(start) = start { - self.add_const(start) - } - if let Some(end) = end { - self.add_const(end) - } + ty::PatternKind::Range { start, end } => { + self.add_const(start); + self.add_const(end); } } } diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index ed0b3059d75..27576a2ec4a 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -159,8 +159,8 @@ unsafe impl<'tcx> Sync for GenericArg<'tcx> where } impl<'tcx> IntoDiagArg for GenericArg<'tcx> { - fn into_diag_arg(self) -> DiagArgValue { - self.to_string().into_diag_arg() + fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue { + self.to_string().into_diag_arg(&mut None) } } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index 505c7278176..953ad62be0a 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -236,6 +236,11 @@ impl<'tcx> InhabitedPredicate<'tcx> { self.instantiate_opt(tcx, args).unwrap_or(self) } + /// Same as [`Self::instantiate`], but if there is no generics to + /// instantiate, returns `None`. This is useful because it lets us avoid + /// allocating a recursive copy of everything when the result is unchanged. + /// + /// Only used to implement `instantiate` itself. fn instantiate_opt(self, tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> Option<Self> { match self { Self::ConstIsZero(c) => { @@ -260,7 +265,10 @@ impl<'tcx> InhabitedPredicate<'tcx> { Some(InhabitedPredicate::True) => Some(InhabitedPredicate::True), Some(a) => Some(a.or(tcx, b.instantiate_opt(tcx, args).unwrap_or(b))), }, - _ => None, + Self::True | Self::False | Self::NotInModule(_) => None, + Self::OpaqueType(_) => { + bug!("unexpected OpaqueType in InhabitedPredicate"); + } } } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index e9c19331e4a..98ca71b86be 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -111,8 +111,9 @@ pub enum InstanceKind<'tcx> { /// Dynamic dispatch to `<dyn Trait as Trait>::fn`. /// - /// This `InstanceKind` does not have callable MIR. Calls to `Virtual` instances must be - /// codegen'd as virtual calls through the vtable. + /// This `InstanceKind` may have a callable MIR as the default implementation. + /// Calls to `Virtual` instances must be codegen'd as virtual calls through the vtable. + /// *This means we might not know exactly what is being called.* /// /// If this is reified to a `fn` pointer, a `ReifyShim` is used (see `ReifyShim` above for more /// details on that). diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index eb14ed20fba..272bb0cc915 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -315,8 +315,8 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { } impl<'tcx> IntoDiagArg for LayoutError<'tcx> { - fn into_diag_arg(self) -> DiagArgValue { - self.to_string().into_diag_arg() + fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue { + self.to_string().into_diag_arg(&mut None) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index eb70a35d370..527509af05f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -122,6 +122,7 @@ pub mod normalize_erasing_regions; pub mod pattern; pub mod print; pub mod relate; +pub mod significant_drop_order; pub mod trait_def; pub mod util; pub mod visit; @@ -991,12 +992,6 @@ impl<'tcx> ParamEnv<'tcx> { ParamEnv { caller_bounds } } - /// Returns this same environment but with no caller bounds. - #[inline] - pub fn without_caller_bounds(self) -> Self { - Self::new(ListWithCachedTypeInfo::empty()) - } - /// Creates a pair of param-env and value for use in queries. pub fn and<T: TypeVisitable<TyCtxt<'tcx>>>(self, value: T) -> ParamEnvAnd<'tcx, T> { ParamEnvAnd { param_env: self, value } diff --git a/compiler/rustc_middle/src/ty/pattern.rs b/compiler/rustc_middle/src/ty/pattern.rs index e604aedd05e..4cad1ab2099 100644 --- a/compiler/rustc_middle/src/ty/pattern.rs +++ b/compiler/rustc_middle/src/ty/pattern.rs @@ -26,18 +26,30 @@ impl<'tcx> fmt::Debug for Pattern<'tcx> { impl<'tcx> fmt::Debug for PatternKind<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - PatternKind::Range { start, end, include_end } => { - if let Some(start) = start { - write!(f, "{start}")?; + PatternKind::Range { start, end } => { + write!(f, "{start}")?; + + if let Some(c) = end.try_to_value() { + let end = c.valtree.unwrap_leaf(); + let size = end.size(); + let max = match c.ty.kind() { + ty::Int(_) => { + Some(ty::ScalarInt::truncate_from_int(size.signed_int_max(), size)) + } + ty::Uint(_) => { + Some(ty::ScalarInt::truncate_from_uint(size.unsigned_int_max(), size)) + } + ty::Char => Some(ty::ScalarInt::truncate_from_uint(char::MAX, size)), + _ => None, + }; + if let Some((max, _)) = max + && end == max + { + return write!(f, ".."); + } } - write!(f, "..")?; - if include_end { - write!(f, "=")?; - } - if let Some(end) = end { - write!(f, "{end}")?; - } - Ok(()) + + write!(f, "..={end}") } } } @@ -46,5 +58,5 @@ impl<'tcx> fmt::Debug for PatternKind<'tcx> { #[derive(Clone, PartialEq, Eq, Hash)] #[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] pub enum PatternKind<'tcx> { - Range { start: Option<ty::Const<'tcx>>, end: Option<ty::Const<'tcx>>, include_end: bool }, + Range { start: ty::Const<'tcx>, end: ty::Const<'tcx> }, } diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 553de83dfcb..1674ca4cfc5 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -4,7 +4,6 @@ use rustc_data_structures::intern::Interned; use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, extension}; use rustc_type_ir as ir; -use tracing::instrument; use crate::ty::{ self, DebruijnIndex, EarlyBinder, PredicatePolarity, Ty, TyCtxt, TypeFlags, Upcast, UpcastFrom, @@ -51,10 +50,6 @@ impl<'tcx> rustc_type_ir::inherent::Predicate<TyCtxt<'tcx>> for Predicate<'tcx> self.as_clause() } - fn is_coinductive(self, interner: TyCtxt<'tcx>) -> bool { - self.is_coinductive(interner) - } - fn allow_normalization(self) -> bool { self.allow_normalization() } @@ -119,17 +114,6 @@ impl<'tcx> Predicate<'tcx> { Some(tcx.mk_predicate(kind)) } - #[instrument(level = "debug", skip(tcx), ret)] - pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool { - match self.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { - tcx.trait_is_coinductive(data.def_id()) - } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => true, - _ => false, - } - } - /// Whether this projection can be soundly normalized. /// /// Wf predicates must not be normalized, as normalization @@ -158,15 +142,21 @@ impl<'tcx> Predicate<'tcx> { } } -impl rustc_errors::IntoDiagArg for Predicate<'_> { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { - rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(self.to_string())) +impl<'tcx> rustc_errors::IntoDiagArg for Predicate<'tcx> { + fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue { + ty::tls::with(|tcx| { + let pred = tcx.short_string(self, path); + rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(pred)) + }) } } -impl rustc_errors::IntoDiagArg for Clause<'_> { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { - rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(self.to_string())) +impl<'tcx> rustc_errors::IntoDiagArg for Clause<'tcx> { + fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue { + ty::tls::with(|tcx| { + let clause = tcx.short_string(self, path); + rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(clause)) + }) } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ed0839f47e6..34d85534d0a 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -133,6 +133,20 @@ pub macro with_no_queries($e:expr) {{ )) }} +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum WrapBinderMode { + ForAll, + Unsafe, +} +impl WrapBinderMode { + pub fn start_str(self) -> &'static str { + match self { + WrapBinderMode::ForAll => "for<", + WrapBinderMode::Unsafe => "unsafe<", + } + } +} + /// The "region highlights" are used to control region printing during /// specific error messages. When a "region highlight" is enabled, it /// gives an alternate way to print specific regions. For now, we @@ -219,7 +233,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { self.print_def_path(def_id, args) } - fn in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError> + fn print_in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError> where T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>, { @@ -229,6 +243,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { fn wrap_binder<T, F: FnOnce(&T, &mut Self) -> Result<(), fmt::Error>>( &mut self, value: &ty::Binder<'tcx, T>, + _mode: WrapBinderMode, f: F, ) -> Result<(), PrintError> where @@ -703,8 +718,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } ty::FnPtr(ref sig_tys, hdr) => p!(print(sig_tys.with(hdr))), ty::UnsafeBinder(ref bound_ty) => { - // FIXME(unsafe_binders): Make this print `unsafe<>` rather than `for<>`. - self.wrap_binder(bound_ty, |ty, cx| cx.pretty_print_type(*ty))?; + self.wrap_binder(bound_ty, WrapBinderMode::Unsafe, |ty, cx| { + cx.pretty_print_type(*ty) + })?; } ty::Infer(infer_ty) => { if self.should_print_verbose() { @@ -1067,29 +1083,33 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { }; if let Some(return_ty) = entry.return_ty { - self.wrap_binder(&bound_args_and_self_ty, |(args, _), cx| { - define_scoped_cx!(cx); - p!(write("{}", tcx.item_name(trait_def_id))); - p!("("); - - for (idx, ty) in args.iter().enumerate() { - if idx > 0 { - p!(", "); + self.wrap_binder( + &bound_args_and_self_ty, + WrapBinderMode::ForAll, + |(args, _), cx| { + define_scoped_cx!(cx); + p!(write("{}", tcx.item_name(trait_def_id))); + p!("("); + + for (idx, ty) in args.iter().enumerate() { + if idx > 0 { + p!(", "); + } + p!(print(ty)); } - p!(print(ty)); - } - p!(")"); - if let Some(ty) = return_ty.skip_binder().as_type() { - if !ty.is_unit() { - p!(" -> ", print(return_ty)); + p!(")"); + if let Some(ty) = return_ty.skip_binder().as_type() { + if !ty.is_unit() { + p!(" -> ", print(return_ty)); + } } - } - p!(write("{}", if paren_needed { ")" } else { "" })); + p!(write("{}", if paren_needed { ")" } else { "" })); - first = false; - Ok(()) - })?; + first = false; + Ok(()) + }, + )?; } else { // Otherwise, render this like a regular trait. traits.insert( @@ -1110,7 +1130,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { for (trait_pred, assoc_items) in traits { write!(self, "{}", if first { "" } else { " + " })?; - self.wrap_binder(&trait_pred, |trait_pred, cx| { + self.wrap_binder(&trait_pred, WrapBinderMode::ForAll, |trait_pred, cx| { define_scoped_cx!(cx); if trait_pred.polarity == ty::PredicatePolarity::Negative { @@ -1302,7 +1322,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { let mut first = true; if let Some(bound_principal) = predicates.principal() { - self.wrap_binder(&bound_principal, |principal, cx| { + self.wrap_binder(&bound_principal, WrapBinderMode::ForAll, |principal, cx| { define_scoped_cx!(cx); p!(print_def_path(principal.def_id, &[])); @@ -1516,10 +1536,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { ty::ExprKind::Binop(op) => { let (_, _, c1, c2) = expr.binop_args(); - let precedence = |binop: crate::mir::BinOp| { - use rustc_ast::util::parser::AssocOp; - AssocOp::from_ast_binop(binop.to_hir_binop()).precedence() - }; + let precedence = |binop: crate::mir::BinOp| binop.to_hir_binop().precedence(); let op_precedence = precedence(op); let formatted_op = op.to_hir_binop().as_str(); let (lhs_parenthesized, rhs_parenthesized) = match (c1.kind(), c2.kind()) { @@ -1930,7 +1947,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { let kind = closure.kind_ty().to_opt_closure_kind().unwrap_or(ty::ClosureKind::Fn); write!(self, "impl ")?; - self.wrap_binder(&sig, |sig, cx| { + self.wrap_binder(&sig, WrapBinderMode::ForAll, |sig, cx| { define_scoped_cx!(cx); p!(write("{kind}(")); @@ -2370,22 +2387,23 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { Ok(()) } - fn in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError> + fn print_in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError> where T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>, { - self.pretty_in_binder(value) + self.pretty_print_in_binder(value) } fn wrap_binder<T, C: FnOnce(&T, &mut Self) -> Result<(), PrintError>>( &mut self, value: &ty::Binder<'tcx, T>, + mode: WrapBinderMode, f: C, ) -> Result<(), PrintError> where T: TypeFoldable<TyCtxt<'tcx>>, { - self.pretty_wrap_binder(value, f) + self.pretty_wrap_binder(value, mode, f) } fn typed_value( @@ -2635,6 +2653,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { pub fn name_all_regions<T>( &mut self, value: &ty::Binder<'tcx, T>, + mode: WrapBinderMode, ) -> Result<(T, UnordMap<ty::BoundRegion, ty::Region<'tcx>>), fmt::Error> where T: TypeFoldable<TyCtxt<'tcx>>, @@ -2708,9 +2727,13 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { // anyways. let (new_value, map) = if self.should_print_verbose() { for var in value.bound_vars().iter() { - start_or_continue(self, "for<", ", "); + start_or_continue(self, mode.start_str(), ", "); write!(self, "{var:?}")?; } + // Unconditionally render `unsafe<>`. + if value.bound_vars().is_empty() && mode == WrapBinderMode::Unsafe { + start_or_continue(self, mode.start_str(), ""); + } start_or_continue(self, "", "> "); (value.clone().skip_binder(), UnordMap::default()) } else { @@ -2775,8 +2798,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { } }; - if !trim_path { - start_or_continue(self, "for<", ", "); + // Unconditionally render `unsafe<>`. + if !trim_path || mode == WrapBinderMode::Unsafe { + start_or_continue(self, mode.start_str(), ", "); do_continue(self, name); } ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { var: br.var, kind }) @@ -2789,9 +2813,12 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { }; let new_value = value.clone().skip_binder().fold_with(&mut folder); let region_map = folder.region_map; - if !trim_path { - start_or_continue(self, "", "> "); + + if mode == WrapBinderMode::Unsafe && region_map.is_empty() { + start_or_continue(self, mode.start_str(), ""); } + start_or_continue(self, "", "> "); + (new_value, region_map) }; @@ -2800,12 +2827,15 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { Ok((new_value, map)) } - pub fn pretty_in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), fmt::Error> + pub fn pretty_print_in_binder<T>( + &mut self, + value: &ty::Binder<'tcx, T>, + ) -> Result<(), fmt::Error> where T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>, { let old_region_index = self.region_index; - let (new_value, _) = self.name_all_regions(value)?; + let (new_value, _) = self.name_all_regions(value, WrapBinderMode::ForAll)?; new_value.print(self)?; self.region_index = old_region_index; self.binder_depth -= 1; @@ -2815,13 +2845,14 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { pub fn pretty_wrap_binder<T, C: FnOnce(&T, &mut Self) -> Result<(), fmt::Error>>( &mut self, value: &ty::Binder<'tcx, T>, + mode: WrapBinderMode, f: C, ) -> Result<(), fmt::Error> where T: TypeFoldable<TyCtxt<'tcx>>, { let old_region_index = self.region_index; - let (new_value, _) = self.name_all_regions(value)?; + let (new_value, _) = self.name_all_regions(value, mode)?; f(&new_value, self)?; self.region_index = old_region_index; self.binder_depth -= 1; @@ -2880,7 +2911,7 @@ where T: Print<'tcx, P> + TypeFoldable<TyCtxt<'tcx>>, { fn print(&self, cx: &mut P) -> Result<(), PrintError> { - cx.in_binder(self) + cx.print_in_binder(self) } } @@ -2898,12 +2929,15 @@ where /// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only /// the trait path. That is, it will print `Trait<U>` instead of /// `<T as Trait<U>>`. -#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] +#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift, Hash)] pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>); impl<'tcx> rustc_errors::IntoDiagArg for TraitRefPrintOnlyTraitPath<'tcx> { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { - self.to_string().into_diag_arg() + fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue { + ty::tls::with(|tcx| { + let trait_ref = tcx.short_string(self, path); + rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(trait_ref)) + }) } } @@ -2915,12 +2949,15 @@ impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { /// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only /// the trait path, and additionally tries to "sugar" `Fn(...)` trait bounds. -#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] +#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift, Hash)] pub struct TraitRefPrintSugared<'tcx>(ty::TraitRef<'tcx>); impl<'tcx> rustc_errors::IntoDiagArg for TraitRefPrintSugared<'tcx> { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { - self.to_string().into_diag_arg() + fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue { + ty::tls::with(|tcx| { + let trait_ref = tcx.short_string(self, path); + rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(trait_ref)) + }) } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 839c1c346a4..b1dfcb80bde 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -51,22 +51,12 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Pattern<'tcx> { ) -> RelateResult<'tcx, Self> { match (&*a, &*b) { ( - &ty::PatternKind::Range { start: start_a, end: end_a, include_end: inc_a }, - &ty::PatternKind::Range { start: start_b, end: end_b, include_end: inc_b }, + &ty::PatternKind::Range { start: start_a, end: end_a }, + &ty::PatternKind::Range { start: start_b, end: end_b }, ) => { - // FIXME(pattern_types): make equal patterns equal (`0..=` is the same as `..=`). - let mut relate_opt_const = |a, b| match (a, b) { - (None, None) => Ok(None), - (Some(a), Some(b)) => relation.relate(a, b).map(Some), - // FIXME(pattern_types): report a better error - _ => Err(TypeError::Mismatch), - }; - let start = relate_opt_const(start_a, start_b)?; - let end = relate_opt_const(end_a, end_b)?; - if inc_a != inc_b { - todo!() - } - Ok(relation.cx().mk_pat(ty::PatternKind::Range { start, end, include_end: inc_a })) + let start = relation.relate(start_a, start_b)?; + let end = relation.relate(end_a, end_b)?; + Ok(relation.cx().mk_pat(ty::PatternKind::Range { start, end })) } } } diff --git a/compiler/rustc_middle/src/ty/significant_drop_order.rs b/compiler/rustc_middle/src/ty/significant_drop_order.rs new file mode 100644 index 00000000000..7f0d82d89fe --- /dev/null +++ b/compiler/rustc_middle/src/ty/significant_drop_order.rs @@ -0,0 +1,172 @@ +use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::unord::UnordSet; +use rustc_hir::def_id::DefId; +use rustc_span::Span; +use smallvec::{SmallVec, smallvec}; +use tracing::{debug, instrument}; + +use crate::ty::{self, Ty, TyCtxt}; + +/// An additional filter to exclude well-known types from the ecosystem +/// because their drops are trivial. +/// This returns additional types to check if the drops are delegated to those. +/// A typical example is `hashbrown::HashMap<K, V>`, whose drop is delegated to `K` and `V`. +fn true_significant_drop_ty<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, +) -> Option<SmallVec<[Ty<'tcx>; 2]>> { + if let ty::Adt(def, args) = ty.kind() { + let mut did = def.did(); + let mut name_rev = vec![]; + loop { + let key = tcx.def_key(did); + + match key.disambiguated_data.data { + rustc_hir::definitions::DefPathData::CrateRoot => { + name_rev.push(tcx.crate_name(did.krate)) + } + rustc_hir::definitions::DefPathData::TypeNs(symbol) => name_rev.push(symbol), + _ => return None, + } + if let Some(parent) = key.parent { + did = DefId { krate: did.krate, index: parent }; + } else { + break; + } + } + let name_str: Vec<_> = name_rev.iter().rev().map(|x| x.as_str()).collect(); + debug!(?name_str); + match name_str[..] { + // These are the types from Rust core ecosystem + ["syn" | "proc_macro2", ..] + | ["core" | "std", "task", "LocalWaker" | "Waker"] + | ["core" | "std", "task", "wake", "LocalWaker" | "Waker"] => Some(smallvec![]), + // These are important types from Rust ecosystem + ["tracing", "instrument", "Instrumented"] | ["bytes", "Bytes"] => Some(smallvec![]), + ["hashbrown", "raw", "RawTable" | "RawIntoIter"] => { + if let [ty, ..] = &***args + && let Some(ty) = ty.as_type() + { + Some(smallvec![ty]) + } else { + None + } + } + ["hashbrown", "raw", "RawDrain"] => { + if let [_, ty, ..] = &***args + && let Some(ty) = ty.as_type() + { + Some(smallvec![ty]) + } else { + None + } + } + _ => None, + } + } else { + None + } +} + +/// Returns the list of types with a "potentially sigificant" that may be dropped +/// by dropping a value of type `ty`. +#[instrument(level = "trace", skip(tcx, typing_env))] +pub fn extract_component_raw<'tcx>( + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, + ty_seen: &mut UnordSet<Ty<'tcx>>, +) -> SmallVec<[Ty<'tcx>; 4]> { + // Droppiness does not depend on regions, so let us erase them. + let ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty); + + let tys = tcx.list_significant_drop_tys(typing_env.as_query_input(ty)); + debug!(?ty, "components"); + let mut out_tys = smallvec![]; + for ty in tys { + if let Some(tys) = true_significant_drop_ty(tcx, ty) { + // Some types can be further opened up because the drop is simply delegated + for ty in tys { + if ty_seen.insert(ty) { + out_tys.extend(extract_component_raw(tcx, typing_env, ty, ty_seen)); + } + } + } else { + if ty_seen.insert(ty) { + out_tys.push(ty); + } + } + } + out_tys +} + +#[instrument(level = "trace", skip(tcx, typing_env))] +pub fn extract_component_with_significant_dtor<'tcx>( + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, +) -> SmallVec<[Ty<'tcx>; 4]> { + let mut tys = extract_component_raw(tcx, typing_env, ty, &mut Default::default()); + let mut deduplicate = FxHashSet::default(); + tys.retain(|oty| deduplicate.insert(*oty)); + tys.into_iter().collect() +} + +/// Extract the span of the custom destructor of a type +/// especially the span of the `impl Drop` header or its entire block +/// when we are working with current local crate. +#[instrument(level = "trace", skip(tcx))] +pub fn ty_dtor_span<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Span> { + match ty.kind() { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Error(_) + | ty::Str + | ty::Never + | ty::RawPtr(_, _) + | ty::Ref(_, _, _) + | ty::FnPtr(_, _) + | ty::Tuple(_) + | ty::Dynamic(_, _, _) + | ty::Alias(_, _) + | ty::Bound(_, _) + | ty::Pat(_, _) + | ty::Placeholder(_) + | ty::Infer(_) + | ty::Slice(_) + | ty::Array(_, _) + | ty::UnsafeBinder(_) => None, + + ty::Adt(adt_def, _) => { + let did = adt_def.did(); + let try_local_did_span = |did: DefId| { + if let Some(local) = did.as_local() { + tcx.source_span(local) + } else { + tcx.def_span(did) + } + }; + let dtor = if let Some(dtor) = tcx.adt_destructor(did) { + dtor.did + } else if let Some(dtor) = tcx.adt_async_destructor(did) { + dtor.future + } else { + return Some(try_local_did_span(did)); + }; + let def_key = tcx.def_key(dtor); + let Some(parent_index) = def_key.parent else { return Some(try_local_did_span(dtor)) }; + let parent_did = DefId { index: parent_index, krate: dtor.krate }; + Some(try_local_did_span(parent_did)) + } + ty::Coroutine(did, _) + | ty::CoroutineWitness(did, _) + | ty::CoroutineClosure(did, _) + | ty::Closure(did, _) + | ty::FnDef(did, _) + | ty::Foreign(did) => Some(tcx.def_span(did)), + ty::Param(_) => None, + } +} diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index db9e9fbc643..6c62c04f42e 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -284,6 +284,7 @@ TrivialTypeTraversalImpls! { rustc_hir::def_id::LocalDefId, rustc_hir::HirId, rustc_hir::MatchSource, + rustc_hir::RangeEnd, rustc_span::Ident, rustc_span::Span, rustc_span::Symbol, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index d5617adf26b..ce563c59251 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -342,6 +342,7 @@ impl ParamConst { ParamConst::new(def.index, def.name) } + #[instrument(level = "debug")] pub fn find_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> { let mut candidates = env.caller_bounds().iter().filter_map(|clause| { // `ConstArgHasType` are never desugared to be higher ranked. @@ -461,7 +462,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_param(tcx: TyCtxt<'tcx>, index: u32, name: Symbol) -> Ty<'tcx> { - tcx.mk_ty_from_kind(Param(ParamTy { index, name })) + Ty::new(tcx, Param(ParamTy { index, name })) } #[inline] diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index d4484a16fea..7d9c23c05f9 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -394,8 +394,10 @@ impl<'tcx> TypeckResults<'tcx> { matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _)))) } - pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> { - self.pat_binding_modes().get(id).copied().or_else(|| { + /// Returns the computed binding mode for a `PatKind::Binding` pattern + /// (after match ergonomics adjustments). + pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> BindingMode { + self.pat_binding_modes().get(id).copied().unwrap_or_else(|| { s.dcx().span_bug(sp, "missing binding mode"); }) } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 4d917963cd6..237aa66f486 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -740,51 +740,37 @@ impl<'tcx> TyCtxt<'tcx> { } /// Return the set of types that should be taken into account when checking - /// trait bounds on a coroutine's internal state. - // FIXME(compiler-errors): We should remove this when the old solver goes away; - // and all other usages of this function should go through `bound_coroutine_hidden_types` - // instead. - pub fn coroutine_hidden_types( - self, - def_id: DefId, - ) -> impl Iterator<Item = ty::EarlyBinder<'tcx, Ty<'tcx>>> { - let coroutine_layout = self.mir_coroutine_witnesses(def_id); - coroutine_layout - .as_ref() - .map_or_else(|| [].iter(), |l| l.field_tys.iter()) - .filter(|decl| !decl.ignore_for_traits) - .map(|decl| ty::EarlyBinder::bind(decl.ty)) - } - - /// Return the set of types that should be taken into account when checking /// trait bounds on a coroutine's internal state. This properly replaces /// `ReErased` with new existential bound lifetimes. - pub fn bound_coroutine_hidden_types( + pub fn coroutine_hidden_types( self, def_id: DefId, - ) -> impl Iterator<Item = ty::EarlyBinder<'tcx, ty::Binder<'tcx, Ty<'tcx>>>> { + ) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>>> { let coroutine_layout = self.mir_coroutine_witnesses(def_id); - coroutine_layout - .as_ref() - .map_or_else(|| [].iter(), |l| l.field_tys.iter()) - .filter(|decl| !decl.ignore_for_traits) - .map(move |decl| { - let mut vars = vec![]; - let ty = fold_regions(self, decl.ty, |re, debruijn| { - assert_eq!(re, self.lifetimes.re_erased); - let var = ty::BoundVar::from_usize(vars.len()); - vars.push(ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon)); - ty::Region::new_bound( - self, - debruijn, - ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon }, - ) - }); - ty::EarlyBinder::bind(ty::Binder::bind_with_vars( - ty, - self.mk_bound_variable_kinds(&vars), - )) - }) + let mut vars = vec![]; + let bound_tys = self.mk_type_list_from_iter( + coroutine_layout + .as_ref() + .map_or_else(|| [].iter(), |l| l.field_tys.iter()) + .filter(|decl| !decl.ignore_for_traits) + .map(|decl| { + let ty = fold_regions(self, decl.ty, |re, debruijn| { + assert_eq!(re, self.lifetimes.re_erased); + let var = ty::BoundVar::from_usize(vars.len()); + vars.push(ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon)); + ty::Region::new_bound( + self, + debruijn, + ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon }, + ) + }); + ty + }), + ); + ty::EarlyBinder::bind(ty::Binder::bind_with_vars( + bound_tys, + self.mk_bound_variable_kinds(&vars), + )) } /// Expands the given impl trait type, stopping if the type is recursive. diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 3e8a3d1a289..a23316ae6fc 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -137,9 +137,9 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) ty::Pat(ty, pat) => { match *pat { - ty::PatternKind::Range { start, end, include_end: _ } => { - stack.extend(end.map(Into::into)); - stack.extend(start.map(Into::into)); + ty::PatternKind::Range { start, end } => { + stack.push(end.into()); + stack.push(start.into()); } } stack.push(ty.into()); |
