diff options
Diffstat (limited to 'compiler/rustc_middle/src')
81 files changed, 3635 insertions, 3234 deletions
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 6c404fbb7c6..5a320865c95 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -27,6 +27,11 @@ macro_rules! arena_types { rustc_middle::mir::Promoted, rustc_middle::mir::Body<'tcx> >, + [decode] closure_debuginfo: + rustc_index::IndexVec< + rustc_target::abi::FieldIdx, + rustc_span::symbol::Symbol, + >, [decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>, [decode] borrowck_result: rustc_middle::mir::BorrowCheckResult<'tcx>, @@ -78,9 +83,9 @@ macro_rules! arena_types { rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::FnSig<'tcx>> >, - [] type_op_normalize_predicate: + [] type_op_normalize_clause: rustc_middle::infer::canonical::Canonical<'tcx, - rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Predicate<'tcx>> + rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Clause<'tcx>> >, [] type_op_normalize_ty: rustc_middle::infer::canonical::Canonical<'tcx, diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 5f2eb890c4e..1fd68dc5cb2 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -195,13 +195,7 @@ impl<'hir> Map<'hir> { ItemKind::Fn(..) => DefKind::Fn, ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind), ItemKind::Mod(..) => DefKind::Mod, - ItemKind::OpaqueTy(ref opaque) => { - if opaque.in_trait && !self.tcx.lower_impl_trait_in_trait_to_assoc_ty() { - DefKind::ImplTraitPlaceholder - } else { - DefKind::OpaqueTy - } - } + ItemKind::OpaqueTy(..) => DefKind::OpaqueTy, ItemKind::TyAlias(..) => DefKind::TyAlias, ItemKind::Enum(..) => DefKind::Enum, ItemKind::Struct(..) => DefKind::Struct, @@ -1109,6 +1103,33 @@ impl<'hir> Map<'hir> { _ => None, } } + + pub fn maybe_get_struct_pattern_shorthand_field(&self, expr: &Expr<'_>) -> Option<Symbol> { + let local = match expr { + Expr { + kind: + ExprKind::Path(QPath::Resolved( + None, + Path { + res: def::Res::Local(_), segments: [PathSegment { ident, .. }], .. + }, + )), + .. + } => Some(ident), + _ => None, + }?; + + match self.find_parent(expr.hir_id)? { + Node::ExprField(field) => { + if field.ident.name == local.name && field.is_shorthand { + return Some(local.name); + } + } + _ => {} + } + + None + } } impl<'hir> intravisit::Map<'hir> for Map<'hir> { diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 29dae67bfca..81823118ab8 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -23,7 +23,7 @@ use crate::infer::MemberConstraint; use crate::mir::ConstraintCategory; -use crate::ty::subst::GenericArg; +use crate::ty::GenericArg; use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt}; use rustc_macros::HashStable; use smallvec::SmallVec; @@ -63,7 +63,7 @@ impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct CanonicalVarValues<'tcx> { - pub var_values: ty::SubstsRef<'tcx>, + pub var_values: ty::GenericArgsRef<'tcx>, } impl CanonicalVarValues<'_> { @@ -82,15 +82,40 @@ impl CanonicalVarValues<'_> { } pub fn is_identity_modulo_regions(&self) -> bool { - self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() { - ty::GenericArgKind::Lifetime(_) => true, - ty::GenericArgKind::Type(ty) => { - matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv) - } - ty::GenericArgKind::Const(ct) => { - matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv) + let mut var = ty::BoundVar::from_u32(0); + for arg in self.var_values { + match arg.unpack() { + ty::GenericArgKind::Lifetime(r) => { + if let ty::ReLateBound(ty::INNERMOST, br) = *r + && var == br.var + { + var = var + 1; + } else { + // It's ok if this region var isn't unique + } + }, + ty::GenericArgKind::Type(ty) => { + if let ty::Bound(ty::INNERMOST, bt) = *ty.kind() + && var == bt.var + { + var = var + 1; + } else { + return false; + } + } + ty::GenericArgKind::Const(ct) => { + if let ty::ConstKind::Bound(ty::INNERMOST, bc) = ct.kind() + && var == bc + { + var = var + 1; + } else { + return false; + } + } } - }) + } + + true } } @@ -404,11 +429,12 @@ impl<'tcx> CanonicalVarValues<'tcx> { infos: CanonicalVarInfos<'tcx>, ) -> CanonicalVarValues<'tcx> { CanonicalVarValues { - var_values: tcx.mk_substs_from_iter(infos.iter().enumerate().map( + var_values: tcx.mk_args_from_iter(infos.iter().enumerate().map( |(i, info)| -> ty::GenericArg<'tcx> { match info.kind { CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => { - tcx.mk_bound(ty::INNERMOST, ty::BoundVar::from_usize(i).into()).into() + Ty::new_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i).into()) + .into() } CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => { let br = ty::BoundRegion { @@ -418,12 +444,13 @@ impl<'tcx> CanonicalVarValues<'tcx> { ty::Region::new_late_bound(tcx, ty::INNERMOST, br).into() } CanonicalVarKind::Const(_, ty) - | CanonicalVarKind::PlaceholderConst(_, ty) => tcx - .mk_const( - ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i)), - ty, - ) - .into(), + | CanonicalVarKind::PlaceholderConst(_, ty) => ty::Const::new_bound( + tcx, + ty::INNERMOST, + ty::BoundVar::from_usize(i), + ty, + ) + .into(), } }, )), diff --git a/compiler/rustc_middle/src/infer/mod.rs b/compiler/rustc_middle/src/infer/mod.rs index 2db59f37f40..493bb8a6823 100644 --- a/compiler/rustc_middle/src/infer/mod.rs +++ b/compiler/rustc_middle/src/infer/mod.rs @@ -15,7 +15,7 @@ use rustc_span::Span; #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct MemberConstraint<'tcx> { - /// The `DefId` and substs of the opaque type causing this constraint. + /// The `DefId` and args of the opaque type causing this constraint. /// Used for error reporting. pub key: OpaqueTypeKey<'tcx>, diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 991b9f01985..85fb9214d9d 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -90,15 +90,15 @@ impl<'tcx> UnifyValue for UnifiedRegion<'tcx> { impl ToType for ty::IntVarValue { fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match *self { - ty::IntType(i) => tcx.mk_mach_int(i), - ty::UintType(i) => tcx.mk_mach_uint(i), + ty::IntType(i) => Ty::new_int(tcx, i), + ty::UintType(i) => Ty::new_uint(tcx, i), } } } impl ToType for ty::FloatVarValue { fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - tcx.mk_mach_float(self.0) + Ty::new_float(tcx, self.0) } } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index caf3fc26039..6ce1ad8f43e 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -169,26 +169,6 @@ impl TyCtxt<'_> { pub fn lint_level_at_node(self, lint: &'static Lint, id: HirId) -> (Level, LintLevelSource) { self.shallow_lint_levels_on(id.owner).lint_level_id_at_node(self, LintId::of(lint), id) } - - /// Walks upwards from `id` to find a node which might change lint levels with attributes. - /// It stops at `bound` and just returns it if reached. - pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId { - let hir = self.hir(); - loop { - if id == bound { - return bound; - } - - if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) { - return id; - } - let next = hir.parent_id(id); - if next == id { - bug!("lint traversal reached the root of the crate"); - } - id = next; - } - } } /// This struct represents a lint expectation and holds all required information @@ -298,6 +278,7 @@ pub fn explain_lint_level_source( /// // ^^^^^^^^^^^^^^^^^^^^^ returns `&mut DiagnosticBuilder` by default /// ) /// ``` +#[track_caller] pub fn struct_lint_level( sess: &Session, lint: &'static Lint, @@ -311,6 +292,7 @@ pub fn struct_lint_level( ) { // Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to // the "real" work. + #[track_caller] fn struct_lint_level_impl( sess: &Session, lint: &'static Lint, @@ -388,10 +370,11 @@ pub fn struct_lint_level( // it'll become a hard error, so we have to emit *something*. Also, // if this lint occurs in the expansion of a macro from an external crate, // allow individual lints to opt-out from being reported. - let not_future_incompatible = - future_incompatible.map(|f| f.reason.edition().is_some()).unwrap_or(true); - if not_future_incompatible && !lint.report_in_external_macro { + let incompatible = future_incompatible.is_some_and(|f| f.reason.edition().is_none()); + + if !incompatible && !lint.report_in_external_macro { err.cancel(); + // Don't continue further, since we don't want to have // `diag_span_note_once` called for a diagnostic that isn't emitted. return; diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index c4601a1fb41..02fd6ed7ba6 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -100,6 +100,8 @@ bitflags! { const REALLOCATOR = 1 << 18; /// `#[rustc_allocator_zeroed]`: a hint to LLVM that the function only allocates zeroed memory. const ALLOCATOR_ZEROED = 1 << 19; + /// `#[no_builtins]`: indicates that disable implicit builtin knowledge of functions for the function. + const NO_BUILTINS = 1 << 20; } } diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs index 9041da9a060..f19812619b2 100644 --- a/compiler/rustc_middle/src/middle/exported_symbols.rs +++ b/compiler/rustc_middle/src/middle/exported_symbols.rs @@ -1,4 +1,4 @@ -use crate::ty::subst::SubstsRef; +use crate::ty::GenericArgsRef; use crate::ty::{self, Ty, TyCtxt}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_macros::HashStable; @@ -41,7 +41,7 @@ pub struct SymbolExportInfo { #[derive(Eq, PartialEq, Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)] pub enum ExportedSymbol<'tcx> { NonGeneric(DefId), - Generic(DefId, SubstsRef<'tcx>), + Generic(DefId, GenericArgsRef<'tcx>), DropGlue(Ty<'tcx>), ThreadLocalShim(DefId), NoDefId(ty::SymbolName<'tcx>), @@ -53,15 +53,15 @@ impl<'tcx> ExportedSymbol<'tcx> { pub fn symbol_name_for_local_instance(&self, tcx: TyCtxt<'tcx>) -> ty::SymbolName<'tcx> { match *self { ExportedSymbol::NonGeneric(def_id) => tcx.symbol_name(ty::Instance::mono(tcx, def_id)), - ExportedSymbol::Generic(def_id, substs) => { - tcx.symbol_name(ty::Instance::new(def_id, substs)) + ExportedSymbol::Generic(def_id, args) => { + tcx.symbol_name(ty::Instance::new(def_id, args)) } ExportedSymbol::DropGlue(ty) => { tcx.symbol_name(ty::Instance::resolve_drop_in_place(tcx, ty)) } ExportedSymbol::ThreadLocalShim(def_id) => tcx.symbol_name(ty::Instance { def: ty::InstanceDef::ThreadLocalShim(def_id), - substs: ty::InternalSubsts::empty(), + args: ty::GenericArgs::empty(), }), ExportedSymbol::NoDefId(symbol_name) => symbol_name, } diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index f45cf788dd9..5baeb1ee0cf 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -4,6 +4,7 @@ use crate::ty::{TyCtxt, Visibility}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_hir::def::DefKind; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; use rustc_span::def_id::{LocalDefId, CRATE_DEF_ID}; @@ -148,13 +149,12 @@ impl EffectiveVisibilities { }; } - pub fn check_invariants(&self, tcx: TyCtxt<'_>, early: bool) { + pub fn check_invariants(&self, tcx: TyCtxt<'_>) { if !cfg!(debug_assertions) { return; } for (&def_id, ev) in &self.map { // More direct visibility levels can never go farther than less direct ones, - // neither of effective visibilities can go farther than nominal visibility, // and all effective visibilities are larger or equal than private visibility. let private_vis = Visibility::Restricted(tcx.parent_module_from_def_id(def_id)); let span = tcx.def_span(def_id.to_def_id()); @@ -175,17 +175,20 @@ impl EffectiveVisibilities { ev.reachable_through_impl_trait ); } - let nominal_vis = tcx.visibility(def_id); - // FIXME: `rustc_privacy` is not yet updated for the new logic and can set - // effective visibilities that are larger than the nominal one. - if !nominal_vis.is_at_least(ev.reachable_through_impl_trait, tcx) && early { - span_bug!( - span, - "{:?}: reachable_through_impl_trait {:?} > nominal {:?}", - def_id, - ev.reachable_through_impl_trait, - nominal_vis - ); + // All effective visibilities except `reachable_through_impl_trait` are limited to + // nominal visibility. For some items nominal visibility doesn't make sense so we + // don't check this condition for them. + if !matches!(tcx.def_kind(def_id), DefKind::Impl { .. }) { + let nominal_vis = tcx.visibility(def_id); + if !nominal_vis.is_at_least(ev.reachable, tcx) { + span_bug!( + span, + "{:?}: reachable {:?} > nominal {:?}", + def_id, + ev.reachable, + nominal_vis + ); + } } } } @@ -212,7 +215,7 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> { pub fn update( &mut self, id: Id, - nominal_vis: Option<Visibility>, + max_vis: Option<Visibility>, lazy_private_vis: impl FnOnce() -> Visibility, inherited_effective_vis: EffectiveVisibility, level: Level, @@ -236,8 +239,8 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> { if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level && level != l) { - calculated_effective_vis = if let Some(nominal_vis) = nominal_vis && !nominal_vis.is_at_least(inherited_effective_vis_at_level, tcx) { - nominal_vis + calculated_effective_vis = if let Some(max_vis) = max_vis && !max_vis.is_at_least(inherited_effective_vis_at_level, tcx) { + max_vis } else { inherited_effective_vis_at_level } diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 10712e14686..c50c5e6f701 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -10,7 +10,7 @@ use crate::ty::TyCtxt; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir as hir; -use rustc_hir::Node; +use rustc_hir::{HirIdMap, Node}; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; use rustc_span::{Span, DUMMY_SP}; @@ -228,7 +228,7 @@ pub struct ScopeTree { /// and not the enclosing *statement*. Expressions that are not present in this /// table are not rvalue candidates. The set of rvalue candidates is computed /// during type check based on a traversal of the AST. - pub rvalue_candidates: FxHashMap<hir::HirId, RvalueCandidateType>, + pub rvalue_candidates: HirIdMap<RvalueCandidateType>, /// If there are any `yield` nested within a scope, this map /// stores the `Span` of the last one and its index in the diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index 9d70dbfa072..7722e7b47cf 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -26,7 +26,7 @@ struct Cache { predecessors: OnceCell<Predecessors>, switch_sources: OnceCell<SwitchSources>, is_cyclic: OnceCell<bool>, - postorder: OnceCell<Vec<BasicBlock>>, + reverse_postorder: OnceCell<Vec<BasicBlock>>, dominators: OnceCell<Dominators<BasicBlock>>, } @@ -62,11 +62,14 @@ impl<'tcx> BasicBlocks<'tcx> { }) } - /// Returns basic blocks in a postorder. + /// Returns basic blocks in a reverse postorder. #[inline] - pub fn postorder(&self) -> &[BasicBlock] { - self.cache.postorder.get_or_init(|| { - Postorder::new(&self.basic_blocks, START_BLOCK).map(|(bb, _)| bb).collect() + pub fn reverse_postorder(&self) -> &[BasicBlock] { + self.cache.reverse_postorder.get_or_init(|| { + let mut rpo: Vec<_> = + Postorder::new(&self.basic_blocks, START_BLOCK).map(|(bb, _)| bb).collect(); + rpo.reverse(); + rpo }) } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 2435bc59ec0..1bcef17d73b 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -22,7 +22,7 @@ pub enum ErrorHandled { /// *guaranteed* to fail. Warnings/lints *must not* produce `Reported`. Reported(ReportedErrorInfo), /// Don't emit an error, the evaluation failed because the MIR was generic - /// and the substs didn't fully monomorphize it. + /// and the args didn't fully monomorphize it. TooGeneric, } @@ -388,7 +388,6 @@ pub enum ValidationErrorKind<'tcx> { MutableRefInConst, NullFnPtr, NeverVal, - NullablePtrOutOfRange { range: WrappingRange, max_value: u128 }, PtrOutOfRange { range: WrappingRange, max_value: u128 }, OutOfRange { value: String, range: WrappingRange, max_value: u128 }, UnsafeCell, diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 2d2cfee1b21..69c15e9cc06 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -138,7 +138,7 @@ use rustc_target::abi::{AddressSpace, Endian, HasDataLayout}; use crate::mir; use crate::ty::codec::{TyDecoder, TyEncoder}; -use crate::ty::subst::GenericArgKind; +use crate::ty::GenericArgKind; use crate::ty::{self, Instance, Ty, TyCtxt}; pub use self::error::{ @@ -274,7 +274,7 @@ pub struct AllocDecodingState { // For each `AllocId`, we keep track of which decoding state it's currently in. decoding_state: Vec<Lock<State>>, // The offsets of each allocation in the data stream. - data_offsets: Vec<u32>, + data_offsets: Vec<u64>, } impl AllocDecodingState { @@ -289,7 +289,7 @@ impl AllocDecodingState { AllocDecodingSession { state: self, session_id } } - pub fn new(data_offsets: Vec<u32>) -> Self { + pub fn new(data_offsets: Vec<u64>) -> Self { let decoding_state = std::iter::repeat_with(|| Lock::new(State::Empty)).take(data_offsets.len()).collect(); @@ -559,7 +559,7 @@ impl<'tcx> TyCtxt<'tcx> { // However, formatting code relies on function identity (see #58320), so we only do // this for generic functions. Lifetime parameters are ignored. let is_generic = instance - .substs + .args .into_iter() .any(|kind| !matches!(kind.unpack(), GenericArgKind::Lifetime(_))); if is_generic { diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 65d04919357..c8133bcc387 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -19,33 +19,19 @@ pub trait PointerArithmetic: HasDataLayout { #[inline(always)] fn max_size_of_val(&self) -> Size { - Size::from_bytes(self.target_isize_max()) - } - - #[inline] - fn target_usize_max(&self) -> u64 { - self.pointer_size().unsigned_int_max().try_into().unwrap() - } - - #[inline] - fn target_isize_min(&self) -> i64 { - self.pointer_size().signed_int_min().try_into().unwrap() - } - - #[inline] - fn target_isize_max(&self) -> i64 { - self.pointer_size().signed_int_max().try_into().unwrap() + Size::from_bytes(self.data_layout().target_isize_max()) } #[inline] fn target_usize_to_isize(&self, val: u64) -> i64 { + let dl = self.data_layout(); let val = val as i64; // Now wrap-around into the machine_isize range. - if val > self.target_isize_max() { + if val > dl.target_isize_max() { // This can only happen if the ptr size is < 64, so we know max_usize_plus_1 fits into // i64. - debug_assert!(self.pointer_size().bits() < 64); - let max_usize_plus_1 = 1u128 << self.pointer_size().bits(); + debug_assert!(dl.pointer_size.bits() < 64); + let max_usize_plus_1 = 1u128 << dl.pointer_size.bits(); val - i64::try_from(max_usize_plus_1).unwrap() } else { val @@ -58,7 +44,7 @@ pub trait PointerArithmetic: HasDataLayout { #[inline] fn truncate_to_ptr(&self, (val, over): (u64, bool)) -> (u64, bool) { let val = u128::from(val); - let max_ptr_plus_1 = 1u128 << self.pointer_size().bits(); + let max_ptr_plus_1 = 1u128 << self.data_layout().pointer_size.bits(); (u64::try_from(val % max_ptr_plus_1).unwrap(), over || val >= max_ptr_plus_1) } @@ -76,11 +62,11 @@ pub trait PointerArithmetic: HasDataLayout { let n = i.unsigned_abs(); if i >= 0 { let (val, over) = self.overflowing_offset(val, n); - (val, over || i > self.target_isize_max()) + (val, over || i > self.data_layout().target_isize_max()) } else { let res = val.overflowing_sub(n); let (val, over) = self.truncate_to_ptr(res); - (val, over || i < self.target_isize_min()) + (val, over || i < self.data_layout().target_isize_min()) } } diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index ae32a54be3d..c9db0e7c11d 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -2,8 +2,8 @@ use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId} use crate::mir; use crate::query::{TyCtxtAt, TyCtxtEnsure}; -use crate::ty::subst::InternalSubsts; use crate::ty::visit::TypeVisitableExt; +use crate::ty::GenericArgs; use crate::ty::{self, TyCtxt}; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; @@ -20,8 +20,8 @@ impl<'tcx> TyCtxt<'tcx> { // to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions // into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are // encountered. - let substs = InternalSubsts::identity_for_item(self, def_id); - let instance = ty::Instance::new(def_id, substs); + let args = GenericArgs::identity_for_item(self, def_id); + let instance = ty::Instance::new(def_id, args); let cid = GlobalId { instance, promoted: None }; let param_env = self.param_env(def_id).with_reveal_all_normalized(self); self.const_eval_global_id(param_env, cid, None) @@ -48,14 +48,14 @@ impl<'tcx> TyCtxt<'tcx> { // // When trying to evaluate constants containing inference variables, // use `Infcx::const_eval_resolve` instead. - if ct.substs.has_non_region_infer() { + if ct.args.has_non_region_infer() { bug!("did not expect inference variables here"); } match ty::Instance::resolve( self, param_env, // FIXME: maybe have a separate version for resolving mir::UnevaluatedConst? - ct.def, ct.substs, + ct.def, ct.args, ) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: ct.promoted }; @@ -79,11 +79,11 @@ impl<'tcx> TyCtxt<'tcx> { // // When trying to evaluate constants containing inference variables, // use `Infcx::const_eval_resolve` instead. - if ct.substs.has_non_region_infer() { + if ct.args.has_non_region_infer() { bug!("did not expect inference variables here"); } - match ty::Instance::resolve(self, param_env, ct.def, ct.substs) { + match ty::Instance::resolve(self, param_env, ct.def, ct.args) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: None }; self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| { @@ -94,12 +94,16 @@ impl<'tcx> TyCtxt<'tcx> { // @lcnr believes that successfully evaluating even though there are // used generic parameters is a bug of evaluation, so checking for it // here does feel somewhat sensible. - if !self.features().generic_const_exprs && ct.substs.has_non_region_param() { - assert!(matches!( - self.def_kind(ct.def), - DefKind::InlineConst | DefKind::AnonConst - )); - let mir_body = self.mir_for_ctfe(ct.def); + if !self.features().generic_const_exprs && ct.args.has_non_region_param() { + let def_kind = self.def_kind(instance.def_id()); + assert!( + matches!( + def_kind, + DefKind::InlineConst | DefKind::AnonConst | DefKind::AssocConst + ), + "{cid:?} is {def_kind:?}", + ); + let mir_body = self.mir_for_ctfe(instance.def_id()); if mir_body.is_polymorphic { let Some(local_def_id) = ct.def.as_local() else { return }; self.struct_span_lint_hir( @@ -217,8 +221,8 @@ impl<'tcx> TyCtxtEnsure<'tcx> { // to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions // into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are // encountered. - let substs = InternalSubsts::identity_for_item(self.tcx, def_id); - let instance = ty::Instance::new(def_id, substs); + let args = GenericArgs::identity_for_item(self.tcx, def_id); + let instance = ty::Instance::new(def_id, args); let cid = GlobalId { instance, promoted: None }; let param_env = self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx).with_const(); @@ -239,15 +243,3 @@ impl<'tcx> TyCtxtEnsure<'tcx> { self.eval_to_allocation_raw(param_env.and(gid)) } } - -impl<'tcx> TyCtxt<'tcx> { - /// Destructure a mir constant ADT or array into its variant index and its field values. - /// Panics if the destructuring fails, use `try_destructure_mir_constant` for fallible version. - pub fn destructure_mir_constant( - self, - param_env: ty::ParamEnv<'tcx>, - constant: mir::ConstantKind<'tcx>, - ) -> mir::DestructuredConstant<'tcx> { - self.try_destructure_mir_constant(param_env.and(constant)).unwrap() - } -} diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index e929240bf30..97f53a59fd6 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -12,7 +12,7 @@ use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::visit::TypeVisitableExt; use crate::ty::{self, List, Ty, TyCtxt}; use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex}; -use crate::ty::{GenericArg, InternalSubsts, SubstsRef}; +use crate::ty::{GenericArg, GenericArgs, GenericArgsRef}; use rustc_data_structures::captures::Captures; use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg}; @@ -145,7 +145,7 @@ impl MirPhase { } "analysis" => Self::Analysis(AnalysisPhase::parse(phase)), "runtime" => Self::Runtime(RuntimePhase::parse(phase)), - _ => panic!("Unknown MIR dialect {}", dialect), + _ => bug!("Unknown MIR dialect: '{}'", dialect), } } } @@ -159,7 +159,7 @@ impl AnalysisPhase { match &*phase.to_ascii_lowercase() { "initial" => Self::Initial, "post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup, - _ => panic!("Unknown analysis phase {}", phase), + _ => bug!("Unknown analysis phase: '{}'", phase), } } } @@ -174,7 +174,7 @@ impl RuntimePhase { "initial" => Self::Initial, "post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup, "optimized" => Self::Optimized, - _ => panic!("Unknown runtime phase {}", phase), + _ => bug!("Unknown runtime phase: '{}'", phase), } } } @@ -1905,15 +1905,15 @@ impl<'tcx> Debug for Operand<'tcx> { impl<'tcx> Operand<'tcx> { /// Convenience helper to make a constant that refers to the fn - /// with given `DefId` and substs. Since this is used to synthesize + /// with given `DefId` and args. Since this is used to synthesize /// MIR, assumes `user_ty` is None. pub fn function_handle( tcx: TyCtxt<'tcx>, def_id: DefId, - substs: impl IntoIterator<Item = GenericArg<'tcx>>, + args: impl IntoIterator<Item = GenericArg<'tcx>>, span: Span, ) -> Self { - let ty = tcx.mk_fn_def(def_id, substs); + let ty = Ty::new_fn_def(tcx, def_id, args); Operand::Constant(Box::new(Constant { span, user_ty: None, @@ -1981,9 +1981,9 @@ impl<'tcx> Operand<'tcx> { /// /// While this is unlikely in general, it's the normal case of what you'll /// find as the `func` in a [`TerminatorKind::Call`]. - pub fn const_fn_def(&self) -> Option<(DefId, SubstsRef<'tcx>)> { + pub fn const_fn_def(&self) -> Option<(DefId, GenericArgsRef<'tcx>)> { let const_ty = self.constant()?.literal.ty(); - if let ty::FnDef(def_id, substs) = *const_ty.kind() { Some((def_id, substs)) } else { None } + if let ty::FnDef(def_id, args) = *const_ty.kind() { Some((def_id, args)) } else { None } } } @@ -2014,7 +2014,7 @@ impl<'tcx> Rvalue<'tcx> { | CastKind::IntToFloat | CastKind::FnPtrToPtr | CastKind::PtrToPtr - | CastKind::Pointer(_) + | CastKind::PointerCoercion(_) | CastKind::PointerFromExposedAddress | CastKind::DynStar | CastKind::Transmute, @@ -2035,23 +2035,19 @@ impl<'tcx> Rvalue<'tcx> { impl BorrowKind { pub fn mutability(&self) -> Mutability { match *self { - BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => Mutability::Not, + BorrowKind::Shared | BorrowKind::Shallow => Mutability::Not, BorrowKind::Mut { .. } => Mutability::Mut, } } pub fn allows_two_phase_borrow(&self) -> bool { match *self { - BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false, - BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow, - } - } - - // FIXME: won't be used after diagnostic migration - pub fn describe_mutability(&self) -> &str { - match *self { - BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => "immutable", - BorrowKind::Mut { .. } => "mutable", + BorrowKind::Shared + | BorrowKind::Shallow + | BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::ClosureCapture } => { + false + } + BorrowKind::Mut { kind: MutBorrowKind::TwoPhaseBorrow } => true, } } } @@ -2090,7 +2086,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { let kind_str = match borrow_kind { BorrowKind::Shared => "", BorrowKind::Shallow => "shallow ", - BorrowKind::Mut { .. } | BorrowKind::Unique => "mut ", + BorrowKind::Mut { .. } => "mut ", }; // When printing regions, add trailing space if necessary. @@ -2141,12 +2137,12 @@ impl<'tcx> Debug for Rvalue<'tcx> { } } - AggregateKind::Adt(adt_did, variant, substs, _user_ty, _) => { + AggregateKind::Adt(adt_did, variant, args, _user_ty, _) => { ty::tls::with(|tcx| { let variant_def = &tcx.adt_def(adt_did).variant(variant); - let substs = tcx.lift(substs).expect("could not lift for printing"); + let args = tcx.lift(args).expect("could not lift for printing"); let name = FmtPrinter::new(tcx, Namespace::ValueNS) - .print_def_path(variant_def.def_id, substs)? + .print_def_path(variant_def.def_id, args)? .into_buffer(); match variant_def.ctor_kind() { @@ -2163,10 +2159,10 @@ impl<'tcx> Debug for Rvalue<'tcx> { }) } - AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| { + AggregateKind::Closure(def_id, args) => ty::tls::with(|tcx| { let name = if tcx.sess.opts.unstable_opts.span_free_formats { - let substs = tcx.lift(substs).unwrap(); - format!("[closure@{}]", tcx.def_path_str_with_substs(def_id, substs),) + let args = tcx.lift(args).unwrap(); + format!("[closure@{}]", tcx.def_path_str_with_args(def_id, args),) } else { let span = tcx.def_span(def_id); format!( @@ -2333,10 +2329,10 @@ impl<'tcx> ConstantKind<'tcx> { pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { match self { Self::Ty(c) => { - if let Some(val) = c.kind().try_eval_for_mir(tcx, param_env) { + if let Some(val) = c.try_eval_for_mir(tcx, param_env) { match val { Ok(val) => Self::Val(val, c.ty()), - Err(guar) => Self::Ty(tcx.const_error(self.ty(), guar)), + Err(guar) => Self::Ty(ty::Const::new_error(tcx, guar, self.ty())), } } else { self @@ -2348,7 +2344,9 @@ impl<'tcx> ConstantKind<'tcx> { match tcx.const_eval_resolve(param_env, uneval, None) { Ok(val) => Self::Val(val, ty), Err(ErrorHandled::TooGeneric) => self, - Err(ErrorHandled::Reported(guar)) => Self::Ty(tcx.const_error(ty, guar.into())), + Err(ErrorHandled::Reported(guar)) => { + Self::Ty(ty::Const::new_error(tcx, guar.into(), ty)) + } } } } @@ -2495,7 +2493,7 @@ impl<'tcx> ConstantKind<'tcx> { }; debug!("expr.kind: {:?}", expr.kind); - let ty = tcx.type_of(def).subst_identity(); + let ty = tcx.type_of(def).instantiate_identity(); debug!(?ty); // FIXME(const_generics): We currently have to special case parameters because `min_const_generics` @@ -2514,7 +2512,7 @@ impl<'tcx> ConstantKind<'tcx> { let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; let name = tcx.item_name(def_id); - let ty_const = tcx.mk_const(ty::ParamConst::new(index, name), ty); + let ty_const = ty::Const::new_param(tcx, ty::ParamConst::new(index, name), ty); debug!(?ty_const); return Self::Ty(ty_const); @@ -2523,23 +2521,22 @@ impl<'tcx> ConstantKind<'tcx> { } let hir_id = tcx.hir().local_def_id_to_hir_id(def); - let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id) + let parent_args = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id) && let Some(parent_did) = parent_hir_id.as_owner() { - InternalSubsts::identity_for_item(tcx, parent_did) + GenericArgs::identity_for_item(tcx, parent_did) } else { List::empty() }; - debug!(?parent_substs); + debug!(?parent_args); let did = def.to_def_id(); - let child_substs = InternalSubsts::identity_for_item(tcx, did); - let substs = - tcx.mk_substs_from_iter(parent_substs.into_iter().chain(child_substs.into_iter())); - debug!(?substs); + let child_args = GenericArgs::identity_for_item(tcx, did); + let args = tcx.mk_args_from_iter(parent_args.into_iter().chain(child_args.into_iter())); + debug!(?args); let span = tcx.def_span(def); - let uneval = UnevaluatedConst::new(did, substs); + let uneval = UnevaluatedConst::new(did, args); debug!(?span, ?param_env); match tcx.const_eval_resolve(param_env, uneval, Some(span)) { @@ -2554,7 +2551,7 @@ impl<'tcx> ConstantKind<'tcx> { Self::Unevaluated( UnevaluatedConst { def: did, - substs: InternalSubsts::identity_for_item(tcx, did), + args: GenericArgs::identity_for_item(tcx, did), promoted: None, }, ty, @@ -2580,23 +2577,22 @@ impl<'tcx> ConstantKind<'tcx> { #[derive(Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct UnevaluatedConst<'tcx> { pub def: DefId, - pub substs: SubstsRef<'tcx>, + pub args: GenericArgsRef<'tcx>, pub promoted: Option<Promoted>, } impl<'tcx> UnevaluatedConst<'tcx> { - // FIXME: probably should get rid of this method. It's also wrong to - // shrink and then later expand a promoted. #[inline] pub fn shrink(self) -> ty::UnevaluatedConst<'tcx> { - ty::UnevaluatedConst { def: self.def, substs: self.substs } + assert_eq!(self.promoted, None); + ty::UnevaluatedConst { def: self.def, args: self.args } } } impl<'tcx> UnevaluatedConst<'tcx> { #[inline] - pub fn new(def: DefId, substs: SubstsRef<'tcx>) -> UnevaluatedConst<'tcx> { - UnevaluatedConst { def, substs, promoted: Default::default() } + pub fn new(def: DefId, args: GenericArgsRef<'tcx>) -> UnevaluatedConst<'tcx> { + UnevaluatedConst { def, args, promoted: Default::default() } } } @@ -2779,7 +2775,7 @@ impl<'tcx> Display for ConstantKind<'tcx> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { match *self { ConstantKind::Ty(c) => pretty_print_const(c, fmt, true), - ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt, true), + ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt), // FIXME(valtrees): Correctly print mir constants. ConstantKind::Unevaluated(..) => { fmt.write_str("_")?; @@ -2809,13 +2805,16 @@ fn pretty_print_byte_str(fmt: &mut Formatter<'_>, byte_str: &[u8]) -> fmt::Resul write!(fmt, "b\"{}\"", byte_str.escape_ascii()) } -fn comma_sep<'tcx>(fmt: &mut Formatter<'_>, elems: Vec<ConstantKind<'tcx>>) -> fmt::Result { +fn comma_sep<'tcx>( + fmt: &mut Formatter<'_>, + elems: Vec<(ConstValue<'tcx>, Ty<'tcx>)>, +) -> fmt::Result { let mut first = true; - for elem in elems { + for (ct, ty) in elems { if !first { fmt.write_str(", ")?; } - fmt.write_str(&format!("{}", elem))?; + pretty_print_const_value(ct, ty, fmt)?; first = false; } Ok(()) @@ -2826,7 +2825,6 @@ fn pretty_print_const_value<'tcx>( ct: ConstValue<'tcx>, ty: Ty<'tcx>, fmt: &mut Formatter<'_>, - print_ty: bool, ) -> fmt::Result { use crate::ty::print::PrettyPrinter; @@ -2870,7 +2868,7 @@ fn pretty_print_const_value<'tcx>( } } (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => { - let n = n.kind().try_to_bits(tcx.data_layout.pointer_size).unwrap(); + let n = n.try_to_bits(tcx.data_layout.pointer_size).unwrap(); // cast is ok because we already checked for pointer size (32 or 64 bit) above let range = AllocRange { start: offset, size: Size::from_bytes(n) }; let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap(); @@ -2885,16 +2883,11 @@ fn pretty_print_const_value<'tcx>( // introducing ICEs (e.g. via `layout_of`) from missing bounds. // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized` // to be able to destructure the tuple into `(0u8, *mut T)` - // - // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the - // correct `ty::ParamEnv` to allow printing *all* constant values. (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => { let ct = tcx.lift(ct).unwrap(); let ty = tcx.lift(ty).unwrap(); - if let Some(contents) = tcx.try_destructure_mir_constant( - ty::ParamEnv::reveal_all().and(ConstantKind::Val(ct, ty)), - ) { - let fields = contents.fields.to_vec(); + if let Some(contents) = tcx.try_destructure_mir_constant_for_diagnostics((ct, ty)) { + let fields: Vec<(ConstValue<'_>, Ty<'_>)> = contents.fields.to_vec(); match *ty.kind() { ty::Array(..) => { fmt.write_str("[")?; @@ -2912,15 +2905,15 @@ fn pretty_print_const_value<'tcx>( ty::Adt(def, _) if def.variants().is_empty() => { fmt.write_str(&format!("{{unreachable(): {}}}", ty))?; } - ty::Adt(def, substs) => { + ty::Adt(def, args) => { let variant_idx = contents .variant .expect("destructed mir constant of adt without variant idx"); let variant_def = &def.variant(variant_idx); - let substs = tcx.lift(substs).unwrap(); + let args = tcx.lift(args).unwrap(); let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS); cx.print_alloc_ids = true; - let cx = cx.print_value_path(variant_def.def_id, substs)?; + let cx = cx.print_value_path(variant_def.def_id, args)?; fmt.write_str(&cx.into_buffer())?; match variant_def.ctor_kind() { @@ -2933,12 +2926,14 @@ fn pretty_print_const_value<'tcx>( None => { fmt.write_str(" {{ ")?; let mut first = true; - for (field_def, field) in iter::zip(&variant_def.fields, fields) + for (field_def, (ct, ty)) in + iter::zip(&variant_def.fields, fields) { if !first { fmt.write_str(", ")?; } - fmt.write_str(&format!("{}: {}", field_def.name, field))?; + write!(fmt, "{}: ", field_def.name)?; + pretty_print_const_value(ct, ty, fmt)?; first = false; } fmt.write_str(" }}")?; @@ -2948,20 +2943,13 @@ fn pretty_print_const_value<'tcx>( _ => unreachable!(), } return Ok(()); - } else { - // Fall back to debug pretty printing for invalid constants. - fmt.write_str(&format!("{:?}", ct))?; - if print_ty { - fmt.write_str(&format!(": {}", ty))?; - } - return Ok(()); - }; + } } (ConstValue::Scalar(scalar), _) => { let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS); cx.print_alloc_ids = true; let ty = tcx.lift(ty).unwrap(); - cx = cx.pretty_print_const_scalar(scalar, ty, print_ty)?; + cx = cx.pretty_print_const_scalar(scalar, ty)?; fmt.write_str(&cx.into_buffer())?; return Ok(()); } @@ -2976,12 +2964,8 @@ fn pretty_print_const_value<'tcx>( // their fields instead of just dumping the memory. _ => {} } - // fallback - fmt.write_str(&format!("{:?}", ct))?; - if print_ty { - fmt.write_str(&format!(": {}", ty))?; - } - Ok(()) + // Fall back to debug pretty printing for invalid constants. + write!(fmt, "{ct:?}: {ty}") }) } diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 1511e255235..f4133dfbc95 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -1,5 +1,5 @@ use crate::dep_graph::{DepNode, WorkProduct, WorkProductId}; -use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt}; +use crate::ty::{GenericArgs, Instance, InstanceDef, SymbolName, TyCtxt}; use rustc_attr::InlineAttr; use rustc_data_structures::base_n; use rustc_data_structures::fingerprint::Fingerprint; @@ -56,22 +56,31 @@ impl<'tcx> MonoItem<'tcx> { } } + // Note: if you change how item size estimates work, you might need to + // change NON_INCR_MIN_CGU_SIZE as well. pub fn size_estimate(&self, tcx: TyCtxt<'tcx>) -> usize { match *self { MonoItem::Fn(instance) => { - // Estimate the size of a function based on how many statements - // it contains. - tcx.instance_def_size_estimate(instance.def) + match instance.def { + // "Normal" functions size estimate: the number of + // statements, plus one for the terminator. + InstanceDef::Item(..) | InstanceDef::DropGlue(..) => { + let mir = tcx.instance_mir(instance.def); + mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum() + } + // Other compiler-generated shims size estimate: 1 + _ => 1, + } } - // Conservatively estimate the size of a static declaration - // or assembly to be 1. + // Conservatively estimate the size of a static declaration or + // assembly item to be 1. MonoItem::Static(_) | MonoItem::GlobalAsm(_) => 1, } } pub fn is_generic_fn(&self) -> bool { match *self { - MonoItem::Fn(ref instance) => instance.substs.non_erasable_generics().next().is_some(), + MonoItem::Fn(ref instance) => instance.args.non_erasable_generics().next().is_some(), MonoItem::Static(..) | MonoItem::GlobalAsm(..) => false, } } @@ -168,14 +177,14 @@ impl<'tcx> MonoItem<'tcx> { /// which will never be accessed) in its place. pub fn is_instantiable(&self, tcx: TyCtxt<'tcx>) -> bool { debug!("is_instantiable({:?})", self); - let (def_id, substs) = match *self { - MonoItem::Fn(ref instance) => (instance.def_id(), instance.substs), - MonoItem::Static(def_id) => (def_id, InternalSubsts::empty()), + let (def_id, args) = match *self { + MonoItem::Fn(ref instance) => (instance.def_id(), instance.args), + MonoItem::Static(def_id) => (def_id, GenericArgs::empty()), // global asm never has predicates MonoItem::GlobalAsm(..) => return true, }; - !tcx.subst_and_check_impossible_predicates((def_id, &substs)) + !tcx.subst_and_check_impossible_predicates((def_id, &args)) } pub fn local_span(&self, tcx: TyCtxt<'tcx>) -> Option<Span> { @@ -216,7 +225,7 @@ impl<'tcx> fmt::Display for MonoItem<'tcx> { match *self { MonoItem::Fn(instance) => write!(f, "fn {}", instance), MonoItem::Static(def_id) => { - write!(f, "static {}", Instance::new(def_id, InternalSubsts::empty())) + write!(f, "static {}", Instance::new(def_id, GenericArgs::empty())) } MonoItem::GlobalAsm(..) => write!(f, "global_asm"), } @@ -230,14 +239,28 @@ pub struct CodegenUnit<'tcx> { /// contain something unique to this crate (e.g., a module path) /// as well as the crate name and disambiguator. name: Symbol, - items: FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)>, - size_estimate: Option<usize>, + items: FxHashMap<MonoItem<'tcx>, MonoItemData>, + size_estimate: usize, primary: bool, /// True if this is CGU is used to hold code coverage information for dead code, /// false otherwise. is_code_coverage_dead_code_cgu: bool, } +/// Auxiliary info about a `MonoItem`. +#[derive(Copy, Clone, PartialEq, Debug, HashStable)] +pub struct MonoItemData { + /// A cached copy of the result of `MonoItem::instantiation_mode`, where + /// `GloballyShared` maps to `false` and `LocalCopy` maps to `true`. + pub inlined: bool, + + pub linkage: Linkage, + pub visibility: Visibility, + + /// A cached copy of the result of `MonoItem::size_estimate`. + pub size_estimate: usize, +} + /// Specifies the linkage type for a `MonoItem`. /// /// See <https://llvm.org/docs/LangRef.html#linkage-types> for more details about these variants. @@ -269,7 +292,7 @@ impl<'tcx> CodegenUnit<'tcx> { CodegenUnit { name, items: Default::default(), - size_estimate: None, + size_estimate: 0, primary: false, is_code_coverage_dead_code_cgu: false, } @@ -292,12 +315,12 @@ impl<'tcx> CodegenUnit<'tcx> { } /// The order of these items is non-determinstic. - pub fn items(&self) -> &FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> { + pub fn items(&self) -> &FxHashMap<MonoItem<'tcx>, MonoItemData> { &self.items } /// The order of these items is non-determinstic. - pub fn items_mut(&mut self) -> &mut FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> { + pub fn items_mut(&mut self) -> &mut FxHashMap<MonoItem<'tcx>, MonoItemData> { &mut self.items } @@ -320,23 +343,21 @@ impl<'tcx> CodegenUnit<'tcx> { base_n::encode(hash, base_n::CASE_INSENSITIVE) } - pub fn create_size_estimate(&mut self, tcx: TyCtxt<'tcx>) { - // Estimate the size of a codegen unit as (approximately) the number of MIR - // statements it corresponds to. - self.size_estimate = Some(self.items.keys().map(|mi| mi.size_estimate(tcx)).sum()); + pub fn compute_size_estimate(&mut self) { + // The size of a codegen unit as the sum of the sizes of the items + // within it. + self.size_estimate = self.items.values().map(|data| data.size_estimate).sum(); } - #[inline] - /// Should only be called if [`create_size_estimate`] has previously been called. + /// Should only be called if [`compute_size_estimate`] has previously been called. /// - /// [`create_size_estimate`]: Self::create_size_estimate + /// [`compute_size_estimate`]: Self::compute_size_estimate + #[inline] pub fn size_estimate(&self) -> usize { + // Items are never zero-sized, so if we have items the estimate must be + // non-zero, unless we forgot to call `compute_size_estimate` first. + assert!(self.items.is_empty() || self.size_estimate != 0); self.size_estimate - .expect("create_size_estimate must be called before getting a size_estimate") - } - - pub fn modify_size_estimate(&mut self, delta: usize) { - *self.size_estimate.as_mut().unwrap() += delta; } pub fn contains_item(&self, item: &MonoItem<'tcx>) -> bool { @@ -357,7 +378,7 @@ impl<'tcx> CodegenUnit<'tcx> { pub fn items_in_deterministic_order( &self, tcx: TyCtxt<'tcx>, - ) -> Vec<(MonoItem<'tcx>, (Linkage, Visibility))> { + ) -> Vec<(MonoItem<'tcx>, MonoItemData)> { // The codegen tests rely on items being process in the same order as // they appear in the file, so for local items, we sort by node_id first #[derive(PartialEq, Eq, PartialOrd, Ord)] @@ -392,7 +413,7 @@ impl<'tcx> CodegenUnit<'tcx> { ) } - let mut items: Vec<_> = self.items().iter().map(|(&i, &l)| (i, l)).collect(); + let mut items: Vec<_> = self.items().iter().map(|(&i, &data)| (i, data)).collect(); items.sort_by_cached_key(|&(i, _)| item_sort_key(tcx, i)); items } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index ffa7a5400d3..8cbab31451b 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -477,7 +477,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { ConstantKind::Ty(ct) => match ct.kind() { ty::ConstKind::Param(p) => format!("Param({})", p), ty::ConstKind::Unevaluated(uv) => { - format!("Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.substs,) + format!("Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,) } ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)), ty::ConstKind::Error(_) => "Error".to_string(), @@ -491,7 +491,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { format!( "Unevaluated({}, {:?}, {:?})", self.tcx.def_path_str(uv.def), - uv.substs, + uv.args, uv.promoted, ) } @@ -512,16 +512,16 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { self.super_rvalue(rvalue, location); if let Rvalue::Aggregate(kind, _) = rvalue { match **kind { - AggregateKind::Closure(def_id, substs) => { + AggregateKind::Closure(def_id, args) => { self.push("closure"); self.push(&format!("+ def_id: {:?}", def_id)); - self.push(&format!("+ substs: {:#?}", substs)); + self.push(&format!("+ args: {:#?}", args)); } - AggregateKind::Generator(def_id, substs, movability) => { + AggregateKind::Generator(def_id, args, movability) => { self.push("generator"); self.push(&format!("+ def_id: {:?}", def_id)); - self.push(&format!("+ substs: {:#?}", substs)); + self.push(&format!("+ args: {:#?}", args)); self.push(&format!("+ movability: {:?}", movability)); } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index a15c419da7a..e8cb9860ee5 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -1,6 +1,6 @@ //! Values computed by queries that use MIR. -use crate::mir::ConstantKind; +use crate::mir::interpret::ConstValue; use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::UnordSet; @@ -9,6 +9,7 @@ use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::BitMatrix; use rustc_index::{Idx, IndexVec}; +use rustc_span::symbol::Symbol; use rustc_span::Span; use rustc_target::abi::{FieldIdx, VariantIdx}; use smallvec::SmallVec; @@ -150,6 +151,9 @@ pub struct GeneratorLayout<'tcx> { /// The type of every local stored inside the generator. pub field_tys: IndexVec<GeneratorSavedLocal, GeneratorSavedTy<'tcx>>, + /// The name for debuginfo. + pub field_names: IndexVec<GeneratorSavedLocal, Option<Symbol>>, + /// Which of the above fields are in each variant. Note that one field may /// be stored in multiple variants. pub variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, GeneratorSavedLocal>>, @@ -190,7 +194,7 @@ impl Debug for GeneratorLayout<'_> { } impl Debug for GenVariantPrinter { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let variant_name = ty::GeneratorSubsts::variant_name(self.0); + let variant_name = ty::GeneratorArgs::variant_name(self.0); if fmt.alternate() { write!(fmt, "{:9}({:?})", variant_name, self.0) } else { @@ -261,10 +265,10 @@ pub struct ConstQualifs { /// `UniversalRegions::closure_mapping`.) Note the free regions in the /// closure's signature and captures are erased. /// -/// Example: If type check produces a closure with the closure substs: +/// Example: If type check produces a closure with the closure args: /// /// ```text -/// ClosureSubsts = [ +/// ClosureArgs = [ /// 'a, // From the parent. /// 'b, /// i8, // the "closure kind" @@ -276,7 +280,7 @@ pub struct ConstQualifs { /// We would "renumber" each free region to a unique vid, as follows: /// /// ```text -/// ClosureSubsts = [ +/// ClosureArgs = [ /// '1, // From the parent. /// '2, /// i8, // the "closure kind" @@ -440,7 +444,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { #[derive(Copy, Clone, Debug, HashStable)] pub struct DestructuredConstant<'tcx> { pub variant: Option<VariantIdx>, - pub fields: &'tcx [ConstantKind<'tcx>], + pub fields: &'tcx [(ConstValue<'tcx>, Ty<'tcx>)], } /// Coverage information summarized from a MIR if instrumented for source code coverage (see diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs index 2165403da26..730c551576a 100644 --- a/compiler/rustc_middle/src/mir/spanview.rs +++ b/compiler/rustc_middle/src/mir/spanview.rs @@ -3,7 +3,7 @@ use rustc_middle::hir; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use rustc_session::config::MirSpanview; -use rustc_span::{BytePos, Pos, Span, SyntaxContext}; +use rustc_span::{BytePos, Pos, Span}; use std::cmp; use std::io::{self, Write}; @@ -15,8 +15,9 @@ const ANNOTATION_LEFT_BRACKET: char = '\u{298a}'; // Unicode `Z NOTATION RIGHT B const ANNOTATION_RIGHT_BRACKET: char = '\u{2989}'; // Unicode `Z NOTATION LEFT BINDING BRACKET` const NEW_LINE_SPAN: &str = "</span>\n<span class=\"line\">"; const HEADER: &str = r#"<!DOCTYPE html> -<html> -<head>"#; +<html lang="en"> +<head> +<meta charset="utf-8">"#; const START_BODY: &str = r#"</head> <body>"#; const FOOTER: &str = r#"</body> @@ -327,7 +328,7 @@ fn compute_block_span(data: &BasicBlockData<'_>, body_span: Span) -> Span { let mut span = data.terminator().source_info.span; for statement_span in data.statements.iter().map(|statement| statement.source_info.span) { // Only combine Spans from the root context, and within the function's body_span. - if statement_span.ctxt() == SyntaxContext::root() && body_span.contains(statement_span) { + if statement_span.ctxt().is_root() && body_span.contains(statement_span) { span = span.to(statement_span); } } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 1a65f74f4fe..be27bf75dbd 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -7,8 +7,8 @@ use super::{BasicBlock, Constant, Local, SwitchTargets, UserTypeProjection}; use crate::mir::coverage::{CodeRegion, CoverageKind}; use crate::traits::Reveal; -use crate::ty::adjustment::PointerCast; -use crate::ty::subst::SubstsRef; +use crate::ty::adjustment::PointerCoercion; +use crate::ty::GenericArgsRef; use crate::ty::{self, List, Ty}; use crate::ty::{Region, UserTypeAnnotationIndex}; @@ -182,6 +182,16 @@ pub enum BorrowKind { /// We can also report errors with this kind of borrow differently. Shallow, + /// Data is mutable and not aliasable. + Mut { kind: MutBorrowKind }, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)] +#[derive(Hash, HashStable)] +pub enum MutBorrowKind { + Default, + /// This borrow arose from method-call auto-ref. (i.e., `adjustment::Adjust::Borrow`) + TwoPhaseBorrow, /// Data must be immutable but not aliasable. This kind of borrow /// cannot currently be expressed by the user and is used only in /// implicit closure bindings. It is needed when the closure is @@ -216,23 +226,14 @@ pub enum BorrowKind { /// user code, if awkward, but extra weird for closures, since the /// borrow is hidden. /// - /// So we introduce a "unique imm" borrow -- the referent is - /// immutable, but not aliasable. This solves the problem. For - /// simplicity, we don't give users the way to express this - /// borrow, it's just used when translating closures. + /// So we introduce a `ClosureCapture` borrow -- user will not have to mark the variable + /// containing the mutable reference as `mut`, as they didn't ever + /// intend to mutate the mutable reference itself. We still mutable capture it in order to + /// mutate the pointed value through it (but not mutating the reference itself). /// - // FIXME(#112072): This is wrong. Unique borrows are mutable borrows except - // that they do not require their pointee to be marked as a mutable. - // They should still be treated as mutable borrows in every other way, - // e.g. for variance or overlap checking. - Unique, - - /// Data is mutable and not aliasable. - Mut { - /// `true` if this borrow arose from method-call auto-ref - /// (i.e., `adjustment::Adjust::Borrow`). - allow_two_phase_borrow: bool, - }, + /// This solves the problem. For simplicity, we don't give users the way to express this + /// borrow, it's just used when translating closures. + ClosureCapture, } /////////////////////////////////////////////////////////////////////////// @@ -512,6 +513,31 @@ pub struct CopyNonOverlapping<'tcx> { pub count: Operand<'tcx>, } +/// Represents how a `TerminatorKind::Call` was constructed, used for diagnostics +#[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, PartialEq, Hash, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] +pub enum CallSource { + /// This came from something such as `a > b` or `a + b`. In THIR, if `from_hir_call` + /// is false then this is the desugaring. + OverloadedOperator, + /// This was from comparison generated by a match, used by const-eval for better errors + /// when the comparison cannot be done in compile time. + /// + /// (see <https://github.com/rust-lang/rust/issues/90237>) + MatchCmp, + /// Other types of desugaring that did not come from the HIR, but we don't care about + /// for diagnostics (yet). + Misc, + /// Normal function call, no special source + Normal, +} + +impl CallSource { + pub fn from_hir_call(self) -> bool { + matches!(self, CallSource::Normal) + } +} + /////////////////////////////////////////////////////////////////////////// // Terminators @@ -638,11 +664,10 @@ pub enum TerminatorKind<'tcx> { target: Option<BasicBlock>, /// Action to be taken if the call unwinds. unwind: UnwindAction, - /// `true` if this is from a call in HIR rather than from an overloaded - /// operator. True for overloaded function call. - from_hir_call: bool, + /// Where this call came from in HIR/THIR. + call_source: CallSource, /// This `Span` is the span of the function, without the dot and receiver - /// (e.g. `foo(a, b)` in `x.foo(a, b)` + /// e.g. `foo(a, b)` in `x.foo(a, b)` fn_span: Span, }, @@ -1025,10 +1050,6 @@ pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>; /// there may be other effects: if the type has a validity constraint loading the place might be UB /// if the validity constraint is not met. /// -/// **Needs clarification:** Ralf proposes that loading a place not have side-effects. -/// This is what is implemented in miri today. Are these the semantics we want for MIR? Is this -/// something we can even decide without knowing more about Rust's memory model? -/// /// **Needs clarification:** Is loading a place that has its variant index set well-formed? Miri /// currently implements it, but it seems like this may be something to check against in the /// validator. @@ -1046,6 +1067,16 @@ pub enum Operand<'tcx> { /// in [UCG#188]. You should not emit MIR that may attempt a subsequent second load of this /// place without first re-initializing it. /// + /// **Needs clarification:** The operational impact of `Move` is unclear. Currently (both in + /// Miri and codegen) it has no effect at all unless it appears in an argument to `Call`; for + /// `Call` it allows the argument to be passed to the callee "in-place", i.e. the callee might + /// just get a reference to this place instead of a full copy. Miri implements this with a + /// combination of aliasing model "protectors" and putting `uninit` into the place. Ralf + /// proposes that we don't want these semantics for `Move` in regular assignments, because + /// loading a place should not have side-effects, and the aliasing model "protectors" are + /// inherently tied to a function call. Are these the semantics we want for MIR? Is this + /// something we can even decide without knowing more about Rust's memory model? + /// /// [UCG#188]: https://github.com/rust-lang/unsafe-code-guidelines/issues/188 Move(Place<'tcx>), @@ -1205,9 +1236,9 @@ pub enum CastKind { /// An address-to-pointer cast that picks up an exposed provenance. /// See the docs on `from_exposed_addr` for more details. PointerFromExposedAddress, - /// All sorts of pointer-to-pointer casts. Note that reference-to-raw-ptr casts are + /// Pointer related casts that are done by coercions. Note that reference-to-raw-ptr casts are /// translated into `&raw mut/const *r`, i.e., they are not actually casts. - Pointer(PointerCast), + PointerCoercion(PointerCoercion), /// Cast into a dyn* object. DynStar, IntToInt, @@ -1237,10 +1268,10 @@ pub enum AggregateKind<'tcx> { /// active field number and is present only for union expressions /// -- e.g., for a union expression `SomeUnion { c: .. }`, the /// active field index would identity the field `c` - Adt(DefId, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<FieldIdx>), + Adt(DefId, VariantIdx, GenericArgsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<FieldIdx>), - Closure(DefId, SubstsRef<'tcx>), - Generator(DefId, SubstsRef<'tcx>, hir::Movability), + Closure(DefId, GenericArgsRef<'tcx>), + Generator(DefId, GenericArgsRef<'tcx>, hir::Movability), } #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] @@ -1267,10 +1298,16 @@ pub enum UnOp { pub enum BinOp { /// The `+` operator (addition) Add, + /// Like `Add`, but with UB on overflow. (Integers only.) + AddUnchecked, /// The `-` operator (subtraction) Sub, + /// Like `Sub`, but with UB on overflow. (Integers only.) + SubUnchecked, /// The `*` operator (multiplication) Mul, + /// Like `Mul`, but with UB on overflow. (Integers only.) + MulUnchecked, /// The `/` operator (division) /// /// For integer types, division by zero is UB, as is `MIN / -1` for signed. @@ -1296,10 +1333,17 @@ pub enum BinOp { /// /// The offset is truncated to the size of the first operand before shifting. Shl, + /// Like `Shl`, but is UB if the RHS >= LHS::BITS + ShlUnchecked, /// The `>>` operator (shift right) /// /// The offset is truncated to the size of the first operand before shifting. + /// + /// This is an arithmetic shift if the LHS is signed + /// and a logical shift if the LHS is unsigned. Shr, + /// Like `Shl`, but is UB if the RHS >= LHS::BITS + ShrUnchecked, /// The `==` operator (equality) Eq, /// The `<` operator (less than) diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 5ca82413448..f79697936d2 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -35,7 +35,7 @@ impl<'tcx> PlaceTy<'tcx> { #[instrument(level = "debug", skip(tcx), ret)] pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: FieldIdx) -> Ty<'tcx> { match self.ty.kind() { - ty::Adt(adt_def, substs) => { + ty::Adt(adt_def, args) => { let variant_def = match self.variant_index { None => adt_def.non_enum_variant(), Some(variant_index) => { @@ -44,7 +44,7 @@ impl<'tcx> PlaceTy<'tcx> { } }; let field_def = &variant_def.fields[f]; - field_def.ty(tcx, substs) + field_def.ty(tcx, args) } ty::Tuple(tys) => tys[f.index()], _ => bug!("extracting field of non-tuple non-adt: {:?}", self), @@ -95,11 +95,13 @@ impl<'tcx> PlaceTy<'tcx> { ProjectionElem::Subslice { from, to, from_end } => { PlaceTy::from_ty(match self.ty.kind() { ty::Slice(..) => self.ty, - ty::Array(inner, _) if !from_end => tcx.mk_array(*inner, (to - from) as u64), + ty::Array(inner, _) if !from_end => { + Ty::new_array(tcx, *inner, (to - from) as u64) + } ty::Array(inner, size) if from_end => { let size = size.eval_target_usize(tcx, param_env); let len = size - from - to; - tcx.mk_array(*inner, len) + Ty::new_array(tcx, *inner, len) } _ => bug!("cannot subslice non-array type: `{:?}`", self), }) @@ -162,16 +164,16 @@ impl<'tcx> Rvalue<'tcx> { match *self { Rvalue::Use(ref operand) => operand.ty(local_decls, tcx), Rvalue::Repeat(ref operand, count) => { - tcx.mk_array_with_const_len(operand.ty(local_decls, tcx), count) + Ty::new_array_with_const_len(tcx, operand.ty(local_decls, tcx), count) } Rvalue::ThreadLocalRef(did) => tcx.thread_local_ptr_ty(did), Rvalue::Ref(reg, bk, ref place) => { let place_ty = place.ty(local_decls, tcx).ty; - tcx.mk_ref(reg, ty::TypeAndMut { ty: place_ty, mutbl: bk.to_mutbl_lossy() }) + Ty::new_ref(tcx, reg, ty::TypeAndMut { ty: place_ty, mutbl: bk.to_mutbl_lossy() }) } Rvalue::AddressOf(mutability, ref place) => { let place_ty = place.ty(local_decls, tcx).ty; - tcx.mk_ptr(ty::TypeAndMut { ty: place_ty, mutbl: mutability }) + Ty::new_ptr(tcx, ty::TypeAndMut { ty: place_ty, mutbl: mutability }) } Rvalue::Len(..) => tcx.types.usize, Rvalue::Cast(.., ty) => ty, @@ -184,7 +186,7 @@ impl<'tcx> Rvalue<'tcx> { let lhs_ty = lhs.ty(local_decls, tcx); let rhs_ty = rhs.ty(local_decls, tcx); let ty = op.ty(tcx, lhs_ty, rhs_ty); - tcx.mk_tup(&[ty, tcx.types.bool]) + Ty::new_tup(tcx, &[ty, tcx.types.bool]) } Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx), Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx), @@ -192,17 +194,17 @@ impl<'tcx> Rvalue<'tcx> { tcx.types.usize } Rvalue::Aggregate(ref ak, ref ops) => match **ak { - AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64), + AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64), AggregateKind::Tuple => { - tcx.mk_tup_from_iter(ops.iter().map(|op| op.ty(local_decls, tcx))) + Ty::new_tup_from_iter(tcx, ops.iter().map(|op| op.ty(local_decls, tcx))) } - AggregateKind::Adt(did, _, substs, _, _) => tcx.type_of(did).subst(tcx, substs), - AggregateKind::Closure(did, substs) => tcx.mk_closure(did, substs), - AggregateKind::Generator(did, substs, movability) => { - tcx.mk_generator(did, substs, movability) + AggregateKind::Adt(did, _, args, _, _) => tcx.type_of(did).instantiate(tcx, args), + AggregateKind::Closure(did, args) => Ty::new_closure(tcx, did, args), + AggregateKind::Generator(did, args, movability) => { + Ty::new_generator(tcx, did, args, movability) } }, - Rvalue::ShallowInitBox(_, ty) => tcx.mk_box(ty), + Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty), Rvalue::CopyForDeref(ref place) => place.ty(local_decls, tcx).ty, } } @@ -235,8 +237,11 @@ impl<'tcx> BinOp { // FIXME: handle SIMD correctly match self { &BinOp::Add + | &BinOp::AddUnchecked | &BinOp::Sub + | &BinOp::SubUnchecked | &BinOp::Mul + | &BinOp::MulUnchecked | &BinOp::Div | &BinOp::Rem | &BinOp::BitXor @@ -246,7 +251,11 @@ impl<'tcx> BinOp { assert_eq!(lhs_ty, rhs_ty); lhs_ty } - &BinOp::Shl | &BinOp::Shr | &BinOp::Offset => { + &BinOp::Shl + | &BinOp::ShlUnchecked + | &BinOp::Shr + | &BinOp::ShrUnchecked + | &BinOp::Offset => { lhs_ty // lhs_ty can be != rhs_ty } &BinOp::Eq | &BinOp::Lt | &BinOp::Le | &BinOp::Ne | &BinOp::Ge | &BinOp::Gt => { @@ -262,11 +271,6 @@ impl BorrowKind { BorrowKind::Mut { .. } => hir::Mutability::Mut, BorrowKind::Shared => hir::Mutability::Not, - // We have no type corresponding to a unique imm borrow, so - // use `&mut`. It gives all the capabilities of a `&uniq` - // and hence is a safe "over approximation". - BorrowKind::Unique => hir::Mutability::Mut, - // We have no type corresponding to a shallow borrow, so use // `&` as an approximation. BorrowKind::Shallow => hir::Mutability::Not, @@ -293,7 +297,14 @@ impl BinOp { BinOp::Gt => hir::BinOpKind::Gt, BinOp::Le => hir::BinOpKind::Le, BinOp::Ge => hir::BinOpKind::Ge, - BinOp::Offset => unreachable!(), + BinOp::AddUnchecked + | BinOp::SubUnchecked + | BinOp::MulUnchecked + | BinOp::ShlUnchecked + | BinOp::ShrUnchecked + | BinOp::Offset => { + unreachable!() + } } } } diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 561ef371b09..1b9c1438f40 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -272,7 +272,8 @@ impl<'tcx> Debug for TerminatorKind<'tcx> { let unwind = match self.unwind() { // Not needed or included in successors - None | Some(UnwindAction::Continue) | Some(UnwindAction::Cleanup(_)) => None, + None | Some(UnwindAction::Cleanup(_)) => None, + Some(UnwindAction::Continue) => Some("unwind continue"), Some(UnwindAction::Unreachable) => Some("unwind unreachable"), Some(UnwindAction::Terminate) => Some("unwind terminate"), }; diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 99ead14139a..ec16a8470c4 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -188,10 +188,6 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { } } -pub fn postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> Postorder<'a, 'tcx> { - Postorder::new(&body.basic_blocks, START_BLOCK) -} - impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> { type Item = (BasicBlock, &'a BasicBlockData<'tcx>); @@ -219,6 +215,17 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> { } } +/// Creates an iterator over the `Body`'s basic blocks, that: +/// - returns basic blocks in a postorder, +/// - traverses the `BasicBlocks` CFG cache's reverse postorder backwards, and does not cache the +/// postorder itself. +pub fn postorder<'a, 'tcx>( + body: &'a Body<'tcx>, +) -> impl Iterator<Item = (BasicBlock, &'a BasicBlockData<'tcx>)> + ExactSizeIterator + DoubleEndedIterator +{ + reverse_postorder(body).rev() +} + /// Reverse postorder traversal of a graph /// /// Reverse postorder is the reverse order of a postorder traversal. @@ -295,34 +302,12 @@ pub fn reachable_as_bitset(body: &Body<'_>) -> BitSet<BasicBlock> { iter.visited } -#[derive(Clone)] -pub struct ReversePostorderIter<'a, 'tcx> { +/// Creates an iterator over the `Body`'s basic blocks, that: +/// - returns basic blocks in a reverse postorder, +/// - makes use of the `BasicBlocks` CFG cache's reverse postorder. +pub fn reverse_postorder<'a, 'tcx>( body: &'a Body<'tcx>, - blocks: &'a [BasicBlock], - idx: usize, -} - -impl<'a, 'tcx> Iterator for ReversePostorderIter<'a, 'tcx> { - type Item = (BasicBlock, &'a BasicBlockData<'tcx>); - - fn next(&mut self) -> Option<(BasicBlock, &'a BasicBlockData<'tcx>)> { - if self.idx == 0 { - return None; - } - self.idx -= 1; - - self.blocks.get(self.idx).map(|&bb| (bb, &self.body[bb])) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.idx, Some(self.idx)) - } -} - -impl<'a, 'tcx> ExactSizeIterator for ReversePostorderIter<'a, 'tcx> {} - -pub fn reverse_postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> ReversePostorderIter<'a, 'tcx> { - let blocks = body.basic_blocks.postorder(); - let len = blocks.len(); - ReversePostorderIter { body, blocks, idx: len } +) -> impl Iterator<Item = (BasicBlock, &'a BasicBlockData<'tcx>)> + ExactSizeIterator + DoubleEndedIterator +{ + body.basic_blocks.reverse_postorder().iter().map(|&bb| (bb, &body.basic_blocks[bb])) } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 8d44e929afd..64bc4fa7926 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -63,7 +63,7 @@ //! `is_cleanup` above. use crate::mir::*; -use crate::ty::subst::SubstsRef; +use crate::ty::GenericArgsRef; use crate::ty::{self, CanonicalUserTypeAnnotation, Ty}; use rustc_span::Span; @@ -245,12 +245,12 @@ macro_rules! make_mir_visitor { self.super_region(region); } - fn visit_substs( + fn visit_args( &mut self, - substs: & $($mutability)? SubstsRef<'tcx>, + args: & $($mutability)? GenericArgsRef<'tcx>, _: Location, ) { - self.super_substs(substs); + self.super_args(args); } fn visit_local_decl( @@ -335,7 +335,7 @@ macro_rules! make_mir_visitor { self.visit_span($(& $mutability)? *callsite_span); - let ty::Instance { def: callee_def, substs: callee_substs } = callee; + let ty::Instance { def: callee_def, args: callee_args } = callee; match callee_def { ty::InstanceDef::Item(_def_id) => {} @@ -355,7 +355,7 @@ macro_rules! make_mir_visitor { self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)); } } - self.visit_substs(callee_substs, location); + self.visit_args(callee_args, location); } if let Some(inlined_parent_scope) = inlined_parent_scope { self.visit_source_scope($(& $mutability)? *inlined_parent_scope); @@ -519,7 +519,7 @@ macro_rules! make_mir_visitor { destination, target: _, unwind: _, - from_hir_call: _, + call_source: _, fn_span: _ } => { self.visit_operand(func, location); @@ -650,9 +650,6 @@ macro_rules! make_mir_visitor { BorrowKind::Shallow => PlaceContext::NonMutatingUse( NonMutatingUseContext::ShallowBorrow ), - BorrowKind::Unique => PlaceContext::MutatingUse( - MutatingUseContext::Borrow - ), BorrowKind::Mut { .. } => PlaceContext::MutatingUse(MutatingUseContext::Borrow), }; @@ -724,24 +721,24 @@ macro_rules! make_mir_visitor { AggregateKind::Adt( _adt_def, _variant_index, - substs, - _user_substs, + args, + _user_args, _active_field_index ) => { - self.visit_substs(substs, location); + self.visit_args(args, location); } AggregateKind::Closure( _, - closure_substs + closure_args ) => { - self.visit_substs(closure_substs, location); + self.visit_args(closure_args, location); } AggregateKind::Generator( _, - generator_substs, + generator_args, _movability, ) => { - self.visit_substs(generator_substs, location); + self.visit_args(generator_args, location); } } @@ -936,7 +933,7 @@ macro_rules! make_mir_visitor { fn super_region(&mut self, _region: $(& $mutability)? ty::Region<'tcx>) { } - fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) { + fn super_args(&mut self, _args: & $($mutability)? GenericArgsRef<'tcx>) { } // Convenience methods @@ -1136,13 +1133,12 @@ macro_rules! visit_place_fns { fn visit_projection_elem( &mut self, - local: Local, - proj_base: &[PlaceElem<'tcx>], + place_ref: PlaceRef<'tcx>, elem: PlaceElem<'tcx>, context: PlaceContext, location: Location, ) { - self.super_projection_elem(local, proj_base, elem, context, location); + self.super_projection_elem(place_ref, elem, context, location); } fn super_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { @@ -1171,15 +1167,13 @@ macro_rules! visit_place_fns { location: Location, ) { for (base, elem) in place_ref.iter_projections().rev() { - let base_proj = base.projection; - self.visit_projection_elem(place_ref.local, base_proj, elem, context, location); + self.visit_projection_elem(base, elem, context, location); } } fn super_projection_elem( &mut self, - _local: Local, - _proj_base: &[PlaceElem<'tcx>], + _place_ref: PlaceRef<'tcx>, elem: PlaceElem<'tcx>, _context: PlaceContext, location: Location, diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index fd02a16130f..9bf02267005 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -55,6 +55,10 @@ impl<T> EraseType for &'_ ty::List<T> { type Result = [u8; size_of::<*const ()>()]; } +impl<I: rustc_index::Idx, T> EraseType for &'_ rustc_index::IndexSlice<I, T> { + type Result = [u8; size_of::<&'static rustc_index::IndexSlice<u32, ()>>()]; +} + impl<T> EraseType for Result<&'_ T, traits::query::NoSolution> { type Result = [u8; size_of::<Result<&'static (), traits::query::NoSolution>>()]; } @@ -67,8 +71,8 @@ impl<T> EraseType for Result<&'_ T, traits::CodegenObligationError> { type Result = [u8; size_of::<Result<&'static (), traits::CodegenObligationError>>()]; } -impl<T> EraseType for Result<&'_ T, ty::layout::FnAbiError<'_>> { - type Result = [u8; size_of::<Result<&'static (), ty::layout::FnAbiError<'static>>>()]; +impl<T> EraseType for Result<&'_ T, &'_ ty::layout::FnAbiError<'_>> { + type Result = [u8; size_of::<Result<&'static (), &'static ty::layout::FnAbiError<'static>>>()]; } impl<T> EraseType for Result<(&'_ T, rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed> { @@ -92,19 +96,26 @@ impl EraseType for Result<ty::GenericArg<'_>, traits::query::NoSolution> { type Result = [u8; size_of::<Result<ty::GenericArg<'static>, traits::query::NoSolution>>()]; } -impl EraseType for Result<bool, ty::layout::LayoutError<'_>> { - type Result = [u8; size_of::<Result<bool, ty::layout::LayoutError<'static>>>()]; +impl EraseType for Result<bool, &ty::layout::LayoutError<'_>> { + type Result = [u8; size_of::<Result<bool, &'static ty::layout::LayoutError<'static>>>()]; } -impl EraseType for Result<rustc_target::abi::TyAndLayout<'_, Ty<'_>>, ty::layout::LayoutError<'_>> { +impl EraseType + for Result<rustc_target::abi::TyAndLayout<'_, Ty<'_>>, &ty::layout::LayoutError<'_>> +{ type Result = [u8; size_of::< Result< rustc_target::abi::TyAndLayout<'static, Ty<'static>>, - ty::layout::LayoutError<'static>, + &'static ty::layout::LayoutError<'static>, >, >()]; } +impl EraseType for Result<ty::layout::TyAndNaiveLayout<'_>, &ty::layout::LayoutError<'_>> { + type Result = + [u8; size_of::<Result<ty::layout::TyAndNaiveLayout<'_>, &ty::layout::LayoutError<'_>>>()]; +} + impl EraseType for Result<ty::Const<'_>, mir::interpret::LitToConstError> { type Result = [u8; size_of::<Result<ty::Const<'static>, mir::interpret::LitToConstError>>()]; } @@ -285,6 +296,7 @@ trivial! { rustc_span::Symbol, rustc_span::symbol::Ident, rustc_target::spec::PanicStrategy, + rustc_target::abi::ReferenceNichePolicy, rustc_type_ir::Variance, u32, usize, @@ -309,7 +321,6 @@ tcx_lifetime! { rustc_middle::mir::interpret::ConstValue, rustc_middle::mir::interpret::GlobalId, rustc_middle::mir::interpret::LitToConstInput, - rustc_middle::traits::ChalkEnvironmentAndGoal, rustc_middle::traits::query::MethodAutoderefStepsResult, rustc_middle::traits::query::type_op::AscribeUserType, rustc_middle::traits::query::type_op::Eq, @@ -317,7 +328,7 @@ tcx_lifetime! { rustc_middle::traits::query::type_op::Subtype, rustc_middle::ty::AdtDef, rustc_middle::ty::AliasTy, - rustc_middle::ty::Clause, + rustc_middle::ty::ClauseKind, rustc_middle::ty::ClosureTypeInfo, rustc_middle::ty::Const, rustc_middle::ty::DestructuredConst, diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index fa62b7f32b1..a8aec3096d5 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -2,11 +2,12 @@ use crate::infer::canonical::Canonical; use crate::mir; +use crate::mir::interpret::ConstValue; use crate::traits; use crate::ty::fast_reject::SimplifiedType; use crate::ty::layout::{TyAndLayout, ValidityRequirement}; -use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::{self, Ty, TyCtxt}; +use crate::ty::{GenericArg, GenericArgsRef}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::hir_id::{HirId, OwnerId}; use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector}; @@ -285,7 +286,7 @@ impl Key for (DefId, SimplifiedType) { } } -impl<'tcx> Key for SubstsRef<'tcx> { +impl<'tcx> Key for GenericArgsRef<'tcx> { type CacheSelector = DefaultCacheSelector<Self>; fn default_span(&self, _: TyCtxt<'_>) -> Span { @@ -293,7 +294,7 @@ impl<'tcx> Key for SubstsRef<'tcx> { } } -impl<'tcx> Key for (DefId, SubstsRef<'tcx>) { +impl<'tcx> Key for (DefId, GenericArgsRef<'tcx>) { type CacheSelector = DefaultCacheSelector<Self>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { @@ -309,7 +310,7 @@ impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) { } } -impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) { +impl<'tcx> Key for (LocalDefId, DefId, GenericArgsRef<'tcx>) { type CacheSelector = DefaultCacheSelector<Self>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { @@ -317,11 +318,11 @@ impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) { } } -impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) { +impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) { type CacheSelector = DefaultCacheSelector<Self>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { - tcx.def_span(self.1.def_id()) + tcx.def_span(self.1.def_id) } } @@ -333,6 +334,14 @@ impl<'tcx> Key for (ty::Const<'tcx>, FieldIdx) { } } +impl<'tcx> Key for (ConstValue<'tcx>, Ty<'tcx>) { + type CacheSelector = DefaultCacheSelector<Self>; + + fn default_span(&self, _: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> { type CacheSelector = DefaultCacheSelector<Self>; @@ -420,7 +429,7 @@ impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) { } } -impl<'tcx> Key for &'tcx ty::List<ty::Predicate<'tcx>> { +impl<'tcx> Key for &'tcx ty::List<ty::Clause<'tcx>> { type CacheSelector = DefaultCacheSelector<Self>; fn default_span(&self, _: TyCtxt<'_>) -> Span { @@ -478,7 +487,7 @@ impl Key for (Symbol, u32, u32) { } } -impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) { +impl<'tcx> Key for (DefId, Ty<'tcx>, GenericArgsRef<'tcx>, ty::ParamEnv<'tcx>) { type CacheSelector = DefaultCacheSelector<Self>; fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index a6c8d41e925..b5b00b7b640 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -39,12 +39,11 @@ use crate::traits::query::{ }; use crate::traits::specialization_graph; use crate::traits::{ - CanonicalChalkEnvironmentAndGoal, CodegenObligationError, EvaluationResult, ImplSource, - ObjectSafetyViolation, ObligationCause, OverflowError, WellFormedLoc, + CodegenObligationError, EvaluationResult, ImplSource, ObjectSafetyViolation, ObligationCause, + OverflowError, WellFormedLoc, }; use crate::ty::fast_reject::SimplifiedType; use crate::ty::layout::ValidityRequirement; -use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::util::AlwaysRequiresDrop; use crate::ty::GeneratorDiagnosticData; use crate::ty::TyCtxtFeed; @@ -52,6 +51,7 @@ use crate::ty::{ self, print::describe_as_module, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, UnusedGenericParams, }; +use crate::ty::{GenericArg, GenericArgsRef}; use rustc_arena::TypedArena; use rustc_ast as ast; use rustc_ast::expand::{allocator::AllocatorKind, StrippedCfgItem}; @@ -346,7 +346,7 @@ rustc_queries! { /// `key` is the `DefId` of the associated type or opaque type. /// /// Bounds from the parent (e.g. with nested impl trait) are not included. - query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, Span)]> { + query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern @@ -373,7 +373,7 @@ rustc_queries! { /// ``` /// /// Bounds from the parent (e.g. with nested impl trait) are not included. - query item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> { + query item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Clause<'tcx>>> { desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } } @@ -531,6 +531,19 @@ rustc_queries! { } } + /// Returns names of captured upvars for closures and generators. + /// + /// Here are some examples: + /// - `name__field1__field2` when the upvar is captured by value. + /// - `_ref__name__field` when the upvar is captured by reference. + /// + /// For generators this only contains upvars that are shared by all states. + query closure_saved_names_of_captured_variables(def_id: DefId) -> &'tcx IndexVec<abi::FieldIdx, Symbol> { + arena_cache + desc { |tcx| "computing debuginfo for closure `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + query mir_generator_witnesses(key: DefId) -> &'tcx Option<mir::GeneratorLayout<'tcx>> { arena_cache desc { |tcx| "generator witness types for `{}`", tcx.def_path_str(key) } @@ -868,7 +881,7 @@ rustc_queries! { /// /// Note that we've liberated the late bound regions of function signatures, so /// this can not be used to check whether these types are well formed. - query assumed_wf_types(key: DefId) -> &'tcx ty::List<Ty<'tcx>> { + query assumed_wf_types(key: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] { desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) } } @@ -885,6 +898,10 @@ rustc_queries! { desc { |tcx| "linting {}", describe_as_module(key, tcx) } } + query check_unused_traits(_: ()) -> () { + desc { "checking unused trait imports in crate" } + } + /// Checks the attributes in the module. query check_mod_attrs(key: LocalDefId) -> () { desc { |tcx| "checking attributes in {}", describe_as_module(key, tcx) } @@ -1019,7 +1036,7 @@ rustc_queries! { } /// Obtain all the calls into other local functions - query mir_inliner_callees(key: ty::InstanceDef<'tcx>) -> &'tcx [(DefId, SubstsRef<'tcx>)] { + query mir_inliner_callees(key: ty::InstanceDef<'tcx>) -> &'tcx [(DefId, GenericArgsRef<'tcx>)] { fatal_cycle desc { |tcx| "computing all local function calls in `{}`", @@ -1074,11 +1091,13 @@ rustc_queries! { } /// Tries to destructure an `mir::ConstantKind` ADT or array into its variant index - /// and its field values. - query try_destructure_mir_constant( - key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>> + /// and its field values. This should only be used for pretty printing. + query try_destructure_mir_constant_for_diagnostics( + key: (ConstValue<'tcx>, Ty<'tcx>) ) -> Option<mir::DestructuredConstant<'tcx>> { desc { "destructuring MIR constant"} + no_hash + eval_always } query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> { @@ -1263,7 +1282,7 @@ rustc_queries! { } query codegen_select_candidate( - key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) + key: (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { cache_on_disk_if { true } desc { |tcx| "computing candidate for `{}`", key.1 } @@ -1370,18 +1389,30 @@ rustc_queries! { /// executes in "reveal all" mode, and will normalize the input type. query layout_of( key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> - ) -> Result<ty::layout::TyAndLayout<'tcx>, ty::layout::LayoutError<'tcx>> { + ) -> Result<ty::layout::TyAndLayout<'tcx>, &'tcx ty::layout::LayoutError<'tcx>> { depth_limit desc { "computing layout of `{}`", key.value } } + /// Computes the naive layout approximation of a type. Note that this implicitly + /// executes in "reveal all" mode, and will normalize the input type. + /// + /// Unlike `layout_of`, this doesn't look past references (beyond the `Pointee::Metadata` + /// projection), and as such can be called on generic types like `Option<&T>`. + query naive_layout_of( + key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> + ) -> Result<ty::layout::TyAndNaiveLayout<'tcx>, &'tcx ty::layout::LayoutError<'tcx>> { + depth_limit + desc { "computing layout (naive) of `{}`", key.value } + } + /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. /// /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance` /// instead, where the instance is an `InstanceDef::Virtual`. query fn_abi_of_fn_ptr( key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)> - ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> { + ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}` function pointers", key.value.0 } } @@ -1392,7 +1423,7 @@ rustc_queries! { /// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`). query fn_abi_of_instance( key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)> - ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> { + ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}`", key.value.0 } } @@ -1450,6 +1481,11 @@ rustc_queries! { desc { "getting a crate's configured panic-in-drop strategy" } separate_provide_extern } + query reference_niches_policy(_: CrateNum) -> abi::ReferenceNichePolicy { + fatal_cycle + desc { "getting a crate's policy for size and alignment niches of references" } + separate_provide_extern + } query is_no_builtins(_: CrateNum) -> bool { fatal_cycle desc { "getting whether a crate has `#![no_builtins]`" } @@ -1522,7 +1558,7 @@ rustc_queries! { /// added or removed in any upstream crate. Instead use the narrower /// `upstream_monomorphizations_for`, `upstream_drop_glue_for`, or, even /// better, `Instance::upstream_monomorphization()`. - query upstream_monomorphizations(_: ()) -> &'tcx DefIdMap<FxHashMap<SubstsRef<'tcx>, CrateNum>> { + query upstream_monomorphizations(_: ()) -> &'tcx DefIdMap<FxHashMap<GenericArgsRef<'tcx>, CrateNum>> { arena_cache desc { "collecting available upstream monomorphizations" } } @@ -1535,7 +1571,7 @@ rustc_queries! { /// You likely want to call `Instance::upstream_monomorphization()` /// instead of invoking this query directly. query upstream_monomorphizations_for(def_id: DefId) - -> Option<&'tcx FxHashMap<SubstsRef<'tcx>, CrateNum>> + -> Option<&'tcx FxHashMap<GenericArgsRef<'tcx>, CrateNum>> { desc { |tcx| "collecting available upstream monomorphizations for `{}`", @@ -1545,7 +1581,7 @@ rustc_queries! { } /// Returns the upstream crate that exports drop-glue for the given - /// type (`substs` is expected to be a single-item list containing the + /// type (`args` is expected to be a single-item list containing the /// type one wants drop-glue for). /// /// This is a subset of `upstream_monomorphizations_for` in order to @@ -1559,12 +1595,12 @@ rustc_queries! { /// NOTE: This query could easily be extended to also support other /// common functions that have are large set of monomorphizations /// (like `Clone::clone` for example). - query upstream_drop_glue_for(substs: SubstsRef<'tcx>) -> Option<CrateNum> { - desc { "available upstream drop-glue for `{:?}`", substs } + query upstream_drop_glue_for(args: GenericArgsRef<'tcx>) -> Option<CrateNum> { + desc { "available upstream drop-glue for `{:?}`", args } } /// Returns a list of all `extern` blocks of a crate. - query foreign_modules(_: CrateNum) -> &'tcx FxHashMap<DefId, ForeignModule> { + query foreign_modules(_: CrateNum) -> &'tcx FxIndexMap<DefId, ForeignModule> { arena_cache desc { "looking up the foreign modules of a linked crate" } separate_provide_extern @@ -1904,6 +1940,16 @@ rustc_queries! { } /// Do not call this query directly: invoke `normalize` instead. + query normalize_weak_ty( + goal: CanonicalProjectionGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{}`", goal.value.value } + } + + /// Do not call this query directly: invoke `normalize` instead. query normalize_inherent_projection_ty( goal: CanonicalProjectionGoal<'tcx> ) -> Result< @@ -1948,15 +1994,6 @@ rustc_queries! { desc { "evaluating trait selection obligation `{}`", goal.value.value } } - query evaluate_goal( - goal: CanonicalChalkEnvironmentAndGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, - NoSolution - > { - desc { "evaluating trait selection obligation `{}`", goal.value } - } - /// Do not call this query directly: part of the `Eq` type-op query type_op_ascribe_user_type( goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx> @@ -2008,10 +2045,10 @@ rustc_queries! { } /// Do not call this query directly: part of the `Normalize` type-op - query type_op_normalize_predicate( - goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Predicate<'tcx>> + query type_op_normalize_clause( + goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Clause<'tcx>> ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Predicate<'tcx>>>, + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Clause<'tcx>>>, NoSolution, > { desc { "normalizing `{:?}`", goal.value.value.value } @@ -2037,7 +2074,7 @@ rustc_queries! { desc { "normalizing `{:?}`", goal.value.value.value } } - query subst_and_check_impossible_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool { + query subst_and_check_impossible_predicates(key: (DefId, GenericArgsRef<'tcx>)) -> bool { desc { |tcx| "checking impossible substituted predicates: `{}`", tcx.def_path_str(key.0) @@ -2064,12 +2101,6 @@ rustc_queries! { desc { "looking up supported target features" } } - /// Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning. - query instance_def_size_estimate(def: ty::InstanceDef<'tcx>) - -> usize { - desc { |tcx| "estimating size for `{}`", tcx.def_path_str(def.def_id()) } - } - query features_query(_: ()) -> &'tcx rustc_feature::Features { feedable desc { "looking up enabled feature gates" } @@ -2088,21 +2119,21 @@ rustc_queries! { } /// Attempt to resolve the given `DefId` to an `Instance`, for the - /// given generics args (`SubstsRef`), returning one of: + /// given generics args (`GenericArgsRef`), returning one of: /// * `Ok(Some(instance))` on success - /// * `Ok(None)` when the `SubstsRef` are still too generic, + /// * `Ok(None)` when the `GenericArgsRef` are still too generic, /// and therefore don't allow finding the final `Instance` /// * `Err(ErrorGuaranteed)` when the `Instance` resolution process /// couldn't complete due to errors elsewhere - this is distinct /// from `Ok(None)` to avoid misleading diagnostics when an error /// has already been/will be emitted, for the original cause query resolve_instance( - key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)> + key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)> ) -> Result<Option<ty::Instance<'tcx>>, ErrorGuaranteed> { desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) } } - query reveal_opaque_types_in_bounds(key: &'tcx ty::List<ty::Predicate<'tcx>>) -> &'tcx ty::List<ty::Predicate<'tcx>> { + query reveal_opaque_types_in_bounds(key: &'tcx ty::List<ty::Clause<'tcx>>) -> &'tcx ty::List<ty::Clause<'tcx>> { desc { "revealing opaque types in `{:?}`", key } } @@ -2141,7 +2172,7 @@ rustc_queries! { separate_provide_extern } - query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result<bool, ty::layout::LayoutError<'tcx>> { + query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result<bool, &'tcx ty::layout::LayoutError<'tcx>> { desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 } } @@ -2183,6 +2214,10 @@ rustc_queries! { desc { "getting cfg-ed out item names" } separate_provide_extern } + + query generics_require_sized_self(def_id: DefId) -> bool { + desc { "check whether the item has a `where Self: Sized` bound" } + } } rustc_query_append! { define_callbacks! } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 220118ae5cc..995b2140f61 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -104,7 +104,9 @@ struct Footer { query_result_index: EncodedDepNodeIndex, side_effects_index: EncodedDepNodeIndex, // The location of all allocations. - interpret_alloc_index: Vec<u32>, + // Most uses only need values up to u32::MAX, but benchmarking indicates that we can use a u64 + // without measurable overhead. This permits larger const allocations without ICEing. + interpret_alloc_index: Vec<u64>, // See `OnDiskCache.syntax_contexts` syntax_contexts: FxHashMap<u32, AbsoluteBytePos>, // See `OnDiskCache.expn_data` @@ -301,7 +303,7 @@ impl<'sess> OnDiskCache<'sess> { interpret_alloc_index.reserve(new_n - n); for idx in n..new_n { let id = encoder.interpret_allocs[idx]; - let pos: u32 = encoder.position().try_into().unwrap(); + let pos: u64 = encoder.position().try_into().unwrap(); interpret_alloc_index.push(pos); interpret::specialized_encode_alloc_id(&mut encoder, tcx, id); } @@ -791,13 +793,6 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> } } -impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] { - #[inline] - fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { - RefDecodable::decode(d) - } -} - impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] { #[inline] fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 813e109c41e..e070b054720 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -18,9 +18,9 @@ use rustc_index::IndexVec; use rustc_middle::middle::region; use rustc_middle::mir::interpret::AllocId; use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Mutability, UnOp}; -use rustc_middle::ty::adjustment::PointerCast; -use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, AdtDef, FnSig, List, Ty, UpvarSubsts}; +use rustc_middle::ty::adjustment::PointerCoercion; +use rustc_middle::ty::GenericArgsRef; +use rustc_middle::ty::{self, AdtDef, FnSig, List, Ty, UpvarArgs}; use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation}; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span, Symbol, DUMMY_SP}; @@ -150,9 +150,9 @@ pub struct AdtExpr<'tcx> { pub adt_def: AdtDef<'tcx>, /// The variant of the ADT. pub variant_index: VariantIdx, - pub substs: SubstsRef<'tcx>, + pub args: GenericArgsRef<'tcx>, - /// Optional user-given substs: for something like `let x = + /// Optional user-given args: for something like `let x = /// Bar::<T> { ... }`. pub user_ty: UserTy<'tcx>, @@ -164,7 +164,7 @@ pub struct AdtExpr<'tcx> { #[derive(Clone, Debug, HashStable)] pub struct ClosureExpr<'tcx> { pub closure_id: LocalDefId, - pub substs: UpvarSubsts<'tcx>, + pub args: UpvarArgs<'tcx>, pub upvars: Box<[ExprId]>, pub movability: Option<hir::Movability>, pub fake_reads: Vec<(ExprId, FakeReadCause, hir::HirId)>, @@ -329,9 +329,10 @@ pub enum ExprKind<'tcx> { NeverToAny { source: ExprId, }, - /// A pointer cast. More information can be found in [`PointerCast`]. - Pointer { - cast: PointerCast, + /// A pointer coercion. More information can be found in [`PointerCoercion`]. + /// Pointer casts that cannot be done by coercions are represented by [`ExprKind::Cast`]. + PointerCoercion { + cast: PointerCoercion, source: ExprId, }, /// A `loop` expression. @@ -410,10 +411,14 @@ pub enum ExprKind<'tcx> { Return { value: Option<ExprId>, }, + /// A `become` expression. + Become { + value: ExprId, + }, /// An inline `const` block, e.g. `const {}`. ConstBlock { did: DefId, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, }, /// An array literal constructed from one repeated element, e.g. `[1; 5]`. Repeat { @@ -461,7 +466,7 @@ pub enum ExprKind<'tcx> { /// Associated constants and named constants NamedConst { def_id: DefId, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, user_ty: UserTy<'tcx>, }, ConstParam { @@ -709,7 +714,7 @@ pub enum PatKind<'tcx> { /// multiple variants. Variant { adt_def: AdtDef<'tcx>, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, variant_index: VariantIdx, subpatterns: Vec<FieldPat<'tcx>>, }, diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 5c7ec31cf93..55ec17423ec 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -65,7 +65,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp Cast { source } => visitor.visit_expr(&visitor.thir()[source]), Use { source } => visitor.visit_expr(&visitor.thir()[source]), NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]), - Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]), + PointerCoercion { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]), Let { expr, .. } => { visitor.visit_expr(&visitor.thir()[expr]); } @@ -100,7 +100,8 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp visitor.visit_expr(&visitor.thir()[value]) } } - ConstBlock { did: _, substs: _ } => {} + Become { value } => visitor.visit_expr(&visitor.thir()[value]), + ConstBlock { did: _, args: _ } => {} Repeat { value, count: _ } => { visitor.visit_expr(&visitor.thir()[value]); } @@ -114,7 +115,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp ref base, adt_def: _, variant_index: _, - substs: _, + args: _, user_ty: _, }) => { for field in &**fields { @@ -129,7 +130,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp } Closure(box ClosureExpr { closure_id: _, - substs: _, + args: _, upvars: _, movability: _, fake_reads: _, @@ -137,7 +138,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp Literal { lit: _, neg: _ } => {} NonHirLiteral { lit: _, user_ty: _ } => {} ZstLiteral { user_ty: _ } => {} - NamedConst { def_id: _, substs: _, user_ty: _ } => {} + NamedConst { def_id: _, args: _, user_ty: _ } => {} ConstParam { param: _, def_id: _ } => {} StaticRef { alloc_id: _, ty: _, def_id: _ } => {} InlineAsm(box InlineAsmExpr { ref operands, template: _, options: _, line_spans: _ }) => { @@ -226,7 +227,7 @@ pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<' name: _, } => visitor.visit_pat(&subpattern), Binding { .. } | Wild => {} - Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } | Leaf { subpatterns } => { + Variant { subpatterns, adt_def: _, args: _, variant_index: _ } | Leaf { subpatterns } => { for subpattern in subpatterns { visitor.visit_pat(&subpattern.pattern); } diff --git a/compiler/rustc_middle/src/traits/chalk.rs b/compiler/rustc_middle/src/traits/chalk.rs deleted file mode 100644 index fcc8f457a8b..00000000000 --- a/compiler/rustc_middle/src/traits/chalk.rs +++ /dev/null @@ -1,396 +0,0 @@ -//! Types required for Chalk-related queries -//! -//! The primary purpose of this file is defining an implementation for the -//! `chalk_ir::interner::Interner` trait. The primary purpose of this trait, as -//! its name suggest, is to provide an abstraction boundary for creating -//! interned Chalk types. - -use rustc_middle::ty::{self, AdtDef, TyCtxt}; - -use rustc_hir::def_id::DefId; -use rustc_target::spec::abi::Abi; - -use std::cmp::Ordering; -use std::fmt; -use std::hash::{Hash, Hasher}; - -#[derive(Copy, Clone)] -pub struct RustInterner<'tcx> { - pub tcx: TyCtxt<'tcx>, -} - -/// We don't ever actually need this. It's only required for derives. -impl<'tcx> Hash for RustInterner<'tcx> { - fn hash<H: Hasher>(&self, _state: &mut H) {} -} - -/// We don't ever actually need this. It's only required for derives. -impl<'tcx> Ord for RustInterner<'tcx> { - fn cmp(&self, _other: &Self) -> Ordering { - Ordering::Equal - } -} - -/// We don't ever actually need this. It's only required for derives. -impl<'tcx> PartialOrd for RustInterner<'tcx> { - fn partial_cmp(&self, _other: &Self) -> Option<Ordering> { - None - } -} - -/// We don't ever actually need this. It's only required for derives. -impl<'tcx> PartialEq for RustInterner<'tcx> { - fn eq(&self, _other: &Self) -> bool { - false - } -} - -/// We don't ever actually need this. It's only required for derives. -impl<'tcx> Eq for RustInterner<'tcx> {} - -impl fmt::Debug for RustInterner<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "RustInterner") - } -} - -// Right now, there is no interning at all. I was running into problems with -// adding interning in `ty/context.rs` for Chalk types with -// `parallel-compiler = true`. -jackh726 -impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> { - type InternedType = Box<chalk_ir::TyData<Self>>; - type InternedLifetime = Box<chalk_ir::LifetimeData<Self>>; - type InternedConst = Box<chalk_ir::ConstData<Self>>; - type InternedConcreteConst = ty::ValTree<'tcx>; - type InternedGenericArg = Box<chalk_ir::GenericArgData<Self>>; - type InternedGoal = Box<chalk_ir::GoalData<Self>>; - type InternedGoals = Vec<chalk_ir::Goal<Self>>; - type InternedSubstitution = Vec<chalk_ir::GenericArg<Self>>; - type InternedProgramClause = Box<chalk_ir::ProgramClauseData<Self>>; - type InternedProgramClauses = Vec<chalk_ir::ProgramClause<Self>>; - type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; - type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>; - type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>; - type InternedVariances = Vec<chalk_ir::Variance>; - type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>; - type DefId = DefId; - type InternedAdtId = AdtDef<'tcx>; - type Identifier = (); - type FnAbi = Abi; - - fn debug_program_clause_implication( - pci: &chalk_ir::ProgramClauseImplication<Self>, - fmt: &mut fmt::Formatter<'_>, - ) -> Option<fmt::Result> { - let mut write = || { - write!(fmt, "{:?}", pci.consequence)?; - - let conditions = pci.conditions.interned(); - let constraints = pci.constraints.interned(); - - let conds = conditions.len(); - let consts = constraints.len(); - if conds == 0 && consts == 0 { - return Ok(()); - } - - write!(fmt, " :- ")?; - - if conds != 0 { - for cond in &conditions[..conds - 1] { - write!(fmt, "{:?}, ", cond)?; - } - write!(fmt, "{:?}", conditions[conds - 1])?; - } - - if conds != 0 && consts != 0 { - write!(fmt, " ; ")?; - } - - if consts != 0 { - for constraint in &constraints[..consts - 1] { - write!(fmt, "{:?}, ", constraint)?; - } - write!(fmt, "{:?}", constraints[consts - 1])?; - } - - Ok(()) - }; - Some(write()) - } - - fn debug_substitution( - substitution: &chalk_ir::Substitution<Self>, - fmt: &mut fmt::Formatter<'_>, - ) -> Option<fmt::Result> { - Some(write!(fmt, "{:?}", substitution.interned())) - } - - fn debug_separator_trait_ref( - separator_trait_ref: &chalk_ir::SeparatorTraitRef<'_, Self>, - fmt: &mut fmt::Formatter<'_>, - ) -> Option<fmt::Result> { - let substitution = &separator_trait_ref.trait_ref.substitution; - let parameters = substitution.interned(); - Some(write!( - fmt, - "{:?}{}{:?}{:?}", - parameters[0], - separator_trait_ref.separator, - separator_trait_ref.trait_ref.trait_id, - chalk_ir::debug::Angle(¶meters[1..]) - )) - } - - fn debug_quantified_where_clauses( - clauses: &chalk_ir::QuantifiedWhereClauses<Self>, - fmt: &mut fmt::Formatter<'_>, - ) -> Option<fmt::Result> { - Some(write!(fmt, "{:?}", clauses.interned())) - } - - fn debug_ty(ty: &chalk_ir::Ty<Self>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { - match &ty.interned().kind { - chalk_ir::TyKind::Ref(chalk_ir::Mutability::Not, lifetime, ty) => { - Some(write!(fmt, "(&{:?} {:?})", lifetime, ty)) - } - chalk_ir::TyKind::Ref(chalk_ir::Mutability::Mut, lifetime, ty) => { - Some(write!(fmt, "(&{:?} mut {:?})", lifetime, ty)) - } - chalk_ir::TyKind::Array(ty, len) => Some(write!(fmt, "[{:?}; {:?}]", ty, len)), - chalk_ir::TyKind::Slice(ty) => Some(write!(fmt, "[{:?}]", ty)), - chalk_ir::TyKind::Tuple(len, substs) => Some( - try { - write!(fmt, "(")?; - for (idx, substitution) in substs.interned().iter().enumerate() { - if idx == *len && *len != 1 { - // Don't add a trailing comma if the tuple has more than one element - write!(fmt, "{:?}", substitution)?; - } else { - write!(fmt, "{:?},", substitution)?; - } - } - write!(fmt, ")")?; - }, - ), - _ => None, - } - } - - fn debug_alias( - alias_ty: &chalk_ir::AliasTy<Self>, - fmt: &mut fmt::Formatter<'_>, - ) -> Option<fmt::Result> { - match alias_ty { - chalk_ir::AliasTy::Projection(projection_ty) => { - Self::debug_projection_ty(projection_ty, fmt) - } - chalk_ir::AliasTy::Opaque(opaque_ty) => Self::debug_opaque_ty(opaque_ty, fmt), - } - } - - fn debug_projection_ty( - projection_ty: &chalk_ir::ProjectionTy<Self>, - fmt: &mut fmt::Formatter<'_>, - ) -> Option<fmt::Result> { - Some(write!( - fmt, - "projection: {:?} {:?}", - projection_ty.associated_ty_id, projection_ty.substitution, - )) - } - - fn debug_opaque_ty( - opaque_ty: &chalk_ir::OpaqueTy<Self>, - fmt: &mut fmt::Formatter<'_>, - ) -> Option<fmt::Result> { - Some(write!(fmt, "{:?}", opaque_ty.opaque_ty_id)) - } - - fn intern_ty(self, ty: chalk_ir::TyKind<Self>) -> Self::InternedType { - let flags = ty.compute_flags(self); - Box::new(chalk_ir::TyData { kind: ty, flags: flags }) - } - - fn ty_data(self, ty: &Self::InternedType) -> &chalk_ir::TyData<Self> { - ty - } - - fn intern_lifetime(self, lifetime: chalk_ir::LifetimeData<Self>) -> Self::InternedLifetime { - Box::new(lifetime) - } - - fn lifetime_data(self, lifetime: &Self::InternedLifetime) -> &chalk_ir::LifetimeData<Self> { - &lifetime - } - - fn intern_const(self, constant: chalk_ir::ConstData<Self>) -> Self::InternedConst { - Box::new(constant) - } - - fn const_data(self, constant: &Self::InternedConst) -> &chalk_ir::ConstData<Self> { - &constant - } - - fn const_eq( - self, - _ty: &Self::InternedType, - c1: &Self::InternedConcreteConst, - c2: &Self::InternedConcreteConst, - ) -> bool { - c1 == c2 - } - - fn intern_generic_arg(self, data: chalk_ir::GenericArgData<Self>) -> Self::InternedGenericArg { - Box::new(data) - } - - fn generic_arg_data(self, data: &Self::InternedGenericArg) -> &chalk_ir::GenericArgData<Self> { - &data - } - - fn intern_goal(self, goal: chalk_ir::GoalData<Self>) -> Self::InternedGoal { - Box::new(goal) - } - - fn goal_data(self, goal: &Self::InternedGoal) -> &chalk_ir::GoalData<Self> { - &goal - } - - fn intern_goals<E>( - self, - data: impl IntoIterator<Item = Result<chalk_ir::Goal<Self>, E>>, - ) -> Result<Self::InternedGoals, E> { - data.into_iter().collect::<Result<Vec<_>, _>>() - } - - fn goals_data(self, goals: &Self::InternedGoals) -> &[chalk_ir::Goal<Self>] { - goals - } - - fn intern_substitution<E>( - self, - data: impl IntoIterator<Item = Result<chalk_ir::GenericArg<Self>, E>>, - ) -> Result<Self::InternedSubstitution, E> { - data.into_iter().collect::<Result<Vec<_>, _>>() - } - - fn substitution_data( - self, - substitution: &Self::InternedSubstitution, - ) -> &[chalk_ir::GenericArg<Self>] { - substitution - } - - fn intern_program_clause( - self, - data: chalk_ir::ProgramClauseData<Self>, - ) -> Self::InternedProgramClause { - Box::new(data) - } - - fn program_clause_data( - self, - clause: &Self::InternedProgramClause, - ) -> &chalk_ir::ProgramClauseData<Self> { - &clause - } - - fn intern_program_clauses<E>( - self, - data: impl IntoIterator<Item = Result<chalk_ir::ProgramClause<Self>, E>>, - ) -> Result<Self::InternedProgramClauses, E> { - data.into_iter().collect::<Result<Vec<_>, _>>() - } - - fn program_clauses_data( - self, - clauses: &Self::InternedProgramClauses, - ) -> &[chalk_ir::ProgramClause<Self>] { - clauses - } - - fn intern_quantified_where_clauses<E>( - self, - data: impl IntoIterator<Item = Result<chalk_ir::QuantifiedWhereClause<Self>, E>>, - ) -> Result<Self::InternedQuantifiedWhereClauses, E> { - data.into_iter().collect::<Result<Vec<_>, _>>() - } - - fn quantified_where_clauses_data( - self, - clauses: &Self::InternedQuantifiedWhereClauses, - ) -> &[chalk_ir::QuantifiedWhereClause<Self>] { - clauses - } - - fn intern_generic_arg_kinds<E>( - self, - data: impl IntoIterator<Item = Result<chalk_ir::VariableKind<Self>, E>>, - ) -> Result<Self::InternedVariableKinds, E> { - data.into_iter().collect::<Result<Vec<_>, _>>() - } - - fn variable_kinds_data( - self, - parameter_kinds: &Self::InternedVariableKinds, - ) -> &[chalk_ir::VariableKind<Self>] { - parameter_kinds - } - - fn intern_canonical_var_kinds<E>( - self, - data: impl IntoIterator<Item = Result<chalk_ir::CanonicalVarKind<Self>, E>>, - ) -> Result<Self::InternedCanonicalVarKinds, E> { - data.into_iter().collect::<Result<Vec<_>, _>>() - } - - fn canonical_var_kinds_data( - self, - canonical_var_kinds: &Self::InternedCanonicalVarKinds, - ) -> &[chalk_ir::CanonicalVarKind<Self>] { - canonical_var_kinds - } - - fn intern_constraints<E>( - self, - data: impl IntoIterator<Item = Result<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>, E>>, - ) -> Result<Self::InternedConstraints, E> { - data.into_iter().collect::<Result<Vec<_>, _>>() - } - - fn constraints_data( - self, - constraints: &Self::InternedConstraints, - ) -> &[chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>] { - constraints - } - - fn intern_variances<E>( - self, - data: impl IntoIterator<Item = Result<chalk_ir::Variance, E>>, - ) -> Result<Self::InternedVariances, E> { - data.into_iter().collect::<Result<Vec<_>, _>>() - } - - fn variances_data(self, variances: &Self::InternedVariances) -> &[chalk_ir::Variance] { - variances - } -} - -impl<'tcx> chalk_ir::interner::HasInterner for RustInterner<'tcx> { - type Interner = Self; -} - -/// A chalk environment and goal. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, TypeVisitable)] -pub struct ChalkEnvironmentAndGoal<'tcx> { - pub environment: &'tcx ty::List<ty::Predicate<'tcx>>, - pub goal: ty::Predicate<'tcx>, -} - -impl<'tcx> fmt::Display for ChalkEnvironmentAndGoal<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "environment: {:?}, goal: {}", self.environment, self.goal) - } -} diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index bf3872e81d4..b7ffed57a0b 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -2,7 +2,6 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html -mod chalk; pub mod query; pub mod select; pub mod solve; @@ -13,7 +12,7 @@ pub mod util; use crate::infer::canonical::Canonical; use crate::mir::ConstraintCategory; use crate::ty::abstract_const::NotConstEvaluatable; -use crate::ty::subst::SubstsRef; +use crate::ty::GenericArgsRef; use crate::ty::{self, AdtKind, Ty, TyCtxt}; use rustc_data_structures::sync::Lrc; @@ -30,12 +29,8 @@ use std::hash::{Hash, Hasher}; pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache}; -pub type CanonicalChalkEnvironmentAndGoal<'tcx> = Canonical<'tcx, ChalkEnvironmentAndGoal<'tcx>>; - pub use self::ObligationCauseCode::*; -pub use self::chalk::{ChalkEnvironmentAndGoal, RustInterner as ChalkRustInterner}; - /// Depending on the stage of compilation, we want projection to be /// more or less conservative. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable, Encodable, Decodable)] @@ -204,7 +199,7 @@ impl<'tcx> ObligationCause<'tcx> { pub struct UnifyReceiverContext<'tcx> { pub assoc_item: ty::AssocItem, pub param_env: ty::ParamEnv<'tcx>, - pub substs: SubstsRef<'tcx>, + pub args: GenericArgsRef<'tcx>, } #[derive(Clone, PartialEq, Eq, Lift, Default, HashStable)] @@ -448,6 +443,9 @@ pub enum ObligationCauseCode<'tcx> { /// Requirement for a `const N: Ty` to implement `Ty: ConstParamTy` ConstParam(Ty<'tcx>), + + /// Obligations emitted during the normalization of a weak type alias. + TypeAlias(InternedObligationCauseCode<'tcx>, Span, DefId), } /// The 'location' at which we try to perform HIR-based wf checking. @@ -590,6 +588,10 @@ pub enum SelectionError<'tcx> { /// Signaling that an error has already been emitted, to avoid /// multiple errors being shown. ErrorReporting, + /// Computing an opaque type's hidden type caused an error (e.g. a cycle error). + /// We can thus not know whether the hidden type implements an auto trait, so + /// we should not presume anything about it. + OpaqueTypeAutoTraitLeakageUnknown(DefId), } #[derive(Clone, Debug, TypeVisitable, Lift)] @@ -643,12 +645,6 @@ pub enum ImplSource<'tcx, N> { /// ImplSource identifying a particular impl. UserDefined(ImplSourceUserDefinedData<'tcx, N>), - /// ImplSource for auto trait implementations. - /// This carries the information and nested obligations with regards - /// to an auto implementation for a trait `Trait`. The nested obligations - /// ensure the trait implementation holds for all the constituent types. - AutoImpl(ImplSourceAutoImplData<N>), - /// Successful resolution to an obligation provided by the caller /// for some type parameter. The `Vec<N>` represents the /// obligations incurred from normalizing the where-clause (if @@ -656,84 +652,40 @@ pub enum ImplSource<'tcx, N> { Param(Vec<N>, ty::BoundConstness), /// Virtual calls through an object. - Object(ImplSourceObjectData<'tcx, N>), + Object(ImplSourceObjectData<N>), /// Successful resolution for a builtin trait. - Builtin(ImplSourceBuiltinData<N>), + Builtin(Vec<N>), /// ImplSource for trait upcasting coercion - TraitUpcasting(ImplSourceTraitUpcastingData<'tcx, N>), - - /// ImplSource automatically generated for a closure. The `DefId` is the ID - /// of the closure expression. This is an `ImplSource::UserDefined` in spirit, but the - /// impl is generated by the compiler and does not appear in the source. - Closure(ImplSourceClosureData<'tcx, N>), - - /// Same as above, but for a function pointer type with the given signature. - FnPointer(ImplSourceFnPointerData<'tcx, N>), - - /// ImplSource automatically generated for a generator. - Generator(ImplSourceGeneratorData<'tcx, N>), - - /// ImplSource automatically generated for a generator backing an async future. - Future(ImplSourceFutureData<'tcx, N>), - - /// ImplSource for a trait alias. - TraitAlias(ImplSourceTraitAliasData<'tcx, N>), - - /// ImplSource for a `const Drop` implementation. - ConstDestruct(ImplSourceConstDestructData<N>), + TraitUpcasting(ImplSourceTraitUpcastingData<N>), } impl<'tcx, N> ImplSource<'tcx, N> { pub fn nested_obligations(self) -> Vec<N> { match self { ImplSource::UserDefined(i) => i.nested, - ImplSource::Param(n, _) => n, - ImplSource::Builtin(i) => i.nested, - ImplSource::AutoImpl(d) => d.nested, - ImplSource::Closure(c) => c.nested, - ImplSource::Generator(c) => c.nested, - ImplSource::Future(c) => c.nested, + ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, ImplSource::Object(d) => d.nested, - ImplSource::FnPointer(d) => d.nested, - ImplSource::TraitAlias(d) => d.nested, ImplSource::TraitUpcasting(d) => d.nested, - ImplSource::ConstDestruct(i) => i.nested, } } pub fn borrow_nested_obligations(&self) -> &[N] { match self { ImplSource::UserDefined(i) => &i.nested, - ImplSource::Param(n, _) => n, - ImplSource::Builtin(i) => &i.nested, - ImplSource::AutoImpl(d) => &d.nested, - ImplSource::Closure(c) => &c.nested, - ImplSource::Generator(c) => &c.nested, - ImplSource::Future(c) => &c.nested, + ImplSource::Param(n, _) | ImplSource::Builtin(n) => &n, ImplSource::Object(d) => &d.nested, - ImplSource::FnPointer(d) => &d.nested, - ImplSource::TraitAlias(d) => &d.nested, ImplSource::TraitUpcasting(d) => &d.nested, - ImplSource::ConstDestruct(i) => &i.nested, } } pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] { match self { ImplSource::UserDefined(i) => &mut i.nested, - ImplSource::Param(n, _) => n, - ImplSource::Builtin(i) => &mut i.nested, - ImplSource::AutoImpl(d) => &mut d.nested, - ImplSource::Closure(c) => &mut c.nested, - ImplSource::Generator(c) => &mut c.nested, - ImplSource::Future(c) => &mut c.nested, + ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, ImplSource::Object(d) => &mut d.nested, - ImplSource::FnPointer(d) => &mut d.nested, - ImplSource::TraitAlias(d) => &mut d.nested, ImplSource::TraitUpcasting(d) => &mut d.nested, - ImplSource::ConstDestruct(i) => &mut i.nested, } } @@ -744,58 +696,21 @@ impl<'tcx, N> ImplSource<'tcx, N> { match self { ImplSource::UserDefined(i) => ImplSource::UserDefined(ImplSourceUserDefinedData { impl_def_id: i.impl_def_id, - substs: i.substs, + args: i.args, nested: i.nested.into_iter().map(f).collect(), }), ImplSource::Param(n, ct) => ImplSource::Param(n.into_iter().map(f).collect(), ct), - ImplSource::Builtin(i) => ImplSource::Builtin(ImplSourceBuiltinData { - nested: i.nested.into_iter().map(f).collect(), - }), + ImplSource::Builtin(n) => ImplSource::Builtin(n.into_iter().map(f).collect()), ImplSource::Object(o) => ImplSource::Object(ImplSourceObjectData { - upcast_trait_ref: o.upcast_trait_ref, vtable_base: o.vtable_base, nested: o.nested.into_iter().map(f).collect(), }), - ImplSource::AutoImpl(d) => ImplSource::AutoImpl(ImplSourceAutoImplData { - trait_def_id: d.trait_def_id, - nested: d.nested.into_iter().map(f).collect(), - }), - ImplSource::Closure(c) => ImplSource::Closure(ImplSourceClosureData { - closure_def_id: c.closure_def_id, - substs: c.substs, - nested: c.nested.into_iter().map(f).collect(), - }), - ImplSource::Generator(c) => ImplSource::Generator(ImplSourceGeneratorData { - generator_def_id: c.generator_def_id, - substs: c.substs, - nested: c.nested.into_iter().map(f).collect(), - }), - ImplSource::Future(c) => ImplSource::Future(ImplSourceFutureData { - generator_def_id: c.generator_def_id, - substs: c.substs, - nested: c.nested.into_iter().map(f).collect(), - }), - ImplSource::FnPointer(p) => ImplSource::FnPointer(ImplSourceFnPointerData { - fn_ty: p.fn_ty, - nested: p.nested.into_iter().map(f).collect(), - }), - ImplSource::TraitAlias(d) => ImplSource::TraitAlias(ImplSourceTraitAliasData { - alias_def_id: d.alias_def_id, - substs: d.substs, - nested: d.nested.into_iter().map(f).collect(), - }), ImplSource::TraitUpcasting(d) => { ImplSource::TraitUpcasting(ImplSourceTraitUpcastingData { - upcast_trait_ref: d.upcast_trait_ref, vtable_vptr_slot: d.vtable_vptr_slot, nested: d.nested.into_iter().map(f).collect(), }) } - ImplSource::ConstDestruct(i) => { - ImplSource::ConstDestruct(ImplSourceConstDestructData { - nested: i.nested.into_iter().map(f).collect(), - }) - } } } } @@ -814,53 +729,13 @@ impl<'tcx, N> ImplSource<'tcx, N> { #[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceUserDefinedData<'tcx, N> { pub impl_def_id: DefId, - pub substs: SubstsRef<'tcx>, - pub nested: Vec<N>, -} - -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceGeneratorData<'tcx, N> { - pub generator_def_id: DefId, - pub substs: SubstsRef<'tcx>, - /// Nested obligations. This can be non-empty if the generator - /// signature contains associated types. - pub nested: Vec<N>, -} - -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceFutureData<'tcx, N> { - pub generator_def_id: DefId, - pub substs: SubstsRef<'tcx>, - /// Nested obligations. This can be non-empty if the generator - /// signature contains associated types. - pub nested: Vec<N>, -} - -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceClosureData<'tcx, N> { - pub closure_def_id: DefId, - pub substs: SubstsRef<'tcx>, - /// Nested obligations. This can be non-empty if the closure - /// signature contains associated types. - pub nested: Vec<N>, -} - -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceAutoImplData<N> { - pub trait_def_id: DefId, + pub args: GenericArgsRef<'tcx>, pub nested: Vec<N>, } #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] #[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceTraitUpcastingData<'tcx, N> { - /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`. - pub upcast_trait_ref: ty::PolyTraitRef<'tcx>, - +pub struct ImplSourceTraitUpcastingData<N> { /// The vtable is formed by concatenating together the method lists of /// the base object trait and all supertraits, pointers to supertrait vtable will /// be provided when necessary; this is the position of `upcast_trait_ref`'s vtable @@ -870,18 +745,9 @@ pub struct ImplSourceTraitUpcastingData<'tcx, N> { pub nested: Vec<N>, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceBuiltinData<N> { - pub nested: Vec<N>, -} - #[derive(PartialEq, Eq, Clone, TyEncodable, TyDecodable, HashStable, Lift)] #[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceObjectData<'tcx, N> { - /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`. - pub upcast_trait_ref: ty::PolyTraitRef<'tcx>, - +pub struct ImplSourceObjectData<N> { /// The vtable is formed by concatenating together the method lists of /// the base object trait and all supertraits, pointers to supertrait vtable will /// be provided when necessary; this is the start of `upcast_trait_ref`'s methods @@ -891,27 +757,6 @@ pub struct ImplSourceObjectData<'tcx, N> { pub nested: Vec<N>, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceFnPointerData<'tcx, N> { - pub fn_ty: Ty<'tcx>, - pub nested: Vec<N>, -} - -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceConstDestructData<N> { - pub nested: Vec<N>, -} - -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceTraitAliasData<'tcx, N> { - pub alias_def_id: DefId, - pub substs: SubstsRef<'tcx>, - pub nested: Vec<N>, -} - #[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)] pub enum ObjectSafetyViolation { /// `Self: Sized` declared on the trait. @@ -1112,7 +957,7 @@ pub enum CodegenObligationError { FulfillmentError, } -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] pub enum DefiningAnchor { /// `DefId` of the item. Bind(LocalDefId), diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index eae5a280e11..950a59e9695 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -8,7 +8,7 @@ use crate::error::DropCheckOverflow; use crate::infer::canonical::{Canonical, QueryResponse}; use crate::ty::error::TypeError; -use crate::ty::subst::GenericArg; +use crate::ty::GenericArg; use crate::ty::{self, Ty, TyCtxt}; use rustc_span::source_map::Span; @@ -92,7 +92,7 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> = pub type CanonicalTypeOpNormalizeGoal<'tcx, T> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>; -#[derive(Copy, Clone, Debug, HashStable, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, HashStable, PartialEq, Eq)] pub struct NoSolution; impl<'tcx> From<TypeError<'tcx>> for NoSolution { @@ -132,7 +132,7 @@ impl<'tcx> DropckOutlivesResult<'tcx> { pub struct DropckConstraint<'tcx> { /// Types that are required to be alive in order for this /// type to be valid for destruction. - pub outlives: Vec<ty::subst::GenericArg<'tcx>>, + pub outlives: Vec<ty::GenericArg<'tcx>>, /// Types that could not be resolved: projections and params. pub dtorck_types: Vec<Ty<'tcx>>, diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 2c5b64a59cd..73b332fd8ec 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -11,6 +11,8 @@ use crate::ty::{ TypeVisitor, }; +pub mod inspect; + pub type EvaluationCache<'tcx> = Cache<CanonicalInput<'tcx>, QueryResult<'tcx>>; /// A goal is a statement, i.e. `predicate`, we want to prove @@ -18,7 +20,7 @@ pub type EvaluationCache<'tcx> = Cache<CanonicalInput<'tcx>, QueryResult<'tcx>>; /// /// Most of the time the `param_env` contains the `where`-bounds of the function /// we're currently typechecking while the `predicate` is some trait bound. -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct Goal<'tcx, P> { pub predicate: P, pub param_env: ty::ParamEnv<'tcx>, @@ -39,7 +41,7 @@ impl<'tcx, P> Goal<'tcx, P> { } } -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct Response<'tcx> { pub certainty: Certainty, pub var_values: CanonicalVarValues<'tcx>, @@ -47,7 +49,7 @@ pub struct Response<'tcx> { pub external_constraints: ExternalConstraints<'tcx>, } -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] pub enum Certainty { Yes, Maybe(MaybeCause), @@ -86,7 +88,7 @@ impl Certainty { } /// Why we failed to evaluate a goal. -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] pub enum MaybeCause { /// We failed due to ambiguity. This ambiguity can either /// be a true ambiguity, i.e. there are multiple different answers, @@ -96,7 +98,7 @@ pub enum MaybeCause { Overflow, } -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct QueryInput<'tcx, T> { pub goal: Goal<'tcx, T>, pub anchor: DefiningAnchor, @@ -104,12 +106,12 @@ pub struct QueryInput<'tcx, T> { } /// Additional constraints returned on success. -#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)] +#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default)] pub struct PredefinedOpaquesData<'tcx> { pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>, } -#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] +#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, HashStable)] pub struct PredefinedOpaques<'tcx>(pub(crate) Interned<'tcx, PredefinedOpaquesData<'tcx>>); impl<'tcx> std::ops::Deref for PredefinedOpaques<'tcx> { @@ -132,7 +134,7 @@ pub type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>; /// solver, merge the two responses again. pub type QueryResult<'tcx> = Result<CanonicalResponse<'tcx>, NoSolution>; -#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] +#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, HashStable)] pub struct ExternalConstraints<'tcx>(pub(crate) Interned<'tcx, ExternalConstraintsData<'tcx>>); impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> { @@ -144,7 +146,7 @@ impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> { } /// Additional constraints returned on success. -#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)] +#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default)] pub struct ExternalConstraintsData<'tcx> { // FIXME: implement this. pub region_constraints: QueryRegionConstraints<'tcx>, @@ -226,3 +228,9 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> { self.opaque_types.visit_with(visitor) } } + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)] +pub enum IsNormalizesToHack { + Yes, + No, +} diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs new file mode 100644 index 00000000000..8698cf86022 --- /dev/null +++ b/compiler/rustc_middle/src/traits/solve/inspect.rs @@ -0,0 +1,83 @@ +use super::{ + CanonicalInput, Certainty, Goal, IsNormalizesToHack, NoSolution, QueryInput, QueryResult, +}; +use crate::ty; +use format::ProofTreeFormatter; +use std::fmt::{Debug, Write}; + +mod format; + +#[derive(Eq, PartialEq, Debug, Hash, HashStable)] +pub enum CacheHit { + Provisional, + Global, +} + +#[derive(Eq, PartialEq, Hash, HashStable)] +pub struct GoalEvaluation<'tcx> { + pub uncanonicalized_goal: Goal<'tcx, ty::Predicate<'tcx>>, + pub canonicalized_goal: CanonicalInput<'tcx>, + + pub kind: GoalEvaluationKind<'tcx>, + pub is_normalizes_to_hack: IsNormalizesToHack, + pub returned_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>, + + pub result: QueryResult<'tcx>, +} + +#[derive(Eq, PartialEq, Hash, HashStable)] +pub enum GoalEvaluationKind<'tcx> { + CacheHit(CacheHit), + Uncached { revisions: Vec<GoalEvaluationStep<'tcx>> }, +} +impl Debug for GoalEvaluation<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + ProofTreeFormatter::new(f).format_goal_evaluation(self) + } +} + +#[derive(Eq, PartialEq, Hash, HashStable)] +pub struct AddedGoalsEvaluation<'tcx> { + pub evaluations: Vec<Vec<GoalEvaluation<'tcx>>>, + pub result: Result<Certainty, NoSolution>, +} +impl Debug for AddedGoalsEvaluation<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + ProofTreeFormatter::new(f).format_nested_goal_evaluation(self) + } +} + +#[derive(Eq, PartialEq, Hash, HashStable)] +pub struct GoalEvaluationStep<'tcx> { + pub instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>, + + pub nested_goal_evaluations: Vec<AddedGoalsEvaluation<'tcx>>, + pub candidates: Vec<GoalCandidate<'tcx>>, + + pub result: QueryResult<'tcx>, +} +impl Debug for GoalEvaluationStep<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + ProofTreeFormatter::new(f).format_evaluation_step(self) + } +} + +#[derive(Eq, PartialEq, Hash, HashStable)] +pub struct GoalCandidate<'tcx> { + pub nested_goal_evaluations: Vec<AddedGoalsEvaluation<'tcx>>, + pub candidates: Vec<GoalCandidate<'tcx>>, + pub kind: CandidateKind<'tcx>, +} + +#[derive(Eq, PartialEq, Debug, Hash, HashStable)] +pub enum CandidateKind<'tcx> { + /// Probe entered when normalizing the self ty during candidate assembly + NormalizedSelfTyAssembly, + /// A normal candidate for proving a goal + Candidate { name: String, result: QueryResult<'tcx> }, +} +impl Debug for GoalCandidate<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + ProofTreeFormatter::new(f).format_candidate(self) + } +} diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs new file mode 100644 index 00000000000..f19f1189e44 --- /dev/null +++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs @@ -0,0 +1,137 @@ +use super::*; + +pub(super) struct ProofTreeFormatter<'a, 'b> { + f: &'a mut (dyn Write + 'b), +} + +/// A formatter which adds 4 spaces of indentation to its input before +/// passing it on to its nested formatter. +/// +/// We can use this for arbitrary levels of indentation by nesting it. +struct Indentor<'a, 'b> { + f: &'a mut (dyn Write + 'b), + on_newline: bool, +} + +impl Write for Indentor<'_, '_> { + fn write_str(&mut self, s: &str) -> std::fmt::Result { + for line in s.split_inclusive("\n") { + if self.on_newline { + self.f.write_str(" ")?; + } + self.on_newline = line.ends_with("\n"); + self.f.write_str(line)?; + } + + Ok(()) + } +} + +impl<'a, 'b> ProofTreeFormatter<'a, 'b> { + pub(super) fn new(f: &'a mut (dyn Write + 'b)) -> Self { + ProofTreeFormatter { f } + } + + fn nested<F, R>(&mut self, func: F) -> R + where + F: FnOnce(&mut ProofTreeFormatter<'_, '_>) -> R, + { + func(&mut ProofTreeFormatter { f: &mut Indentor { f: self.f, on_newline: true } }) + } + + pub(super) fn format_goal_evaluation(&mut self, goal: &GoalEvaluation<'_>) -> std::fmt::Result { + let goal_text = match goal.is_normalizes_to_hack { + IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL", + IsNormalizesToHack::No => "GOAL", + }; + + writeln!(self.f, "{}: {:?}", goal_text, goal.uncanonicalized_goal)?; + writeln!(self.f, "CANONICALIZED: {:?}", goal.canonicalized_goal)?; + + match &goal.kind { + GoalEvaluationKind::CacheHit(CacheHit::Global) => { + writeln!(self.f, "GLOBAL CACHE HIT: {:?}", goal.result) + } + GoalEvaluationKind::CacheHit(CacheHit::Provisional) => { + writeln!(self.f, "PROVISIONAL CACHE HIT: {:?}", goal.result) + } + GoalEvaluationKind::Uncached { revisions } => { + for (n, step) in revisions.iter().enumerate() { + writeln!(self.f, "REVISION {n}: {:?}", step.result)?; + self.nested(|this| this.format_evaluation_step(step))?; + } + writeln!(self.f, "RESULT: {:?}", goal.result) + } + }?; + + if goal.returned_goals.len() > 0 { + writeln!(self.f, "NESTED GOALS ADDED TO CALLER: [")?; + self.nested(|this| { + for goal in goal.returned_goals.iter() { + writeln!(this.f, "ADDED GOAL: {:?},", goal)?; + } + Ok(()) + })?; + + writeln!(self.f, "]")?; + } + + Ok(()) + } + + pub(super) fn format_evaluation_step( + &mut self, + evaluation_step: &GoalEvaluationStep<'_>, + ) -> std::fmt::Result { + writeln!(self.f, "INSTANTIATED: {:?}", evaluation_step.instantiated_goal)?; + + for candidate in &evaluation_step.candidates { + self.nested(|this| this.format_candidate(candidate))?; + } + for nested in &evaluation_step.nested_goal_evaluations { + self.nested(|this| this.format_nested_goal_evaluation(nested))?; + } + + Ok(()) + } + + pub(super) fn format_candidate(&mut self, candidate: &GoalCandidate<'_>) -> std::fmt::Result { + match &candidate.kind { + CandidateKind::NormalizedSelfTyAssembly => { + writeln!(self.f, "NORMALIZING SELF TY FOR ASSEMBLY:") + } + CandidateKind::Candidate { name, result } => { + writeln!(self.f, "CANDIDATE {}: {:?}", name, result) + } + }?; + + self.nested(|this| { + for candidate in &candidate.candidates { + this.format_candidate(candidate)?; + } + for nested in &candidate.nested_goal_evaluations { + this.format_nested_goal_evaluation(nested)?; + } + Ok(()) + }) + } + + pub(super) fn format_nested_goal_evaluation( + &mut self, + nested_goal_evaluation: &AddedGoalsEvaluation<'_>, + ) -> std::fmt::Result { + writeln!(self.f, "TRY_EVALUATE_ADDED_GOALS: {:?}", nested_goal_evaluation.result)?; + + for (n, revision) in nested_goal_evaluation.evaluations.iter().enumerate() { + writeln!(self.f, "REVISION {n}")?; + self.nested(|this| { + for goal_evaluation in revision { + this.format_goal_evaluation(goal_evaluation)?; + } + Ok(()) + })?; + } + + Ok(()) + } +} diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index dc2cd203560..18a57b6181a 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -259,7 +259,9 @@ pub fn ancestors( if let Some(reported) = specialization_graph.has_errored { Err(reported) - } else if let Err(reported) = tcx.type_of(start_from_impl).subst_identity().error_reported() { + } else if let Err(reported) = + tcx.type_of(start_from_impl).instantiate_identity().error_reported() + { Err(reported) } else { Ok(Ancestors { diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index 6acb7745d65..e2cd118500b 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs @@ -9,15 +9,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> { match *self { super::ImplSource::UserDefined(ref v) => write!(f, "{:?}", v), - super::ImplSource::AutoImpl(ref t) => write!(f, "{:?}", t), - - super::ImplSource::Closure(ref d) => write!(f, "{:?}", d), - - super::ImplSource::Generator(ref d) => write!(f, "{:?}", d), - - super::ImplSource::Future(ref d) => write!(f, "{:?}", d), - - super::ImplSource::FnPointer(ref d) => write!(f, "({:?})", d), + super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d), super::ImplSource::Object(ref d) => write!(f, "{:?}", d), @@ -25,13 +17,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> { write!(f, "ImplSourceParamData({:?}, {:?})", n, ct) } - super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d), - - super::ImplSource::TraitAlias(ref d) => write!(f, "{:?}", d), - super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d), - - super::ImplSource::ConstDestruct(ref d) => write!(f, "{:?}", d), } } } @@ -40,96 +26,28 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceUserDefinedData<'tcx, fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "ImplSourceUserDefinedData(impl_def_id={:?}, substs={:?}, nested={:?})", - self.impl_def_id, self.substs, self.nested - ) - } -} - -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceGeneratorData<'tcx, N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceGeneratorData(generator_def_id={:?}, substs={:?}, nested={:?})", - self.generator_def_id, self.substs, self.nested - ) - } -} - -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceFutureData<'tcx, N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceFutureData(generator_def_id={:?}, substs={:?}, nested={:?})", - self.generator_def_id, self.substs, self.nested - ) - } -} - -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceClosureData<'tcx, N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceClosureData(closure_def_id={:?}, substs={:?}, nested={:?})", - self.closure_def_id, self.substs, self.nested - ) - } -} - -impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceBuiltinData<N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ImplSourceBuiltinData(nested={:?})", self.nested) - } -} - -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitUpcastingData<'tcx, N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceTraitUpcastingData(upcast={:?}, vtable_vptr_slot={:?}, nested={:?})", - self.upcast_trait_ref, self.vtable_vptr_slot, self.nested - ) - } -} - -impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceAutoImplData<N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceAutoImplData(trait_def_id={:?}, nested={:?})", - self.trait_def_id, self.nested + "ImplSourceUserDefinedData(impl_def_id={:?}, args={:?}, nested={:?})", + self.impl_def_id, self.args, self.nested ) } } -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceObjectData<'tcx, N> { +impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitUpcastingData<N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "ImplSourceObjectData(upcast={:?}, vtable_base={}, nested={:?})", - self.upcast_trait_ref, self.vtable_base, self.nested + "ImplSourceTraitUpcastingData(vtable_vptr_slot={:?}, nested={:?})", + self.vtable_vptr_slot, self.nested ) } } -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceFnPointerData<'tcx, N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ImplSourceFnPointerData(fn_ty={:?}, nested={:?})", self.fn_ty, self.nested) - } -} - -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitAliasData<'tcx, N> { +impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceObjectData<N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "ImplSourceTraitAliasData(alias_def_id={:?}, substs={:?}, nested={:?})", - self.alias_def_id, self.substs, self.nested + "ImplSourceObjectData(vtable_base={}, nested={:?})", + self.vtable_base, self.nested ) } } - -impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceConstDestructData<N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ImplSourceConstDestructData(nested={:?})", self.nested) - } -} diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs index d54b8c599d9..05c06efaf16 100644 --- a/compiler/rustc_middle/src/traits/util.rs +++ b/compiler/rustc_middle/src/traits/util.rs @@ -25,9 +25,7 @@ impl<'tcx> Elaborator<'tcx> { .super_predicates_of(trait_ref.def_id()) .predicates .into_iter() - .flat_map(|(pred, _)| { - pred.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_pred() - }) + .flat_map(|(pred, _)| pred.subst_supertrait(self.tcx, &trait_ref).as_trait_clause()) .map(|t| t.map_bound(|pred| pred.trait_ref)) .filter(|supertrait_ref| self.visited.insert(*supertrait_ref)); diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index cbc68fde9d9..09517200b0d 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -81,7 +81,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { Err(TypeError::Sorts(relate::expected_found(self, a, b))) } - (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(self.tcx().ty_error(guar)), + (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(self.tcx(), guar)), _ => relate::structurally_relate_tys(self, a, b), } diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index a39631da936..0364a620810 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -53,10 +53,10 @@ impl<'tcx> TyCtxt<'tcx> { fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> { let ct = match c.kind() { ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) { - Err(e) => self.tcx.const_error(c.ty(), e), + Err(e) => ty::Const::new_error(self.tcx, e, c.ty()), Ok(Some(bac)) => { - let substs = self.tcx.erase_regions(uv.substs); - let bac = bac.subst(self.tcx, substs); + let args = self.tcx.erase_regions(uv.args); + let bac = bac.instantiate(self.tcx, args); return bac.fold_with(self); } Ok(None) => c, diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index cd0f7e8daf1..76931ceaa69 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -6,7 +6,7 @@ use rustc_span::Span; use rustc_target::abi::FieldIdx; #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] -pub enum PointerCast { +pub enum PointerCoercion { /// Go from a fn-item type to a fn-pointer type. ReifyFnPointer, @@ -99,7 +99,7 @@ pub enum Adjust<'tcx> { /// Take the address and produce either a `&` or `*` pointer. Borrow(AutoBorrow<'tcx>), - Pointer(PointerCast), + Pointer(PointerCoercion), /// Cast into a dyn* object. DynStar, @@ -132,7 +132,7 @@ impl<'tcx> OverloadedDeref<'tcx> { .find(|m| m.kind == ty::AssocKind::Fn) .unwrap() .def_id; - tcx.mk_fn_def(method_def_id, [source]) + Ty::new_fn_def(tcx, method_def_id, [source]) } } diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index cce609c261e..f77a8c6712e 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -84,14 +84,22 @@ impl AssocItem { // late-bound regions, and we don't want method signatures to show up // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound // regions just fine, showing `fn(&MyType)`. - tcx.fn_sig(self.def_id).subst_identity().skip_binder().to_string() + tcx.fn_sig(self.def_id).instantiate_identity().skip_binder().to_string() } ty::AssocKind::Type => format!("type {};", self.name), ty::AssocKind::Const => { - format!("const {}: {:?};", self.name, tcx.type_of(self.def_id).subst_identity()) + format!( + "const {}: {:?};", + self.name, + tcx.type_of(self.def_id).instantiate_identity() + ) } } } + + pub fn is_impl_trait_in_trait(&self) -> bool { + self.opt_rpitit_info.is_some() + } } #[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)] diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index be7b2b7ec67..91eefa2c125 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -6,9 +6,10 @@ use crate::{mir, ty}; use std::fmt::Write; use crate::query::Providers; -use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; +use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, LangItem}; +use rustc_span::def_id::LocalDefIdMap; use rustc_span::symbol::Ident; use rustc_span::{Span, Symbol}; @@ -56,12 +57,9 @@ pub enum UpvarCapture { ByRef(BorrowKind), } -pub type UpvarListMap = FxHashMap<DefId, FxIndexMap<hir::HirId, UpvarId>>; -pub type UpvarCaptureMap = FxHashMap<UpvarId, UpvarCapture>; - /// Given the closure DefId this map provides a map of root variables to minimum /// set of `CapturedPlace`s that need to be tracked to support all captures of that closure. -pub type MinCaptureInformationMap<'tcx> = FxHashMap<LocalDefId, RootVariableMinCaptureList<'tcx>>; +pub type MinCaptureInformationMap<'tcx> = LocalDefIdMap<RootVariableMinCaptureList<'tcx>>; /// Part of `MinCaptureInformationMap`; Maps a root variable to the list of `CapturedPlace`. /// Used to track the minimum set of `Place`s that need to be captured to support all @@ -427,6 +425,8 @@ pub enum BorrowKind { /// immutable, but not aliasable. This solves the problem. For /// simplicity, we don't give users the way to express this /// borrow, it's just used when translating closures. + /// + /// FIXME: Rename this to indicate the borrow is actually not immutable. UniqueImmBorrow, /// Data is mutable and not aliasable. diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 76f52bc34ed..b4f4f9bef8e 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -13,7 +13,7 @@ use crate::mir::{ interpret::{AllocId, ConstAllocation}, }; use crate::traits; -use crate::ty::subst::SubstsRef; +use crate::ty::GenericArgsRef; use crate::ty::{self, AdtDef, Ty}; use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::TyCtxt; @@ -128,6 +128,12 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Predicate<'tcx> } } +impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Clause<'tcx> { + fn encode(&self, e: &mut E) { + self.as_predicate().encode(e); + } +} + impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Region<'tcx> { fn encode(&self, e: &mut E) { self.kind().encode(e); @@ -241,12 +247,19 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Predicate<'tcx> } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for SubstsRef<'tcx> { +impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Clause<'tcx> { + fn decode(decoder: &mut D) -> ty::Clause<'tcx> { + let pred: ty::Predicate<'tcx> = Decodable::decode(decoder); + pred.expect_clause() + } +} + +impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for GenericArgsRef<'tcx> { fn decode(decoder: &mut D) -> Self { let len = decoder.read_usize(); let tcx = decoder.interner(); - tcx.mk_substs_from_iter( - (0..len).map::<ty::subst::GenericArg<'tcx>, _>(|_| Decodable::decode(decoder)), + tcx.mk_args_from_iter( + (0..len).map::<ty::GenericArg<'tcx>, _>(|_| Decodable::decode(decoder)), ) } } @@ -331,7 +344,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> { fn decode(decoder: &mut D) -> Self { let consts: ty::ConstData<'tcx> = Decodable::decode(decoder); - decoder.interner().mk_const(consts.kind, consts.ty) + decoder.interner().mk_ct_from_kind(consts.kind, consts.ty) } } @@ -355,16 +368,6 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for AdtDef<'tcx> { } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> - for [(ty::Predicate<'tcx>, Span)] -{ - fn decode(decoder: &mut D) -> &'tcx Self { - decoder.interner().arena.alloc_from_iter( - (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(), - ) - } -} - impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] { fn decode(decoder: &mut D) -> &'tcx Self { decoder.interner().arena.alloc_from_iter( @@ -393,11 +396,11 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty::Predicate<'tcx>> { +impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty::Clause<'tcx>> { fn decode(decoder: &mut D) -> &'tcx Self { let len = decoder.read_usize(); - decoder.interner().mk_predicates_from_iter( - (0..len).map::<ty::Predicate<'tcx>, _>(|_| Decodable::decode(decoder)), + decoder.interner().mk_clauses_from_iter( + (0..len).map::<ty::Clause<'tcx>, _>(|_| Decodable::decode(decoder)), ) } } @@ -421,7 +424,7 @@ impl_decodable_via_ref! { &'tcx mir::BorrowCheckResult<'tcx>, &'tcx mir::coverage::CodeRegion, &'tcx ty::List<ty::BoundVariableKind>, - &'tcx ty::List<ty::Predicate<'tcx>>, + &'tcx ty::List<ty::Clause<'tcx>>, &'tcx ty::List<FieldIdx>, } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index aecb46556b0..4ef70107f19 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -1,7 +1,8 @@ use crate::middle::resolve_bound_vars as rbv; -use crate::mir::interpret::LitToConstInput; -use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; +use crate::mir::interpret::{AllocId, ConstValue, LitToConstInput, Scalar}; +use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_data_structures::intern::Interned; +use rustc_error_messages::MultiSpan; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; @@ -13,8 +14,13 @@ mod valtree; pub use int::*; pub use kind::*; +use rustc_span::ErrorGuaranteed; +use rustc_span::DUMMY_SP; +use rustc_target::abi::Size; pub use valtree::*; +use super::sty::ConstKind; + /// Use this rather than `ConstData`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_pass_by_value] @@ -30,6 +36,16 @@ pub struct ConstData<'tcx> { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(ConstData<'_>, 40); +enum EvalMode { + Typeck, + Mir, +} + +enum EvalResult<'tcx> { + ValTree(ty::ValTree<'tcx>), + ConstVal(ConstValue<'tcx>), +} + impl<'tcx> Const<'tcx> { #[inline] pub fn ty(self) -> Ty<'tcx> { @@ -38,7 +54,98 @@ impl<'tcx> Const<'tcx> { #[inline] pub fn kind(self) -> ConstKind<'tcx> { - self.0.kind + self.0.kind.clone() + } + + #[inline] + pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + tcx.mk_ct_from_kind(kind, ty) + } + + #[inline] + pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Param(param), ty) + } + + #[inline] + pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer)), ty) + } + + #[inline] + pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh)), ty) + } + + #[inline] + pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Infer(infer), ty) + } + + #[inline] + pub fn new_bound( + tcx: TyCtxt<'tcx>, + debruijn: ty::DebruijnIndex, + var: ty::BoundVar, + ty: Ty<'tcx>, + ) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Bound(debruijn, var), ty) + } + + #[inline] + pub fn new_placeholder( + tcx: TyCtxt<'tcx>, + placeholder: ty::PlaceholderConst<'tcx>, + ty: Ty<'tcx>, + ) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Placeholder(placeholder), ty) + } + + #[inline] + pub fn new_unevaluated( + tcx: TyCtxt<'tcx>, + uv: ty::UnevaluatedConst<'tcx>, + ty: Ty<'tcx>, + ) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Unevaluated(uv), ty) + } + + #[inline] + pub fn new_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Value(val), ty) + } + + #[inline] + pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Expr(expr), ty) + } + + #[inline] + pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Error(e), ty) + } + + /// Like [Ty::new_error] but for constants. + #[track_caller] + pub fn new_misc_error(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new_error_with_message( + tcx, + ty, + DUMMY_SP, + "ty::ConstKind::Error constructed but no error reported", + ) + } + + /// Like [Ty::new_error_with_message] but for constants. + #[track_caller] + pub fn new_error_with_message<S: Into<MultiSpan>>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + span: S, + msg: &'static str, + ) -> Const<'tcx> { + let reported = tcx.sess.delay_span_bug(span, msg); + Const::new_error(tcx, reported, ty) } /// Literals and const generic parameters are eagerly converted to a constant, everything else @@ -60,10 +167,11 @@ impl<'tcx> Const<'tcx> { match Self::try_eval_lit_or_param(tcx, ty, expr) { Some(v) => v, - None => tcx.mk_const( + None => ty::Const::new_unevaluated( + tcx, ty::UnevaluatedConst { def: def.to_def_id(), - substs: InternalSubsts::identity_for_item(tcx, def.to_def_id()), + args: GenericArgs::identity_for_item(tcx, def.to_def_id()), }, ty, ), @@ -117,7 +225,7 @@ impl<'tcx> Const<'tcx> { )) => { // Use the type from the param's definition, since we can resolve it, // not the expected parameter type from WithOptConstParam. - let param_ty = tcx.type_of(def_id).subst_identity(); + let param_ty = tcx.type_of(def_id).instantiate_identity(); match tcx.named_bound_var(expr.hir_id) { Some(rbv::ResolvedArg::EarlyBound(_)) => { // Find the name and index of the const parameter by indexing the generics of @@ -126,13 +234,19 @@ impl<'tcx> Const<'tcx> { let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; let name = tcx.item_name(def_id); - Some(tcx.mk_const(ty::ParamConst::new(index, name), param_ty)) + Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name), param_ty)) + } + Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => { + Some(ty::Const::new_bound( + tcx, + debruijn, + ty::BoundVar::from_u32(index), + param_ty, + )) + } + Some(rbv::ResolvedArg::Error(guar)) => { + Some(ty::Const::new_error(tcx, guar, param_ty)) } - Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const( - ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)), - param_ty, - )), - Some(rbv::ResolvedArg::Error(guar)) => Some(tcx.const_error(param_ty, guar)), arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id), } } @@ -155,7 +269,8 @@ impl<'tcx> Const<'tcx> { .layout_of(ty) .unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e)) .size; - tcx.mk_const( + ty::Const::new_value( + tcx, ty::ValTree::from_scalar_int(ScalarInt::try_from_uint(bits, size).unwrap()), ty.value, ) @@ -164,7 +279,7 @@ impl<'tcx> Const<'tcx> { #[inline] /// Creates an interned zst constant. pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self { - tcx.mk_const(ty::ValTree::zst(), ty) + ty::Const::new_value(tcx, ty::ValTree::zst(), ty) } #[inline] @@ -179,6 +294,14 @@ impl<'tcx> Const<'tcx> { Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) } + /// Attempts to convert to a `ValTree` + pub fn try_to_valtree(self) -> Option<ty::ValTree<'tcx>> { + match self.kind() { + ty::ConstKind::Value(valtree) => Some(valtree), + _ => None, + } + } + #[inline] /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it @@ -192,12 +315,12 @@ impl<'tcx> Const<'tcx> { assert_eq!(self.ty(), ty); let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; // if `ty` does not depend on generic parameters, use an empty param_env - self.kind().eval(tcx, param_env).try_to_bits(size) + self.eval(tcx, param_env).try_to_bits(size) } #[inline] pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> { - self.kind().eval(tcx, param_env).try_to_bool() + self.eval(tcx, param_env).try_to_bool() } #[inline] @@ -206,17 +329,17 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ) -> Option<u64> { - self.kind().eval(tcx, param_env).try_to_target_usize(tcx) + self.eval(tcx, param_env).try_to_target_usize(tcx) } #[inline] /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the /// unevaluated constant. pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> { - if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) { + if let Some(val) = self.try_eval_for_typeck(tcx, param_env) { match val { - Ok(val) => tcx.mk_const(val, self.ty()), - Err(guar) => tcx.const_error(self.ty(), guar), + Ok(val) => ty::Const::new_value(tcx, val, self.ty()), + Err(guar) => ty::Const::new_error(tcx, guar, self.ty()), } } else { // Either the constant isn't evaluatable or ValTree creation failed. @@ -238,6 +361,138 @@ impl<'tcx> Const<'tcx> { .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) } + #[inline] + /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary + /// return `None`. + // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. + pub fn try_eval_for_mir( + self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + ) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> { + match self.try_eval_inner(tcx, param_env, EvalMode::Mir) { + Some(Ok(EvalResult::ValTree(_))) => unreachable!(), + Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)), + Some(Err(e)) => Some(Err(e)), + None => None, + } + } + + #[inline] + /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary + /// return `None`. + // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. + pub fn try_eval_for_typeck( + self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + ) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>> { + match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) { + Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)), + Some(Ok(EvalResult::ConstVal(_))) => unreachable!(), + Some(Err(e)) => Some(Err(e)), + None => None, + } + } + + #[inline] + fn try_eval_inner( + self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + eval_mode: EvalMode, + ) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> { + assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}"); + if let ConstKind::Unevaluated(unevaluated) = self.kind() { + use crate::mir::interpret::ErrorHandled; + + // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` + // also does later, but we want to do it before checking for + // inference variables. + // Note that we erase regions *before* calling `with_reveal_all_normalized`, + // so that we don't try to invoke this query with + // any region variables. + + // HACK(eddyb) when the query key would contain inference variables, + // attempt using identity args and `ParamEnv` instead, that will succeed + // when the expression doesn't depend on any parameters. + // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that + // we can call `infcx.const_eval_resolve` which handles inference variables. + let param_env_and = if (param_env, unevaluated).has_non_region_infer() { + tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst { + def: unevaluated.def, + args: GenericArgs::identity_for_item(tcx, unevaluated.def), + }) + } else { + tcx.erase_regions(param_env) + .with_reveal_all_normalized(tcx) + .and(tcx.erase_regions(unevaluated)) + }; + + // FIXME(eddyb) maybe the `const_eval_*` methods should take + // `ty::ParamEnvAnd` instead of having them separate. + let (param_env, unevaluated) = param_env_and.into_parts(); + // try to resolve e.g. associated constants to their definition on an impl, and then + // evaluate the const. + match eval_mode { + EvalMode::Typeck => { + match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) { + // NOTE(eddyb) `val` contains no lifetimes/types/consts, + // and we use the original type, so nothing from `args` + // (which may be identity args, see above), + // can leak through `val` into the const we return. + Ok(val) => Some(Ok(EvalResult::ValTree(val?))), + Err(ErrorHandled::TooGeneric) => None, + Err(ErrorHandled::Reported(e)) => Some(Err(e.into())), + } + } + EvalMode::Mir => { + match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) { + // NOTE(eddyb) `val` contains no lifetimes/types/consts, + // and we use the original type, so nothing from `args` + // (which may be identity args, see above), + // can leak through `val` into the const we return. + Ok(val) => Some(Ok(EvalResult::ConstVal(val))), + Err(ErrorHandled::TooGeneric) => None, + Err(ErrorHandled::Reported(e)) => Some(Err(e.into())), + } + } + } + } else { + None + } + } + + #[inline] + pub fn try_to_value(self) -> Option<ty::ValTree<'tcx>> { + if let ConstKind::Value(val) = self.kind() { Some(val) } else { None } + } + + #[inline] + pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> { + self.try_to_value()?.try_to_scalar() + } + + #[inline] + pub fn try_to_scalar_int(self) -> Option<ScalarInt> { + self.try_to_value()?.try_to_scalar_int() + } + + #[inline] + pub fn try_to_bits(self, size: Size) -> Option<u128> { + self.try_to_scalar_int()?.to_bits(size).ok() + } + + #[inline] + pub fn try_to_bool(self) -> Option<bool> { + self.try_to_scalar_int()?.try_into().ok() + } + + #[inline] + pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> { + self.try_to_value()?.try_to_target_usize(tcx) + } + pub fn is_ct_infer(self) -> bool { matches!(self.kind(), ty::ConstKind::Infer(_)) } diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 1e43fab457e..624195cfb28 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -418,7 +418,7 @@ impl TryFrom<ScalarInt> for char { #[inline] fn try_from(int: ScalarInt) -> Result<Self, Self::Error> { - let Ok(bits) = int.to_bits(Size::from_bytes(std::mem::size_of::<char>())) else { + let Ok(bits) = int.to_bits(Size::from_bytes(std::mem::size_of::<char>())) else { return Err(CharTryFromScalarInt); }; match char::from_u32(bits.try_into().unwrap()) { diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 1dd4f8a2437..6c76075c214 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,24 +1,18 @@ use super::Const; use crate::mir; -use crate::mir::interpret::{AllocId, ConstValue, Scalar}; use crate::ty::abstract_const::CastKind; -use crate::ty::subst::{InternalSubsts, SubstsRef}; -use crate::ty::ParamEnv; -use crate::ty::{self, List, Ty, TyCtxt, TypeVisitableExt}; +use crate::ty::GenericArgsRef; +use crate::ty::{self, List, Ty}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; -use rustc_target::abi::Size; - -use super::ScalarInt; /// An unevaluated (potentially generic) constant used in the type-system. -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] +#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] #[derive(Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct UnevaluatedConst<'tcx> { pub def: DefId, - pub substs: SubstsRef<'tcx>, + pub args: GenericArgsRef<'tcx>, } impl rustc_errors::IntoDiagnosticArg for UnevaluatedConst<'_> { @@ -30,57 +24,18 @@ impl rustc_errors::IntoDiagnosticArg for UnevaluatedConst<'_> { impl<'tcx> UnevaluatedConst<'tcx> { #[inline] pub fn expand(self) -> mir::UnevaluatedConst<'tcx> { - mir::UnevaluatedConst { def: self.def, substs: self.substs, promoted: None } + mir::UnevaluatedConst { def: self.def, args: self.args, promoted: None } } } impl<'tcx> UnevaluatedConst<'tcx> { #[inline] - pub fn new(def: DefId, substs: SubstsRef<'tcx>) -> UnevaluatedConst<'tcx> { - UnevaluatedConst { def, substs } - } -} - -/// Represents a constant in Rust. -#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] -#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)] -#[derive(derive_more::From)] -pub enum ConstKind<'tcx> { - /// A const generic parameter. - Param(ty::ParamConst), - - /// Infer the value of the const. - Infer(InferConst<'tcx>), - - /// Bound const variable, used only when preparing a trait query. - Bound(ty::DebruijnIndex, ty::BoundVar), - - /// A placeholder const - universally quantified higher-ranked const. - Placeholder(ty::PlaceholderConst<'tcx>), - - /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other - /// variants when the code is monomorphic enough for that. - Unevaluated(UnevaluatedConst<'tcx>), - - /// Used to hold computed value. - Value(ty::ValTree<'tcx>), - - /// A placeholder for a const which could not be computed; this is - /// propagated to avoid useless error messages. - #[from(ignore)] - Error(ErrorGuaranteed), - - /// Expr which contains an expression which has partially evaluated items. - Expr(Expr<'tcx>), -} - -impl<'tcx> From<ty::ConstVid<'tcx>> for ConstKind<'tcx> { - fn from(const_vid: ty::ConstVid<'tcx>) -> Self { - InferConst::Var(const_vid).into() + pub fn new(def: DefId, args: GenericArgsRef<'tcx>) -> UnevaluatedConst<'tcx> { + UnevaluatedConst { def, args } } } -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] #[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] pub enum Expr<'tcx> { Binop(mir::BinOp, Const<'tcx>, Const<'tcx>), @@ -93,39 +48,7 @@ pub enum Expr<'tcx> { static_assert_size!(Expr<'_>, 24); #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(ConstKind<'_>, 32); - -impl<'tcx> ConstKind<'tcx> { - #[inline] - pub fn try_to_value(self) -> Option<ty::ValTree<'tcx>> { - if let ConstKind::Value(val) = self { Some(val) } else { None } - } - - #[inline] - pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> { - self.try_to_value()?.try_to_scalar() - } - - #[inline] - pub fn try_to_scalar_int(self) -> Option<ScalarInt> { - self.try_to_value()?.try_to_scalar_int() - } - - #[inline] - pub fn try_to_bits(self, size: Size) -> Option<u128> { - self.try_to_scalar_int()?.to_bits(size).ok() - } - - #[inline] - pub fn try_to_bool(self) -> Option<bool> { - self.try_to_scalar_int()?.try_into().ok() - } - - #[inline] - pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> { - self.try_to_value()?.try_to_target_usize(tcx) - } -} +static_assert_size!(super::ConstKind<'_>, 32); /// An inference variable for a const, for use in const generics. #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)] @@ -144,124 +67,3 @@ impl<CTX> HashStable<CTX> for InferConst<'_> { } } } - -enum EvalMode { - Typeck, - Mir, -} - -enum EvalResult<'tcx> { - ValTree(ty::ValTree<'tcx>), - ConstVal(ConstValue<'tcx>), -} - -impl<'tcx> ConstKind<'tcx> { - #[inline] - /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the - /// unevaluated constant. - pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self { - self.try_eval_for_typeck(tcx, param_env).and_then(Result::ok).map_or(self, ConstKind::Value) - } - - #[inline] - /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary - /// return `None`. - // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. - pub fn try_eval_for_mir( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - ) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> { - match self.try_eval_inner(tcx, param_env, EvalMode::Mir) { - Some(Ok(EvalResult::ValTree(_))) => unreachable!(), - Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)), - Some(Err(e)) => Some(Err(e)), - None => None, - } - } - - #[inline] - /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary - /// return `None`. - // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. - pub fn try_eval_for_typeck( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - ) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>> { - match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) { - Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)), - Some(Ok(EvalResult::ConstVal(_))) => unreachable!(), - Some(Err(e)) => Some(Err(e)), - None => None, - } - } - - #[inline] - fn try_eval_inner( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - eval_mode: EvalMode, - ) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> { - assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}"); - if let ConstKind::Unevaluated(unevaluated) = self { - use crate::mir::interpret::ErrorHandled; - - // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` - // also does later, but we want to do it before checking for - // inference variables. - // Note that we erase regions *before* calling `with_reveal_all_normalized`, - // so that we don't try to invoke this query with - // any region variables. - - // HACK(eddyb) when the query key would contain inference variables, - // attempt using identity substs and `ParamEnv` instead, that will succeed - // when the expression doesn't depend on any parameters. - // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that - // we can call `infcx.const_eval_resolve` which handles inference variables. - let param_env_and = if (param_env, unevaluated).has_non_region_infer() { - tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst { - def: unevaluated.def, - substs: InternalSubsts::identity_for_item(tcx, unevaluated.def), - }) - } else { - tcx.erase_regions(param_env) - .with_reveal_all_normalized(tcx) - .and(tcx.erase_regions(unevaluated)) - }; - - // FIXME(eddyb) maybe the `const_eval_*` methods should take - // `ty::ParamEnvAnd` instead of having them separate. - let (param_env, unevaluated) = param_env_and.into_parts(); - // try to resolve e.g. associated constants to their definition on an impl, and then - // evaluate the const. - match eval_mode { - EvalMode::Typeck => { - match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) { - // NOTE(eddyb) `val` contains no lifetimes/types/consts, - // and we use the original type, so nothing from `substs` - // (which may be identity substs, see above), - // can leak through `val` into the const we return. - Ok(val) => Some(Ok(EvalResult::ValTree(val?))), - Err(ErrorHandled::TooGeneric) => None, - Err(ErrorHandled::Reported(e)) => Some(Err(e.into())), - } - } - EvalMode::Mir => { - match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) { - // NOTE(eddyb) `val` contains no lifetimes/types/consts, - // and we use the original type, so nothing from `substs` - // (which may be identity substs, see above), - // can leak through `val` into the const we return. - Ok(val) => Some(Ok(EvalResult::ConstVal(val))), - Err(ErrorHandled::TooGeneric) => None, - Err(ErrorHandled::Reported(e)) => Some(Err(e.into())), - } - } - } - } else { - None - } - } -} diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index 8b96864ddd7..fb7bf78bafe 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -24,7 +24,7 @@ pub enum ValTree<'tcx> { Leaf(ScalarInt), //SliceOrStr(ValSlice<'tcx>), - // dont use SliceOrStr for now + // don't use SliceOrStr for now /// The fields of any kind of aggregate. Structs, tuples and arrays are represented by /// listing their fields' values in order. /// diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4ee543bbfb6..aa1f8e48b1b 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -25,12 +25,12 @@ use crate::traits::solve::{ ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData, }; use crate::ty::{ - self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, FloatTy, FloatVar, FloatVid, - GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, - PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, ReprOptions, - TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility, + self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, GenericParamDefKind, + ImplPolarity, InferTy, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, + Predicate, PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, + TyVid, TypeAndMut, Visibility, }; -use crate::ty::{GenericArg, InternalSubsts, SubstsRef}; +use crate::ty::{GenericArg, GenericArgs, GenericArgsRef}; use rustc_ast::{self as ast, attr}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -70,10 +70,9 @@ use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx} use rustc_target::spec::abi; use rustc_type_ir::sty::TyKind::*; use rustc_type_ir::WithCachedTypeInfo; -use rustc_type_ir::{CollectAndApply, DynKind, Interner, TypeFlags}; +use rustc_type_ir::{CollectAndApply, Interner, TypeFlags}; use std::any::Any; -use std::assert_matches::debug_assert_matches; use std::borrow::Borrow; use std::cmp::Ordering; use std::fmt; @@ -85,7 +84,7 @@ use std::ops::{Bound, Deref}; #[allow(rustc::usage_of_ty_tykind)] impl<'tcx> Interner for TyCtxt<'tcx> { type AdtDef = ty::AdtDef<'tcx>; - type SubstsRef = ty::SubstsRef<'tcx>; + type GenericArgsRef = ty::GenericArgsRef<'tcx>; type DefId = DefId; type Binder<T> = Binder<'tcx, T>; type Ty = Ty<'tcx>; @@ -108,6 +107,14 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type PredicateKind = ty::PredicateKind<'tcx>; type AllocId = crate::mir::interpret::AllocId; + type InferConst = ty::InferConst<'tcx>; + type AliasConst = ty::UnevaluatedConst<'tcx>; + type ParamConst = ty::ParamConst; + type BoundConst = ty::BoundVar; + type PlaceholderConst = ty::PlaceholderConst<'tcx>; + type ValueConst = ty::ValTree<'tcx>; + type ExprConst = ty::Expr<'tcx>; + type EarlyBoundRegion = ty::EarlyBoundRegion; type BoundRegion = ty::BoundRegion; type FreeRegion = ty::FreeRegion; @@ -135,13 +142,13 @@ pub struct CtxtInterners<'tcx> { // they're accessed quite often. type_: InternedSet<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>, const_lists: InternedSet<'tcx, List<ty::Const<'tcx>>>, - substs: InternedSet<'tcx, InternalSubsts<'tcx>>, + args: InternedSet<'tcx, GenericArgs<'tcx>>, type_lists: InternedSet<'tcx, List<Ty<'tcx>>>, canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>, region: InternedSet<'tcx, RegionKind<'tcx>>, poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>, predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>, - predicates: InternedSet<'tcx, List<Predicate<'tcx>>>, + clauses: InternedSet<'tcx, List<Clause<'tcx>>>, projs: InternedSet<'tcx, List<ProjectionKind>>, place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>, const_: InternedSet<'tcx, ConstData<'tcx>>, @@ -160,13 +167,13 @@ impl<'tcx> CtxtInterners<'tcx> { arena, type_: Default::default(), const_lists: Default::default(), - substs: 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(), - predicates: Default::default(), + clauses: Default::default(), projs: Default::default(), place_elems: Default::default(), const_: Default::default(), @@ -320,6 +327,8 @@ pub struct CommonLifetimes<'tcx> { pub struct CommonConsts<'tcx> { pub unit: Const<'tcx>, + pub true_: Const<'tcx>, + pub false_: Const<'tcx>, } impl<'tcx> CommonTypes<'tcx> { @@ -417,6 +426,14 @@ impl<'tcx> CommonConsts<'tcx> { kind: ty::ConstKind::Value(ty::ValTree::zst()), ty: types.unit, }), + true_: mk_const(ty::ConstData { + kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::TRUE)), + ty: types.bool, + }), + false_: mk_const(ty::ConstData { + kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::FALSE)), + ty: types.bool, + }), } } } @@ -552,6 +569,7 @@ pub struct GlobalCtxt<'tcx> { /// Caches the results of goal evaluation in the new solver. pub new_solver_evaluation_cache: solve::EvaluationCache<'tcx>, + pub new_solver_coherence_evaluation_cache: solve::EvaluationCache<'tcx>, /// Data layout specification for the current target. pub data_layout: TargetDataLayout, @@ -663,10 +681,12 @@ impl<'tcx> TyCtxt<'tcx> { value.lift_to_tcx(self) } - /// Creates a type context and call the closure with a `TyCtxt` reference - /// to the context. The closure enforces that the type context and any interned - /// value (types, substs, etc.) can only be used while `ty::tls` has a valid - /// reference to the context, to allow formatting values that need it. + /// Creates a type context. To use the context call `fn enter` which + /// provides a `TyCtxt`. + /// + /// By only providing the `TyCtxt` inside of the closure we enforce that the type + /// context and any interned alue (types, args, etc.) can only be used while `ty::tls` + /// has a valid reference to the context, to allow formatting values that need it. pub fn create_global_ctxt( s: &'tcx Session, lint_store: Lrc<dyn Any + sync::DynSend + sync::DynSync>, @@ -704,63 +724,12 @@ impl<'tcx> TyCtxt<'tcx> { selection_cache: Default::default(), evaluation_cache: Default::default(), new_solver_evaluation_cache: Default::default(), + new_solver_coherence_evaluation_cache: Default::default(), data_layout, alloc_map: Lock::new(interpret::AllocMap::new()), } } - /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed` - #[track_caller] - pub fn ty_error(self, reported: ErrorGuaranteed) -> Ty<'tcx> { - self.mk_ty_from_kind(Error(reported)) - } - - /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. - #[track_caller] - pub fn ty_error_misc(self) -> Ty<'tcx> { - self.ty_error_with_message(DUMMY_SP, "TyKind::Error constructed but no error reported") - } - - /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to - /// ensure it gets used. - #[track_caller] - pub fn ty_error_with_message<S: Into<MultiSpan>>( - self, - span: S, - msg: impl Into<DiagnosticMessage>, - ) -> Ty<'tcx> { - let reported = self.sess.delay_span_bug(span, msg); - self.mk_ty_from_kind(Error(reported)) - } - - /// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed` - #[track_caller] - pub fn const_error(self, ty: Ty<'tcx>, reported: ErrorGuaranteed) -> Const<'tcx> { - self.mk_const(ty::ConstKind::Error(reported), ty) - } - - /// Like [TyCtxt::ty_error] but for constants. - #[track_caller] - pub fn const_error_misc(self, ty: Ty<'tcx>) -> Const<'tcx> { - self.const_error_with_message( - ty, - DUMMY_SP, - "ty::ConstKind::Error constructed but no error reported", - ) - } - - /// Like [TyCtxt::ty_error_with_message] but for constants. - #[track_caller] - pub fn const_error_with_message<S: Into<MultiSpan>>( - self, - ty: Ty<'tcx>, - span: S, - msg: &'static str, - ) -> Const<'tcx> { - let reported = self.sess.delay_span_bug(span, msg); - self.mk_const(ty::ConstKind::Error(reported), ty) - } - pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool { self.sess.consider_optimizing(|| self.crate_name(LOCAL_CRATE), msg) } @@ -1071,7 +1040,9 @@ impl<'tcx> TyCtxt<'tcx> { scope_def_id: LocalDefId, ) -> Vec<&'tcx hir::Ty<'tcx>> { let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id); - let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) else { + let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = + self.hir().fn_decl_by_hir_id(hir_id) + else { return vec![]; }; @@ -1116,7 +1087,7 @@ impl<'tcx> TyCtxt<'tcx> { _ => return None, } - let ret_ty = self.type_of(scope_def_id).subst_identity(); + let ret_ty = self.type_of(scope_def_id).instantiate_identity(); match ret_ty.kind() { ty::FnDef(_, _) => { let sig = ret_ty.fn_sig(self); @@ -1154,10 +1125,11 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns `&'static core::panic::Location<'static>`. pub fn caller_location_ty(self) -> Ty<'tcx> { - self.mk_imm_ref( + Ty::new_imm_ref( + self, self.lifetimes.re_static, self.type_of(self.require_lang_item(LangItem::PanicLocation, None)) - .subst(self, self.mk_substs(&[self.lifetimes.re_static.into()])), + .instantiate(self, self.mk_args(&[self.lifetimes.re_static.into()])), ) } @@ -1189,12 +1161,18 @@ impl<'tcx> TyCtxt<'tcx> { pub fn local_visibility(self, def_id: LocalDefId) -> Visibility { self.visibility(def_id).expect_local() } + + /// Returns the origin of the opaque type `def_id`. + #[instrument(skip(self), level = "trace", ret)] + pub fn opaque_type_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin { + self.hir().expect_item(def_id).expect_opaque_ty().origin + } } /// A trait implemented for all `X<'a>` types that can be safely and /// efficiently converted to `X<'tcx>` as long as they are part of the /// provided `TyCtxt<'tcx>`. -/// This can be done, for example, for `Ty<'tcx>` or `SubstsRef<'tcx>` +/// This can be done, for example, for `Ty<'tcx>` or `GenericArgsRef<'tcx>` /// by looking them up in their respective interners. /// /// However, this is still not the best implementation as it does @@ -1251,16 +1229,17 @@ nop_lift! {region; Region<'a> => Region<'tcx>} nop_lift! {const_; Const<'a> => Const<'tcx>} nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>} nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>} +nop_lift! {predicate; Clause<'a> => Clause<'tcx>} nop_list_lift! {type_lists; Ty<'a> => Ty<'tcx>} nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>} -nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>} +nop_list_lift! {clauses; Clause<'a> => Clause<'tcx>} nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>} nop_list_lift! {projs; ProjectionKind => ProjectionKind} nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind} -// This is the impl for `&'a InternalSubsts<'a>`. -nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>} +// This is the impl for `&'a GenericArgs<'a>`. +nop_list_lift! {args; GenericArg<'a> => GenericArg<'tcx>} CloneLiftImpls! { Constness, @@ -1372,7 +1351,7 @@ impl<'tcx> TyCtxt<'tcx> { Foreign )?; - writeln!(fmt, "InternalSubsts interner: #{}", self.0.interners.substs.len())?; + writeln!(fmt, "GenericArgs interner: #{}", self.0.interners.args.len())?; writeln!(fmt, "Region interner: #{}", self.0.interners.region.len())?; writeln!( fmt, @@ -1528,11 +1507,11 @@ macro_rules! slice_interners { // should be used when possible, because it's faster. slice_interners!( const_lists: pub mk_const_list(Const<'tcx>), - substs: pub mk_substs(GenericArg<'tcx>), + args: pub mk_args(GenericArg<'tcx>), type_lists: pub mk_type_list(Ty<'tcx>), canonical_var_infos: pub mk_canonical_var_infos(CanonicalVarInfo<'tcx>), poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>), - predicates: intern_predicates(Predicate<'tcx>), + clauses: intern_clauses(Clause<'tcx>), projs: pub mk_projs(ProjectionKind), place_elems: pub mk_place_elems(PlaceElem<'tcx>), bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind), @@ -1545,7 +1524,10 @@ impl<'tcx> TyCtxt<'tcx> { /// unsafe. pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> { assert_eq!(sig.unsafety(), hir::Unsafety::Normal); - self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig })) + Ty::new_fn_ptr( + self, + sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }), + ) } /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name` @@ -1564,7 +1546,7 @@ impl<'tcx> TyCtxt<'tcx> { let future_trait = self.require_lang_item(LangItem::Future, None); self.explicit_item_bounds(def_id).skip_binder().iter().any(|&(predicate, _)| { - let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() else { + let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else { return false; }; trait_predicate.trait_ref.def_id == future_trait @@ -1587,9 +1569,7 @@ impl<'tcx> TyCtxt<'tcx> { let generic_predicates = self.super_predicates_of(trait_did); for (predicate, _) in generic_predicates.predicates { - if let ty::PredicateKind::Clause(ty::Clause::Trait(data)) = - predicate.kind().skip_binder() - { + if let ty::ClauseKind::Trait(data) = predicate.kind().skip_binder() { if set.insert(data.def_id()) { stack.push(data.def_id()); } @@ -1621,18 +1601,6 @@ impl<'tcx> TyCtxt<'tcx> { }) } - // Avoid this in favour of more specific `mk_*` methods, where possible. - #[allow(rustc::usage_of_ty_tykind)] - #[inline] - pub fn mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx> { - self.interners.intern_ty( - st, - self.sess, - // This is only used to create a stable hashing context. - &self.untracked, - ) - } - #[inline] pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> { self.interners.intern_predicate( @@ -1652,181 +1620,13 @@ impl<'tcx> TyCtxt<'tcx> { if pred.kind() != binder { self.mk_predicate(binder) } else { pred } } - pub fn mk_mach_int(self, tm: IntTy) -> Ty<'tcx> { - match tm { - IntTy::Isize => self.types.isize, - IntTy::I8 => self.types.i8, - IntTy::I16 => self.types.i16, - IntTy::I32 => self.types.i32, - IntTy::I64 => self.types.i64, - IntTy::I128 => self.types.i128, - } - } - - pub fn mk_mach_uint(self, tm: UintTy) -> Ty<'tcx> { - match tm { - UintTy::Usize => self.types.usize, - UintTy::U8 => self.types.u8, - UintTy::U16 => self.types.u16, - UintTy::U32 => self.types.u32, - UintTy::U64 => self.types.u64, - UintTy::U128 => self.types.u128, - } - } - - pub fn mk_mach_float(self, tm: FloatTy) -> Ty<'tcx> { - match tm { - FloatTy::F32 => self.types.f32, - FloatTy::F64 => self.types.f64, - } - } - - #[inline] - pub fn mk_static_str(self) -> Ty<'tcx> { - self.mk_imm_ref(self.lifetimes.re_static, self.types.str_) - } - - #[inline] - pub fn mk_adt(self, def: AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> Ty<'tcx> { - // Take a copy of substs so that we own the vectors inside. - self.mk_ty_from_kind(Adt(def, substs)) - } - - #[inline] - pub fn mk_foreign(self, def_id: DefId) -> Ty<'tcx> { - self.mk_ty_from_kind(Foreign(def_id)) - } - - fn mk_generic_adt(self, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> { - let adt_def = self.adt_def(wrapper_def_id); - let substs = - InternalSubsts::for_item(self, wrapper_def_id, |param, substs| match param.kind { - GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(), - GenericParamDefKind::Type { has_default, .. } => { - if param.index == 0 { - ty_param.into() - } else { - assert!(has_default); - self.type_of(param.def_id).subst(self, substs).into() - } - } - }); - self.mk_ty_from_kind(Adt(adt_def, substs)) - } - - #[inline] - pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> { - let def_id = self.require_lang_item(LangItem::OwnedBox, None); - self.mk_generic_adt(def_id, ty) - } - - #[inline] - pub fn mk_lang_item(self, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> { - let def_id = self.lang_items().get(item)?; - Some(self.mk_generic_adt(def_id, ty)) - } - - #[inline] - pub fn mk_diagnostic_item(self, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> { - let def_id = self.get_diagnostic_item(name)?; - Some(self.mk_generic_adt(def_id, ty)) - } - - #[inline] - pub fn mk_maybe_uninit(self, ty: Ty<'tcx>) -> Ty<'tcx> { - let def_id = self.require_lang_item(LangItem::MaybeUninit, None); - self.mk_generic_adt(def_id, ty) - } - - #[inline] - pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { - self.mk_ty_from_kind(RawPtr(tm)) - } - - #[inline] - pub fn mk_ref(self, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { - self.mk_ty_from_kind(Ref(r, tm.ty, tm.mutbl)) - } - - #[inline] - pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Mut }) - } - - #[inline] - pub fn mk_imm_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Not }) - } - - #[inline] - pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Mut }) - } - - #[inline] - pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Not }) - } - - #[inline] - pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> { - self.mk_ty_from_kind(Array(ty, ty::Const::from_target_usize(self, n))) - } - - #[inline] - pub fn mk_array_with_const_len(self, ty: Ty<'tcx>, ct: Const<'tcx>) -> Ty<'tcx> { - self.mk_ty_from_kind(Array(ty, ct)) - } - - #[inline] - pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ty_from_kind(Slice(ty)) - } - - #[inline] - pub fn mk_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> { - if ts.is_empty() { - self.types.unit - } else { - self.mk_ty_from_kind(Tuple(self.mk_type_list(&ts))) - } - } - - pub fn mk_tup_from_iter<I, T>(self, iter: I) -> T::Output - where - I: Iterator<Item = T>, - T: CollectAndApply<Ty<'tcx>, Ty<'tcx>>, - { - T::collect_and_apply(iter, |ts| self.mk_tup(ts)) - } - - #[inline] - pub fn mk_unit(self) -> Ty<'tcx> { - self.types.unit - } - - #[inline] - pub fn mk_diverging_default(self) -> Ty<'tcx> { - if self.features().never_type_fallback { self.types.never } else { self.types.unit } - } - - #[inline] - pub fn mk_fn_def( - self, - def_id: DefId, - substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, - ) -> Ty<'tcx> { - let substs = self.check_and_mk_substs(def_id, substs); - self.mk_ty_from_kind(FnDef(def_id, substs)) - } - #[inline(always)] - pub(crate) fn check_and_mk_substs( + pub(crate) fn check_and_mk_args( self, _def_id: DefId, - substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, - ) -> SubstsRef<'tcx> { - let substs = substs.into_iter().map(Into::into); + args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, + ) -> GenericArgsRef<'tcx> { + let args = args.into_iter().map(Into::into); #[cfg(debug_assertions)] { let generics = self.generics_of(_def_id); @@ -1842,140 +1642,29 @@ impl<'tcx> TyCtxt<'tcx> { }; assert_eq!( (n, Some(n)), - substs.size_hint(), + args.size_hint(), "wrong number of generic parameters for {_def_id:?}: {:?}", - substs.collect::<Vec<_>>(), + args.collect::<Vec<_>>(), ); } - self.mk_substs_from_iter(substs) - } - - #[inline] - pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { - self.mk_ty_from_kind(FnPtr(fty)) - } - - #[inline] - pub fn mk_dynamic( - self, - obj: &'tcx List<PolyExistentialPredicate<'tcx>>, - reg: ty::Region<'tcx>, - repr: DynKind, - ) -> Ty<'tcx> { - self.mk_ty_from_kind(Dynamic(obj, reg, repr)) - } - - #[inline] - pub fn mk_projection( - self, - item_def_id: DefId, - substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, - ) -> Ty<'tcx> { - self.mk_alias(ty::Projection, self.mk_alias_ty(item_def_id, substs)) - } - - #[inline] - pub fn mk_closure(self, def_id: DefId, closure_substs: SubstsRef<'tcx>) -> Ty<'tcx> { - debug_assert_eq!( - closure_substs.len(), - self.generics_of(self.typeck_root_def_id(def_id)).count() + 3, - "closure constructed with incorrect substitutions" - ); - self.mk_ty_from_kind(Closure(def_id, closure_substs)) - } - - #[inline] - pub fn mk_generator( - self, - def_id: DefId, - generator_substs: SubstsRef<'tcx>, - movability: hir::Movability, - ) -> Ty<'tcx> { - debug_assert_eq!( - generator_substs.len(), - self.generics_of(self.typeck_root_def_id(def_id)).count() + 5, - "generator constructed with incorrect number of substitutions" - ); - self.mk_ty_from_kind(Generator(def_id, generator_substs, movability)) - } - - #[inline] - pub fn mk_generator_witness(self, types: ty::Binder<'tcx, &'tcx List<Ty<'tcx>>>) -> Ty<'tcx> { - self.mk_ty_from_kind(GeneratorWitness(types)) - } - - /// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes. - pub fn mk_task_context(self) -> Ty<'tcx> { - let context_did = self.require_lang_item(LangItem::Context, None); - let context_adt_ref = self.adt_def(context_did); - let context_substs = self.mk_substs(&[self.lifetimes.re_erased.into()]); - let context_ty = self.mk_adt(context_adt_ref, context_substs); - self.mk_mut_ref(self.lifetimes.re_erased, context_ty) - } - - #[inline] - pub fn mk_generator_witness_mir(self, id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> { - self.mk_ty_from_kind(GeneratorWitnessMIR(id, substs)) - } - - #[inline] - pub fn mk_const(self, kind: impl Into<ty::ConstKind<'tcx>>, ty: Ty<'tcx>) -> Const<'tcx> { - self.intern_const(ty::ConstData { kind: kind.into(), ty }) - } - - #[inline] - pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> { - // Use a pre-interned one when possible. - self.types - .ty_vars - .get(v.as_usize()) - .copied() - .unwrap_or_else(|| self.mk_ty_from_kind(Infer(TyVar(v)))) - } - - #[inline] - pub fn mk_int_var(self, v: IntVid) -> Ty<'tcx> { - self.mk_ty_from_kind(Infer(IntVar(v))) - } - - #[inline] - pub fn mk_float_var(self, v: FloatVid) -> Ty<'tcx> { - self.mk_ty_from_kind(Infer(FloatVar(v))) - } - - #[inline] - pub fn mk_fresh_ty(self, n: u32) -> Ty<'tcx> { - // Use a pre-interned one when possible. - self.types - .fresh_tys - .get(n as usize) - .copied() - .unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshTy(n)))) - } - - #[inline] - pub fn mk_fresh_int_ty(self, n: u32) -> Ty<'tcx> { - // Use a pre-interned one when possible. - self.types - .fresh_int_tys - .get(n as usize) - .copied() - .unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshIntTy(n)))) + self.mk_args_from_iter(args) } #[inline] - pub fn mk_fresh_float_ty(self, n: u32) -> Ty<'tcx> { - // Use a pre-interned one when possible. - self.types - .fresh_float_tys - .get(n as usize) - .copied() - .unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshFloatTy(n)))) + pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + self.intern_const(ty::ConstData { kind, ty }) } + // Avoid this in favour of more specific `Ty::new_*` methods, where possible. + #[allow(rustc::usage_of_ty_tykind)] #[inline] - pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> { - self.mk_ty_from_kind(Param(ParamTy { index, name })) + pub fn mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx> { + self.interners.intern_ty( + st, + self.sess, + // This is only used to create a stable hashing context. + &self.untracked, + ) } pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> { @@ -1983,44 +1672,18 @@ impl<'tcx> TyCtxt<'tcx> { GenericParamDefKind::Lifetime => { ty::Region::new_early_bound(self, param.to_early_bound_region_data()).into() } - GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(), - GenericParamDefKind::Const { .. } => self - .mk_const( - ParamConst { index: param.index, name: param.name }, - self.type_of(param.def_id) - .no_bound_vars() - .expect("const parameter types cannot be generic"), - ) - .into(), + GenericParamDefKind::Type { .. } => Ty::new_param(self, param.index, param.name).into(), + GenericParamDefKind::Const { .. } => ty::Const::new_param( + self, + ParamConst { index: param.index, name: param.name }, + self.type_of(param.def_id) + .no_bound_vars() + .expect("const parameter types cannot be generic"), + ) + .into(), } } - #[inline] - pub fn mk_bound(self, index: ty::DebruijnIndex, bound_ty: ty::BoundTy) -> Ty<'tcx> { - self.mk_ty_from_kind(Bound(index, bound_ty)) - } - - #[inline] - pub fn mk_placeholder(self, placeholder: ty::PlaceholderType) -> Ty<'tcx> { - self.mk_ty_from_kind(Placeholder(placeholder)) - } - - #[inline] - pub fn mk_alias(self, kind: ty::AliasKind, alias_ty: ty::AliasTy<'tcx>) -> Ty<'tcx> { - debug_assert_matches!( - (kind, self.def_kind(alias_ty.def_id)), - (ty::Opaque, DefKind::OpaqueTy) - | (ty::Projection | ty::Inherent, DefKind::AssocTy) - | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder) - ); - self.mk_ty_from_kind(Alias(kind, alias_ty)) - } - - #[inline] - pub fn mk_opaque(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> { - self.mk_alias(ty::Opaque, self.mk_alias_ty(def_id, substs)) - } - pub fn mk_place_field(self, place: Place<'tcx>, f: FieldIdx, ty: Ty<'tcx>) -> Place<'tcx> { self.mk_place_elem(place, PlaceElem::Field(f, ty)) } @@ -2076,11 +1739,11 @@ impl<'tcx> TyCtxt<'tcx> { self.intern_poly_existential_predicates(eps) } - pub fn mk_predicates(self, preds: &[Predicate<'tcx>]) -> &'tcx List<Predicate<'tcx>> { + pub fn mk_clauses(self, clauses: &[Clause<'tcx>]) -> &'tcx List<Clause<'tcx>> { // FIXME consider asking the input slice to be sorted to avoid // re-interning permutations, in which case that would be asserted // here. - self.intern_predicates(preds) + self.intern_clauses(clauses) } pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output @@ -2126,12 +1789,12 @@ impl<'tcx> TyCtxt<'tcx> { T::collect_and_apply(iter, |xs| self.mk_poly_existential_predicates(xs)) } - pub fn mk_predicates_from_iter<I, T>(self, iter: I) -> T::Output + pub fn mk_clauses_from_iter<I, T>(self, iter: I) -> T::Output where I: Iterator<Item = T>, - T: CollectAndApply<Predicate<'tcx>, &'tcx List<Predicate<'tcx>>>, + T: CollectAndApply<Clause<'tcx>, &'tcx List<Clause<'tcx>>>, { - T::collect_and_apply(iter, |xs| self.mk_predicates(xs)) + T::collect_and_apply(iter, |xs| self.mk_clauses(xs)) } pub fn mk_type_list_from_iter<I, T>(self, iter: I) -> T::Output @@ -2142,12 +1805,12 @@ impl<'tcx> TyCtxt<'tcx> { T::collect_and_apply(iter, |xs| self.mk_type_list(xs)) } - pub fn mk_substs_from_iter<I, T>(self, iter: I) -> T::Output + pub fn mk_args_from_iter<I, T>(self, iter: I) -> T::Output where I: Iterator<Item = T>, T: CollectAndApply<GenericArg<'tcx>, &'tcx List<GenericArg<'tcx>>>, { - T::collect_and_apply(iter, |xs| self.mk_substs(xs)) + T::collect_and_apply(iter, |xs| self.mk_args(xs)) } pub fn mk_canonical_var_infos_from_iter<I, T>(self, iter: I) -> T::Output @@ -2174,21 +1837,21 @@ impl<'tcx> TyCtxt<'tcx> { T::collect_and_apply(iter, |xs| self.mk_fields(xs)) } - pub fn mk_substs_trait( + pub fn mk_args_trait( self, self_ty: Ty<'tcx>, rest: impl IntoIterator<Item = GenericArg<'tcx>>, - ) -> SubstsRef<'tcx> { - self.mk_substs_from_iter(iter::once(self_ty.into()).chain(rest)) + ) -> GenericArgsRef<'tcx> { + self.mk_args_from_iter(iter::once(self_ty.into()).chain(rest)) } pub fn mk_alias_ty( self, def_id: DefId, - substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, + args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, ) -> ty::AliasTy<'tcx> { - let substs = self.check_and_mk_substs(def_id, substs); - ty::AliasTy { def_id, substs, _use_mk_alias_ty_instead: () } + let args = self.check_and_mk_args(def_id, args); + ty::AliasTy { def_id, args, _use_mk_alias_ty_instead: () } } pub fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output @@ -2201,6 +1864,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`, /// typically generated by `#[derive(LintDiagnostic)]`). + #[track_caller] pub fn emit_spanned_lint( self, lint: &'static Lint, @@ -2221,6 +1885,7 @@ impl<'tcx> TyCtxt<'tcx> { /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature #[rustc_lint_diagnostics] + #[track_caller] pub fn struct_span_lint_hir( self, lint: &'static Lint, @@ -2237,6 +1902,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically /// generated by `#[derive(LintDiagnostic)]`). + #[track_caller] pub fn emit_lint( self, lint: &'static Lint, @@ -2252,6 +1918,7 @@ impl<'tcx> TyCtxt<'tcx> { /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature #[rustc_lint_diagnostics] + #[track_caller] pub fn struct_lint_node( self, lint: &'static Lint, @@ -2345,16 +2012,8 @@ impl<'tcx> TyCtxt<'tcx> { ) } - pub fn lower_impl_trait_in_trait_to_assoc_ty(self) -> bool { - self.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty - } - pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { - if self.lower_impl_trait_in_trait_to_assoc_ty() { - self.opt_rpitit_info(def_id).is_some() - } else { - self.def_kind(def_id) == DefKind::ImplTraitPlaceholder - } + self.opt_rpitit_info(def_id).is_some() } /// Named module children from all kinds of items, including imports. @@ -2371,21 +2030,6 @@ impl<'tcx> TyCtxt<'tcx> { } } -impl<'tcx> TyCtxtAt<'tcx> { - /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. - #[track_caller] - pub fn ty_error_misc(self) -> Ty<'tcx> { - self.tcx.ty_error_with_message(self.span, "TyKind::Error constructed but no error reported") - } - - /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to - /// ensure it gets used. - #[track_caller] - pub fn ty_error_with_message(self, msg: impl Into<DiagnosticMessage>) -> Ty<'tcx> { - self.tcx.ty_error_with_message(self.span, msg) - } -} - /// Parameter attributes that can only be determined by examining the body of a function instead /// of just its signature. /// diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index d89baa9c88d..905e855896e 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -71,7 +71,7 @@ impl<'tcx> Ty<'tcx> { /// ADTs with no type arguments. pub fn is_simple_text(self) -> bool { match self.kind() { - Adt(_, substs) => substs.non_erasable_generics().next().is_none(), + Adt(_, args) => args.non_erasable_generics().next().is_none(), Ref(_, ty, _) => ty.is_simple_text(), _ => self.is_simple_ty(), } @@ -491,7 +491,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> { Alias(Opaque, AliasTy { def_id, .. }) => { let parent = self.tcx.parent(def_id); - let parent_ty = self.tcx.type_of(parent).subst_identity(); + let parent_ty = self.tcx.type_of(parent).instantiate_identity(); if let DefKind::TyAlias | DefKind::AssocTy = self.tcx.def_kind(parent) && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind() && parent_opaque_def_id == def_id @@ -558,8 +558,8 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> { let t = match *t.kind() { Infer(InferTy::TyVar(_)) if self.infer_suggestable => t, - FnDef(def_id, substs) => { - self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs)) + FnDef(def_id, args) => { + Ty::new_fn_ptr(self.tcx, self.tcx.fn_sig(def_id).instantiate(self.tcx, args)) } // FIXME(compiler-errors): We could replace these with infer, I guess. @@ -575,7 +575,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> { Alias(Opaque, AliasTy { def_id, .. }) => { let parent = self.tcx.parent(def_id); - let parent_ty = self.tcx.type_of(parent).subst_identity(); + let parent_ty = self.tcx.type_of(parent).instantiate_identity(); if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent) && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind() && parent_opaque_def_id == def_id diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 66293f19eef..c794c3faded 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -300,6 +300,7 @@ impl<'tcx> Ty<'tcx> { ty::Placeholder(..) => "higher-ranked type".into(), ty::Bound(..) => "bound type variable".into(), ty::Alias(ty::Projection | ty::Inherent, _) => "associated type".into(), + ty::Alias(ty::Weak, _) => "type alias".into(), ty::Param(_) => "type parameter".into(), ty::Alias(ty::Opaque, ..) => "opaque type".into(), } diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 76f61d9ac9c..668aa4521c1 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -1,40 +1,38 @@ use crate::mir::Mutability; -use crate::ty::subst::GenericArgKind; -use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeVisitableExt}; +use crate::ty::GenericArgKind; +use crate::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt}; use rustc_hir::def_id::DefId; use std::fmt::Debug; use std::hash::Hash; use std::iter; -use self::SimplifiedType::*; - /// See `simplify_type`. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] pub enum SimplifiedType { - BoolSimplifiedType, - CharSimplifiedType, - IntSimplifiedType(ty::IntTy), - UintSimplifiedType(ty::UintTy), - FloatSimplifiedType(ty::FloatTy), - AdtSimplifiedType(DefId), - ForeignSimplifiedType(DefId), - StrSimplifiedType, - ArraySimplifiedType, - SliceSimplifiedType, - RefSimplifiedType(Mutability), - PtrSimplifiedType(Mutability), - NeverSimplifiedType, - TupleSimplifiedType(usize), + Bool, + Char, + Int(ty::IntTy), + Uint(ty::UintTy), + Float(ty::FloatTy), + Adt(DefId), + Foreign(DefId), + Str, + Array, + Slice, + Ref(Mutability), + Ptr(Mutability), + Never, + Tuple(usize), /// A trait object, all of whose components are markers /// (e.g., `dyn Send + Sync`). - MarkerTraitObjectSimplifiedType, - TraitSimplifiedType(DefId), - ClosureSimplifiedType(DefId), - GeneratorSimplifiedType(DefId), - GeneratorWitnessSimplifiedType(usize), - GeneratorWitnessMIRSimplifiedType(DefId), - FunctionSimplifiedType(usize), - PlaceholderSimplifiedType, + MarkerTraitObject, + Trait(DefId), + Closure(DefId), + Generator(DefId), + GeneratorWitness(usize), + GeneratorWitnessMIR(DefId), + Function(usize), + Placeholder, } /// Generic parameters are pretty much just bound variables, e.g. @@ -64,6 +62,9 @@ pub enum TreatParams { /// correct mode for *lookup*, as during candidate selection. /// /// N.B. during deep rejection, this acts identically to `ForLookup`. + /// + /// FIXME(-Ztrait-solver=next): Remove this variant and cleanup + /// the code. NextSolverLookup, } @@ -110,34 +111,36 @@ pub fn simplify_type<'tcx>( treat_params: TreatParams, ) -> Option<SimplifiedType> { match *ty.kind() { - ty::Bool => Some(BoolSimplifiedType), - ty::Char => Some(CharSimplifiedType), - ty::Int(int_type) => Some(IntSimplifiedType(int_type)), - ty::Uint(uint_type) => Some(UintSimplifiedType(uint_type)), - ty::Float(float_type) => Some(FloatSimplifiedType(float_type)), - ty::Adt(def, _) => Some(AdtSimplifiedType(def.did())), - ty::Str => Some(StrSimplifiedType), - ty::Array(..) => Some(ArraySimplifiedType), - ty::Slice(..) => Some(SliceSimplifiedType), - ty::RawPtr(ptr) => Some(PtrSimplifiedType(ptr.mutbl)), + ty::Bool => Some(SimplifiedType::Bool), + ty::Char => Some(SimplifiedType::Char), + ty::Int(int_type) => Some(SimplifiedType::Int(int_type)), + ty::Uint(uint_type) => Some(SimplifiedType::Uint(uint_type)), + ty::Float(float_type) => Some(SimplifiedType::Float(float_type)), + ty::Adt(def, _) => Some(SimplifiedType::Adt(def.did())), + ty::Str => Some(SimplifiedType::Str), + ty::Array(..) => Some(SimplifiedType::Array), + ty::Slice(..) => Some(SimplifiedType::Slice), + ty::RawPtr(ptr) => Some(SimplifiedType::Ptr(ptr.mutbl)), ty::Dynamic(trait_info, ..) => match trait_info.principal_def_id() { Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => { - Some(TraitSimplifiedType(principal_def_id)) + Some(SimplifiedType::Trait(principal_def_id)) } - _ => Some(MarkerTraitObjectSimplifiedType), + _ => Some(SimplifiedType::MarkerTraitObject), }, - ty::Ref(_, _, mutbl) => Some(RefSimplifiedType(mutbl)), - ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(ClosureSimplifiedType(def_id)), - ty::Generator(def_id, _, _) => Some(GeneratorSimplifiedType(def_id)), - ty::GeneratorWitness(tys) => Some(GeneratorWitnessSimplifiedType(tys.skip_binder().len())), - ty::GeneratorWitnessMIR(def_id, _) => Some(GeneratorWitnessMIRSimplifiedType(def_id)), - ty::Never => Some(NeverSimplifiedType), - ty::Tuple(tys) => Some(TupleSimplifiedType(tys.len())), - ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())), - ty::Placeholder(..) => Some(PlaceholderSimplifiedType), + ty::Ref(_, _, mutbl) => Some(SimplifiedType::Ref(mutbl)), + ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(SimplifiedType::Closure(def_id)), + ty::Generator(def_id, _, _) => Some(SimplifiedType::Generator(def_id)), + ty::GeneratorWitness(tys) => { + Some(SimplifiedType::GeneratorWitness(tys.skip_binder().len())) + } + ty::GeneratorWitnessMIR(def_id, _) => Some(SimplifiedType::GeneratorWitnessMIR(def_id)), + ty::Never => Some(SimplifiedType::Never), + ty::Tuple(tys) => Some(SimplifiedType::Tuple(tys.len())), + ty::FnPtr(f) => Some(SimplifiedType::Function(f.skip_binder().inputs().len())), + ty::Placeholder(..) => Some(SimplifiedType::Placeholder), ty::Param(_) => match treat_params { TreatParams::ForLookup | TreatParams::NextSolverLookup => { - Some(PlaceholderSimplifiedType) + Some(SimplifiedType::Placeholder) } TreatParams::AsCandidateKey => None, }, @@ -147,11 +150,13 @@ pub fn simplify_type<'tcx>( // // We will have to be careful with lazy normalization here. // FIXME(lazy_normalization): This is probably not right... - TreatParams::ForLookup if !ty.has_non_region_infer() => Some(PlaceholderSimplifiedType), - TreatParams::NextSolverLookup => Some(PlaceholderSimplifiedType), + TreatParams::ForLookup if !ty.has_non_region_infer() => { + Some(SimplifiedType::Placeholder) + } + TreatParams::NextSolverLookup => Some(SimplifiedType::Placeholder), TreatParams::ForLookup | TreatParams::AsCandidateKey => None, }, - ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)), + ty::Foreign(def_id) => Some(SimplifiedType::Foreign(def_id)), ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None, } } @@ -159,12 +164,12 @@ pub fn simplify_type<'tcx>( impl SimplifiedType { pub fn def(self) -> Option<DefId> { match self { - AdtSimplifiedType(d) - | ForeignSimplifiedType(d) - | TraitSimplifiedType(d) - | ClosureSimplifiedType(d) - | GeneratorSimplifiedType(d) - | GeneratorWitnessMIRSimplifiedType(d) => Some(d), + SimplifiedType::Adt(d) + | SimplifiedType::Foreign(d) + | SimplifiedType::Trait(d) + | SimplifiedType::Closure(d) + | SimplifiedType::Generator(d) + | SimplifiedType::GeneratorWitnessMIR(d) => Some(d), _ => None, } } @@ -188,12 +193,12 @@ pub struct DeepRejectCtxt { } impl DeepRejectCtxt { - pub fn substs_refs_may_unify<'tcx>( + pub fn args_refs_may_unify<'tcx>( self, - obligation_substs: SubstsRef<'tcx>, - impl_substs: SubstsRef<'tcx>, + obligation_args: GenericArgsRef<'tcx>, + impl_args: GenericArgsRef<'tcx>, ) -> bool { - iter::zip(obligation_substs, impl_substs).all(|(obl, imp)| { + iter::zip(obligation_args, impl_args).all(|(obl, imp)| { match (obl.unpack(), imp.unpack()) { // We don't fast reject based on regions for now. (GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => true, @@ -258,9 +263,9 @@ impl DeepRejectCtxt { } _ => false, }, - ty::Adt(obl_def, obl_substs) => match k { - &ty::Adt(impl_def, impl_substs) => { - obl_def == impl_def && self.substs_refs_may_unify(obl_substs, impl_substs) + ty::Adt(obl_def, obl_args) => match k { + &ty::Adt(impl_def, impl_args) => { + obl_def == impl_def && self.args_refs_may_unify(obl_args, impl_args) } _ => false, }, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index d64875a9f00..bbd4a623330 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -1,5 +1,5 @@ -use crate::ty::subst::{GenericArg, GenericArgKind}; use crate::ty::{self, InferConst, Ty, TypeFlags}; +use crate::ty::{GenericArg, GenericArgKind}; use std::slice; #[derive(Debug)] @@ -105,48 +105,48 @@ impl FlagComputation { self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } - ty::Generator(_, substs, _) => { - let substs = substs.as_generator(); + ty::Generator(_, args, _) => { + let args = args.as_generator(); let should_remove_further_specializable = !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); - self.add_substs(substs.parent_substs()); + self.add_args(args.parent_args()); if should_remove_further_specializable { self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE; } - self.add_ty(substs.resume_ty()); - self.add_ty(substs.return_ty()); - self.add_ty(substs.witness()); - self.add_ty(substs.yield_ty()); - self.add_ty(substs.tupled_upvars_ty()); + self.add_ty(args.resume_ty()); + self.add_ty(args.return_ty()); + self.add_ty(args.witness()); + self.add_ty(args.yield_ty()); + self.add_ty(args.tupled_upvars_ty()); } &ty::GeneratorWitness(ts) => { self.bound_computation(ts, |flags, ts| flags.add_tys(ts)); } - ty::GeneratorWitnessMIR(_, substs) => { + ty::GeneratorWitnessMIR(_, args) => { let should_remove_further_specializable = !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); - self.add_substs(substs); + self.add_args(args); if should_remove_further_specializable { self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE; } self.add_flags(TypeFlags::HAS_TY_GENERATOR); } - &ty::Closure(_, substs) => { - let substs = substs.as_closure(); + &ty::Closure(_, args) => { + let args = args.as_closure(); let should_remove_further_specializable = !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); - self.add_substs(substs.parent_substs()); + self.add_args(args.parent_args()); if should_remove_further_specializable { self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE; } - self.add_ty(substs.sig_as_fn_ptr_ty()); - self.add_ty(substs.kind_ty()); - self.add_ty(substs.tupled_upvars_ty()); + self.add_ty(args.sig_as_fn_ptr_ty()); + self.add_ty(args.kind_ty()); + self.add_ty(args.tupled_upvars_ty()); } &ty::Bound(debruijn, _) => { @@ -172,13 +172,13 @@ impl FlagComputation { } } - &ty::Adt(_, substs) => { - self.add_substs(substs); + &ty::Adt(_, args) => { + self.add_args(args); } &ty::Alias(kind, data) => { self.add_flags(match kind { - ty::Projection => TypeFlags::HAS_TY_PROJECTION, + ty::Weak | ty::Projection => TypeFlags::HAS_TY_PROJECTION, ty::Inherent => TypeFlags::HAS_TY_INHERENT, ty::Opaque => TypeFlags::HAS_TY_OPAQUE, }); @@ -189,7 +189,7 @@ impl FlagComputation { &ty::Dynamic(obj, r, _) => { for predicate in obj.iter() { self.bound_computation(predicate, |computation, predicate| match predicate { - ty::ExistentialPredicate::Trait(tr) => computation.add_substs(tr.substs), + ty::ExistentialPredicate::Trait(tr) => computation.add_args(tr.args), ty::ExistentialPredicate::Projection(p) => { computation.add_existential_projection(&p); } @@ -220,8 +220,8 @@ impl FlagComputation { self.add_tys(types); } - &ty::FnDef(_, substs) => { - self.add_substs(substs); + &ty::FnDef(_, args) => { + self.add_args(args); } &ty::FnPtr(fn_sig) => self.bound_computation(fn_sig, |computation, fn_sig| { @@ -237,21 +237,24 @@ impl FlagComputation { fn add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>) { match atom { - ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => { - self.add_substs(trait_pred.trait_ref.substs); + ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => { + self.add_args(trait_pred.trait_ref.args); } - ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(a, b))) => { + ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate( + a, + b, + ))) => { self.add_region(a); self.add_region(b); } - ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate( + ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( ty, region, ))) => { self.add_ty(ty); self.add_region(region); } - ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { self.add_const(ct); self.add_ty(ty); } @@ -263,30 +266,27 @@ impl FlagComputation { self.add_ty(a); self.add_ty(b); } - ty::PredicateKind::Clause(ty::Clause::Projection(ty::ProjectionPredicate { + ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term, })) => { self.add_alias_ty(projection_ty); self.add_term(term); } - ty::PredicateKind::WellFormed(arg) => { - self.add_substs(slice::from_ref(&arg)); + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { + self.add_args(slice::from_ref(&arg)); } ty::PredicateKind::ObjectSafe(_def_id) => {} - ty::PredicateKind::ClosureKind(_def_id, substs, _kind) => { - self.add_substs(substs); + ty::PredicateKind::ClosureKind(_def_id, args, _kind) => { + self.add_args(args); } - ty::PredicateKind::ConstEvaluatable(uv) => { + ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => { self.add_const(uv); } ty::PredicateKind::ConstEquate(expected, found) => { self.add_const(expected); self.add_const(found); } - ty::PredicateKind::TypeWellFormedFromEnv(ty) => { - self.add_ty(ty); - } ty::PredicateKind::Ambiguous => {} ty::PredicateKind::AliasRelate(t1, t2, _) => { self.add_term(t1); @@ -317,7 +317,7 @@ impl FlagComputation { self.add_ty(c.ty()); match c.kind() { ty::ConstKind::Unevaluated(uv) => { - self.add_substs(uv.substs); + self.add_args(uv.args); self.add_flags(TypeFlags::HAS_CT_PROJECTION); } ty::ConstKind::Infer(infer) => { @@ -365,7 +365,7 @@ impl FlagComputation { } fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) { - self.add_substs(projection.substs); + self.add_args(projection.args); match projection.term.unpack() { ty::TermKind::Ty(ty) => self.add_ty(ty), ty::TermKind::Const(ct) => self.add_const(ct), @@ -373,11 +373,11 @@ impl FlagComputation { } fn add_alias_ty(&mut self, alias_ty: ty::AliasTy<'_>) { - self.add_substs(alias_ty.substs); + self.add_args(alias_ty.args); } - fn add_substs(&mut self, substs: &[GenericArg<'_>]) { - for kind in substs { + fn add_args(&mut self, args: &[GenericArg<'_>]) { + for kind in args { match kind.unpack() { GenericArgKind::Type(ty) => self.add_ty(ty), GenericArgKind::Lifetime(lt) => self.add_region(lt), diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 149ce29b8d9..77cf6bee79d 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -348,10 +348,14 @@ impl<'tcx> TyCtxt<'tcx> { ) }, types: &mut |t: ty::BoundTy| { - self.mk_bound(ty::INNERMOST, ty::BoundTy { var: shift_bv(t.var), kind: t.kind }) + Ty::new_bound( + self, + ty::INNERMOST, + ty::BoundTy { var: shift_bv(t.var), kind: t.kind }, + ) }, consts: &mut |c, ty: Ty<'tcx>| { - self.mk_const(ty::ConstKind::Bound(ty::INNERMOST, shift_bv(c)), ty) + ty::Const::new_bound(self, ty::INNERMOST, shift_bv(c), ty) }, }, ) @@ -393,14 +397,14 @@ impl<'tcx> TyCtxt<'tcx> { let kind = entry .or_insert_with(|| ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon)) .expect_ty(); - self.tcx.mk_bound(ty::INNERMOST, BoundTy { var, kind }) + Ty::new_bound(self.tcx, ty::INNERMOST, BoundTy { var, kind }) } fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> { let entry = self.map.entry(bv); let index = entry.index(); let var = ty::BoundVar::from_usize(index); let () = entry.or_insert_with(|| ty::BoundVariableKind::Const).expect_const(); - self.tcx.mk_const(ty::ConstKind::Bound(ty::INNERMOST, var), ty) + ty::Const::new_bound(self.tcx, ty::INNERMOST, var, ty) } } @@ -462,7 +466,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> { match *ty.kind() { ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => { let debruijn = debruijn.shifted_in(self.amount); - self.tcx.mk_bound(debruijn, bound_ty) + Ty::new_bound(self.tcx, debruijn, bound_ty) } _ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self), @@ -475,7 +479,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> { && debruijn >= self.current_index { let debruijn = debruijn.shifted_in(self.amount); - self.tcx.mk_const(ty::ConstKind::Bound(debruijn, bound_ct), ct.ty()) + ty::Const::new_bound(self.tcx, debruijn, bound_ct, ct.ty()) } else { ct.super_fold_with(self) } diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 8685a22d9ca..97dab5cb47e 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -1,8 +1,8 @@ -// Type substitutions. +// Generic arguments. use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; -use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts}; +use crate::ty::sty::{ClosureArgs, GeneratorArgs, InlineConstArgs}; use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; @@ -11,12 +11,12 @@ use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_serialize::{self, Decodable, Encodable}; +use rustc_span::sym; use rustc_type_ir::WithCachedTypeInfo; use smallvec::SmallVec; use core::intrinsics; use std::cmp::Ordering; -use std::fmt; use std::marker::PhantomData; use std::mem; use std::num::NonZeroUsize; @@ -79,16 +79,6 @@ impl<'tcx> GenericArgKind<'tcx> { } } -impl<'tcx> fmt::Debug for GenericArg<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.unpack() { - GenericArgKind::Lifetime(lt) => lt.fmt(f), - GenericArgKind::Type(ty) => ty.fmt(f), - GenericArgKind::Const(ct) => ct.fmt(f), - } - } -} - impl<'tcx> Ord for GenericArg<'tcx> { fn cmp(&self, other: &GenericArg<'tcx>) -> Ordering { self.unpack().cmp(&other.unpack()) @@ -184,7 +174,7 @@ impl<'tcx> GenericArg<'tcx> { } /// Unpack the `GenericArg` as a type when it is known certainly to be a type. - /// This is true in cases where `Substs` is used in places where the kinds are known + /// This is true in cases where `GenericArgs` is used in places where the kinds are known /// to be limited (e.g. in tuples, where the only parameters are type parameters). pub fn expect_ty(self) -> Ty<'tcx> { self.as_type().unwrap_or_else(|| bug!("expected a type, but found another kind")) @@ -251,13 +241,13 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for GenericArg<'tcx> { } } -/// List of generic arguments that are gonna be used to substitute generic parameters. -pub type InternalSubsts<'tcx> = List<GenericArg<'tcx>>; +/// List of generic arguments that are gonna be used to replace generic parameters. +pub type GenericArgs<'tcx> = List<GenericArg<'tcx>>; -pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>; +pub type GenericArgsRef<'tcx> = &'tcx GenericArgs<'tcx>; -impl<'tcx> InternalSubsts<'tcx> { - /// Converts substs to a type list. +impl<'tcx> GenericArgs<'tcx> { + /// Converts generic args to a type list. /// /// # Panics /// @@ -265,66 +255,71 @@ impl<'tcx> InternalSubsts<'tcx> { pub fn into_type_list(&self, tcx: TyCtxt<'tcx>) -> &'tcx List<Ty<'tcx>> { tcx.mk_type_list_from_iter(self.iter().map(|arg| match arg.unpack() { GenericArgKind::Type(ty) => ty, - _ => bug!("`into_type_list` called on substs with non-types"), + _ => bug!("`into_type_list` called on generic arg with non-types"), })) } - /// Interpret these substitutions as the substitutions of a closure type. - /// Closure substitutions have a particular structure controlled by the + /// Interpret these generic args as the args of a closure type. + /// Closure args have a particular structure controlled by the /// compiler that encodes information like the signature and closure kind; - /// see `ty::ClosureSubsts` struct for more comments. - pub fn as_closure(&'tcx self) -> ClosureSubsts<'tcx> { - ClosureSubsts { substs: self } + /// see `ty::ClosureArgs` struct for more comments. + pub fn as_closure(&'tcx self) -> ClosureArgs<'tcx> { + ClosureArgs { args: self } } - /// Interpret these substitutions as the substitutions of a generator type. - /// Generator substitutions have a particular structure controlled by the + /// Interpret these generic args as the args of a generator type. + /// Generator args have a particular structure controlled by the /// compiler that encodes information like the signature and generator kind; - /// see `ty::GeneratorSubsts` struct for more comments. - pub fn as_generator(&'tcx self) -> GeneratorSubsts<'tcx> { - GeneratorSubsts { substs: self } + /// see `ty::GeneratorArgs` struct for more comments. + pub fn as_generator(&'tcx self) -> GeneratorArgs<'tcx> { + GeneratorArgs { args: self } } - /// Interpret these substitutions as the substitutions of an inline const. - /// Inline const substitutions have a particular structure controlled by the + /// Interpret these generic args as the args of an inline const. + /// Inline const args have a particular structure controlled by the /// compiler that encodes information like the inferred type; - /// see `ty::InlineConstSubsts` struct for more comments. - pub fn as_inline_const(&'tcx self) -> InlineConstSubsts<'tcx> { - InlineConstSubsts { substs: self } + /// see `ty::InlineConstArgs` struct for more comments. + pub fn as_inline_const(&'tcx self) -> InlineConstArgs<'tcx> { + InlineConstArgs { args: self } } - /// Creates an `InternalSubsts` that maps each generic parameter to itself. - pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: impl Into<DefId>) -> SubstsRef<'tcx> { + /// Creates an `GenericArgs` that maps each generic parameter to itself. + pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: impl Into<DefId>) -> GenericArgsRef<'tcx> { Self::for_item(tcx, def_id.into(), |param, _| tcx.mk_param_from_def(param)) } - /// Creates an `InternalSubsts` for generic parameter definitions, + /// Creates an `GenericArgs` for generic parameter definitions, /// by calling closures to obtain each kind. - /// The closures get to observe the `InternalSubsts` as they're + /// The closures get to observe the `GenericArgs` as they're /// being built, which can be used to correctly - /// substitute defaults of generic parameters. - pub fn for_item<F>(tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) -> SubstsRef<'tcx> + /// replace defaults of generic parameters. + pub fn for_item<F>(tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) -> GenericArgsRef<'tcx> where F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>, { let defs = tcx.generics_of(def_id); let count = defs.count(); - let mut substs = SmallVec::with_capacity(count); - Self::fill_item(&mut substs, tcx, defs, &mut mk_kind); - tcx.mk_substs(&substs) + let mut args = SmallVec::with_capacity(count); + Self::fill_item(&mut args, tcx, defs, &mut mk_kind); + tcx.mk_args(&args) } - pub fn extend_to<F>(&self, tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) -> SubstsRef<'tcx> + pub fn extend_to<F>( + &self, + tcx: TyCtxt<'tcx>, + def_id: DefId, + mut mk_kind: F, + ) -> GenericArgsRef<'tcx> where F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>, { - Self::for_item(tcx, def_id, |param, substs| { - self.get(param.index as usize).cloned().unwrap_or_else(|| mk_kind(param, substs)) + Self::for_item(tcx, def_id, |param, args| { + self.get(param.index as usize).cloned().unwrap_or_else(|| mk_kind(param, args)) }) } pub fn fill_item<F>( - substs: &mut SmallVec<[GenericArg<'tcx>; 8]>, + args: &mut SmallVec<[GenericArg<'tcx>; 8]>, tcx: TyCtxt<'tcx>, defs: &ty::Generics, mk_kind: &mut F, @@ -333,38 +328,38 @@ impl<'tcx> InternalSubsts<'tcx> { { if let Some(def_id) = defs.parent { let parent_defs = tcx.generics_of(def_id); - Self::fill_item(substs, tcx, parent_defs, mk_kind); + Self::fill_item(args, tcx, parent_defs, mk_kind); } - Self::fill_single(substs, defs, mk_kind) + Self::fill_single(args, defs, mk_kind) } pub fn fill_single<F>( - substs: &mut SmallVec<[GenericArg<'tcx>; 8]>, + args: &mut SmallVec<[GenericArg<'tcx>; 8]>, defs: &ty::Generics, mk_kind: &mut F, ) where F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>, { - substs.reserve(defs.params.len()); + args.reserve(defs.params.len()); for param in &defs.params { - let kind = mk_kind(param, substs); - assert_eq!(param.index as usize, substs.len(), "{substs:#?}, {defs:#?}"); - substs.push(kind); + let kind = mk_kind(param, args); + assert_eq!(param.index as usize, args.len(), "{args:#?}, {defs:#?}"); + args.push(kind); } } - // Extend an `original_substs` list to the full number of substs expected by `def_id`, + // Extend an `original_args` list to the full number of args expected by `def_id`, // filling in the missing parameters with error ty/ct or 'static regions. pub fn extend_with_error( tcx: TyCtxt<'tcx>, def_id: DefId, - original_substs: &[GenericArg<'tcx>], - ) -> SubstsRef<'tcx> { - ty::InternalSubsts::for_item(tcx, def_id, |def, substs| { - if let Some(subst) = original_substs.get(def.index as usize) { - *subst + original_args: &[GenericArg<'tcx>], + ) -> GenericArgsRef<'tcx> { + ty::GenericArgs::for_item(tcx, def_id, |def, args| { + if let Some(arg) = original_args.get(def.index as usize) { + *arg } else { - def.to_error(tcx, substs) + def.to_error(tcx, args) } }) } @@ -420,9 +415,9 @@ impl<'tcx> InternalSubsts<'tcx> { self.type_at(def.index as usize).into() } - /// Transform from substitutions for a child of `source_ancestor` - /// (e.g., a trait or impl) to substitutions for the same child - /// in a different item, with `target_substs` as the base for + /// Transform from generic args for a child of `source_ancestor` + /// (e.g., a trait or impl) to args for the same child + /// in a different item, with `target_args` as the base for /// the target impl/trait, with the source child-specific /// parameters (e.g., method parameters) on top of that base. /// @@ -433,27 +428,31 @@ impl<'tcx> InternalSubsts<'tcx> { /// impl<U> X<U> for U { fn f<V>() {} } /// ``` /// - /// * If `self` is `[Self, S, T]`: the identity substs of `f` in the trait. + /// * If `self` is `[Self, S, T]`: the identity args of `f` in the trait. /// * If `source_ancestor` is the def_id of the trait. - /// * If `target_substs` is `[U]`, the substs for the impl. - /// * Then we will return `[U, T]`, the subst for `f` in the impl that + /// * If `target_args` is `[U]`, the args for the impl. + /// * Then we will return `[U, T]`, the arg for `f` in the impl that /// are needed for it to match the trait. pub fn rebase_onto( &self, tcx: TyCtxt<'tcx>, source_ancestor: DefId, - target_substs: SubstsRef<'tcx>, - ) -> SubstsRef<'tcx> { + target_args: GenericArgsRef<'tcx>, + ) -> GenericArgsRef<'tcx> { let defs = tcx.generics_of(source_ancestor); - tcx.mk_substs_from_iter(target_substs.iter().chain(self.iter().skip(defs.params.len()))) + tcx.mk_args_from_iter(target_args.iter().chain(self.iter().skip(defs.params.len()))) } - pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> SubstsRef<'tcx> { - tcx.mk_substs_from_iter(self.iter().take(generics.count())) + pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> GenericArgsRef<'tcx> { + tcx.mk_args_from_iter(self.iter().take(generics.count())) + } + + pub fn host_effect_param(&'tcx self) -> Option<ty::Const<'tcx>> { + self.consts().rfind(|x| matches!(x.kind(), ty::ConstKind::Param(p) if p.name == sym::host)) } } -impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for SubstsRef<'tcx> { +impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for GenericArgsRef<'tcx> { fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( self, folder: &mut F, @@ -462,16 +461,12 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for SubstsRef<'tcx> { // common length lists, to avoid the overhead of `SmallVec` creation. // The match arms are in order of frequency. The 1, 2, and 0 cases are // typically hit in 90--99.99% of cases. When folding doesn't change - // the substs, it's faster to reuse the existing substs rather than - // calling `mk_substs`. + // the args, it's faster to reuse the existing args rather than + // calling `mk_args`. match self.len() { 1 => { let param0 = self[0].try_fold_with(folder)?; - if param0 == self[0] { - Ok(self) - } else { - Ok(folder.interner().mk_substs(&[param0])) - } + if param0 == self[0] { Ok(self) } else { Ok(folder.interner().mk_args(&[param0])) } } 2 => { let param0 = self[0].try_fold_with(folder)?; @@ -479,11 +474,11 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for SubstsRef<'tcx> { if param0 == self[0] && param1 == self[1] { Ok(self) } else { - Ok(folder.interner().mk_substs(&[param0, param1])) + Ok(folder.interner().mk_args(&[param0, param1])) } } 0 => Ok(self), - _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_substs(v)), + _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_args(v)), } } } @@ -493,7 +488,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> { self, folder: &mut F, ) -> Result<Self, F::Error> { - // This code is fairly hot, though not as hot as `SubstsRef`. + // This code is fairly hot, though not as hot as `GenericArgsRef`. // // When compiling stage 2, I get the following results: // @@ -531,26 +526,28 @@ impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for &'tcx } /// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)` -/// needs `T` substituted immediately. This type primarily exists to avoid forgetting to call -/// `subst`. +/// needs `T` instantiated immediately. This type primarily exists to avoid forgetting to call +/// `instantiate`. /// -/// If you don't have anything to `subst`, you may be looking for -/// [`subst_identity`](EarlyBinder::subst_identity) or [`skip_binder`](EarlyBinder::skip_binder). +/// If you don't have anything to `instantiate`, you may be looking for +/// [`instantiate_identity`](EarlyBinder::instantiate_identity) or [`skip_binder`](EarlyBinder::skip_binder). #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Encodable, Decodable, HashStable)] -pub struct EarlyBinder<T>(T); +pub struct EarlyBinder<T> { + value: T, +} -/// For early binders, you should first call `subst` before using any visitors. +/// For early binders, you should first call `instantiate` before using any visitors. impl<'tcx, T> !TypeFoldable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {} impl<'tcx, T> !TypeVisitable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {} impl<T> EarlyBinder<T> { - pub fn bind(inner: T) -> EarlyBinder<T> { - EarlyBinder(inner) + pub fn bind(value: T) -> EarlyBinder<T> { + EarlyBinder { value } } pub fn as_ref(&self) -> EarlyBinder<&T> { - EarlyBinder(&self.0) + EarlyBinder { value: &self.value } } pub fn map_bound_ref<F, U>(&self, f: F) -> EarlyBinder<U> @@ -564,27 +561,27 @@ impl<T> EarlyBinder<T> { where F: FnOnce(T) -> U, { - let value = f(self.0); - EarlyBinder(value) + let value = f(self.value); + EarlyBinder { value } } pub fn try_map_bound<F, U, E>(self, f: F) -> Result<EarlyBinder<U>, E> where F: FnOnce(T) -> Result<U, E>, { - let value = f(self.0)?; - Ok(EarlyBinder(value)) + let value = f(self.value)?; + Ok(EarlyBinder { value }) } pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> { - EarlyBinder(value) + EarlyBinder { value } } /// Skips the binder and returns the "bound" value. /// This can be used to extract data that does not depend on generic parameters /// (e.g., getting the `DefId` of the inner value or getting the number of /// arguments of an `FnSig`). Otherwise, consider using - /// [`subst_identity`](EarlyBinder::subst_identity). + /// [`instantiate_identity`](EarlyBinder::instantiate_identity). /// /// To skip the binder on `x: &EarlyBinder<T>` to obtain `&T`, leverage /// [`EarlyBinder::as_ref`](EarlyBinder::as_ref): `x.as_ref().skip_binder()`. @@ -592,19 +589,20 @@ impl<T> EarlyBinder<T> { /// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is /// the analogous operation on [`super::Binder`]. pub fn skip_binder(self) -> T { - self.0 + self.value } } impl<T> EarlyBinder<Option<T>> { pub fn transpose(self) -> Option<EarlyBinder<T>> { - self.0.map(|v| EarlyBinder(v)) + self.value.map(|value| EarlyBinder { value }) } } impl<T, U> EarlyBinder<(T, U)> { pub fn transpose_tuple2(self) -> (EarlyBinder<T>, EarlyBinder<U>) { - (EarlyBinder(self.0.0), EarlyBinder(self.0.1)) + let EarlyBinder { value: (lhs, rhs) } = self; + (EarlyBinder { value: lhs }, EarlyBinder { value: rhs }) } } @@ -612,35 +610,35 @@ impl<'tcx, 's, I: IntoIterator> EarlyBinder<I> where I::Item: TypeFoldable<TyCtxt<'tcx>>, { - pub fn subst_iter( + pub fn iter_instantiated( self, tcx: TyCtxt<'tcx>, - substs: &'s [GenericArg<'tcx>], - ) -> SubstIter<'s, 'tcx, I> { - SubstIter { it: self.0.into_iter(), tcx, substs } + args: &'s [GenericArg<'tcx>], + ) -> IterInstantiated<'s, 'tcx, I> { + IterInstantiated { it: self.value.into_iter(), tcx, args } } - /// Similar to [`subst_identity`](EarlyBinder::subst_identity), + /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity), /// but on an iterator of `TypeFoldable` values. - pub fn subst_identity_iter(self) -> I::IntoIter { - self.0.into_iter() + pub fn instantiate_identity_iter(self) -> I::IntoIter { + self.value.into_iter() } } -pub struct SubstIter<'s, 'tcx, I: IntoIterator> { +pub struct IterInstantiated<'s, 'tcx, I: IntoIterator> { it: I::IntoIter, tcx: TyCtxt<'tcx>, - substs: &'s [GenericArg<'tcx>], + args: &'s [GenericArg<'tcx>], } -impl<'tcx, I: IntoIterator> Iterator for SubstIter<'_, 'tcx, I> +impl<'tcx, I: IntoIterator> Iterator for IterInstantiated<'_, 'tcx, I> where I::Item: TypeFoldable<TyCtxt<'tcx>>, { type Item = I::Item; fn next(&mut self) -> Option<Self::Item> { - Some(EarlyBinder(self.it.next()?).subst(self.tcx, self.substs)) + Some(EarlyBinder { value: self.it.next()? }.instantiate(self.tcx, self.args)) } fn size_hint(&self) -> (usize, Option<usize>) { @@ -648,17 +646,17 @@ where } } -impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIter<'_, 'tcx, I> +impl<'tcx, I: IntoIterator> DoubleEndedIterator for IterInstantiated<'_, 'tcx, I> where I::IntoIter: DoubleEndedIterator, I::Item: TypeFoldable<TyCtxt<'tcx>>, { fn next_back(&mut self) -> Option<Self::Item> { - Some(EarlyBinder(self.it.next_back()?).subst(self.tcx, self.substs)) + Some(EarlyBinder { value: self.it.next_back()? }.instantiate(self.tcx, self.args)) } } -impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIter<'_, 'tcx, I> +impl<'tcx, I: IntoIterator> ExactSizeIterator for IterInstantiated<'_, 'tcx, I> where I::IntoIter: ExactSizeIterator, I::Item: TypeFoldable<TyCtxt<'tcx>>, @@ -670,28 +668,30 @@ where I::Item: Deref, <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>, { - pub fn subst_iter_copied( + pub fn iter_instantiated_copied( self, tcx: TyCtxt<'tcx>, - substs: &'s [GenericArg<'tcx>], - ) -> SubstIterCopied<'s, 'tcx, I> { - SubstIterCopied { it: self.0.into_iter(), tcx, substs } + args: &'s [GenericArg<'tcx>], + ) -> IterInstantiatedCopied<'s, 'tcx, I> { + IterInstantiatedCopied { it: self.value.into_iter(), tcx, args } } - /// Similar to [`subst_identity`](EarlyBinder::subst_identity), + /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity), /// but on an iterator of values that deref to a `TypeFoldable`. - pub fn subst_identity_iter_copied(self) -> impl Iterator<Item = <I::Item as Deref>::Target> { - self.0.into_iter().map(|v| *v) + pub fn instantiate_identity_iter_copied( + self, + ) -> impl Iterator<Item = <I::Item as Deref>::Target> { + self.value.into_iter().map(|v| *v) } } -pub struct SubstIterCopied<'a, 'tcx, I: IntoIterator> { +pub struct IterInstantiatedCopied<'a, 'tcx, I: IntoIterator> { it: I::IntoIter, tcx: TyCtxt<'tcx>, - substs: &'a [GenericArg<'tcx>], + args: &'a [GenericArg<'tcx>], } -impl<'tcx, I: IntoIterator> Iterator for SubstIterCopied<'_, 'tcx, I> +impl<'tcx, I: IntoIterator> Iterator for IterInstantiatedCopied<'_, 'tcx, I> where I::Item: Deref, <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>, @@ -699,7 +699,7 @@ where type Item = <I::Item as Deref>::Target; fn next(&mut self) -> Option<Self::Item> { - Some(EarlyBinder(*self.it.next()?).subst(self.tcx, self.substs)) + self.it.next().map(|value| EarlyBinder { value: *value }.instantiate(self.tcx, self.args)) } fn size_hint(&self) -> (usize, Option<usize>) { @@ -707,18 +707,20 @@ where } } -impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIterCopied<'_, 'tcx, I> +impl<'tcx, I: IntoIterator> DoubleEndedIterator for IterInstantiatedCopied<'_, 'tcx, I> where I::IntoIter: DoubleEndedIterator, I::Item: Deref, <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>, { fn next_back(&mut self) -> Option<Self::Item> { - Some(EarlyBinder(*self.it.next_back()?).subst(self.tcx, self.substs)) + self.it + .next_back() + .map(|value| EarlyBinder { value: *value }.instantiate(self.tcx, self.args)) } } -impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIterCopied<'_, 'tcx, I> +impl<'tcx, I: IntoIterator> ExactSizeIterator for IterInstantiatedCopied<'_, 'tcx, I> where I::IntoIter: ExactSizeIterator, I::Item: Deref, @@ -732,7 +734,7 @@ pub struct EarlyBinderIter<T> { impl<T: IntoIterator> EarlyBinder<T> { pub fn transpose_iter(self) -> EarlyBinderIter<T::IntoIter> { - EarlyBinderIter { t: self.0.into_iter() } + EarlyBinderIter { t: self.value.into_iter() } } } @@ -740,7 +742,7 @@ impl<T: Iterator> Iterator for EarlyBinderIter<T> { type Item = EarlyBinder<T::Item>; fn next(&mut self) -> Option<Self::Item> { - self.t.next().map(|i| EarlyBinder(i)) + self.t.next().map(|value| EarlyBinder { value }) } fn size_hint(&self) -> (usize, Option<usize>) { @@ -749,41 +751,41 @@ impl<T: Iterator> Iterator for EarlyBinderIter<T> { } impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> ty::EarlyBinder<T> { - pub fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> T { - let mut folder = SubstFolder { tcx, substs, binders_passed: 0 }; - self.0.fold_with(&mut folder) + pub fn instantiate(self, tcx: TyCtxt<'tcx>, args: &[GenericArg<'tcx>]) -> T { + let mut folder = ArgFolder { tcx, args, binders_passed: 0 }; + self.value.fold_with(&mut folder) } - /// Makes the identity substitution `T0 => T0, ..., TN => TN`. + /// Makes the identity replacement `T0 => T0, ..., TN => TN`. /// Conceptually, this converts universally bound variables into placeholders /// when inside of a given item. /// /// For example, consider `for<T> fn foo<T>(){ .. }`: /// - Outside of `foo`, `T` is bound (represented by the presence of `EarlyBinder`). /// - Inside of the body of `foo`, we treat `T` as a placeholder by calling - /// `subst_identity` to discharge the `EarlyBinder`. - pub fn subst_identity(self) -> T { - self.0 + /// `instantiate_identity` to discharge the `EarlyBinder`. + pub fn instantiate_identity(self) -> T { + self.value } /// Returns the inner value, but only if it contains no bound vars. pub fn no_bound_vars(self) -> Option<T> { - if !self.0.has_param() { Some(self.0) } else { None } + if !self.value.has_param() { Some(self.value) } else { None } } } /////////////////////////////////////////////////////////////////////////// // The actual substitution engine itself is a type folder. -struct SubstFolder<'a, 'tcx> { +struct ArgFolder<'a, 'tcx> { tcx: TyCtxt<'tcx>, - substs: &'a [GenericArg<'tcx>], + args: &'a [GenericArg<'tcx>], /// Number of region binders we have passed through while doing the substitution binders_passed: u32, } -impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for SubstFolder<'a, 'tcx> { +impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> { #[inline] fn interner(&self) -> TyCtxt<'tcx> { self.tcx @@ -802,12 +804,12 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for SubstFolder<'a, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { #[cold] #[inline(never)] - fn region_param_out_of_range(data: ty::EarlyBoundRegion, substs: &[GenericArg<'_>]) -> ! { + fn region_param_out_of_range(data: ty::EarlyBoundRegion, args: &[GenericArg<'_>]) -> ! { bug!( - "Region parameter out of range when substituting in region {} (index={}, substs = {:?})", + "Region parameter out of range when substituting in region {} (index={}, args = {:?})", data.name, data.index, - substs, + args, ) } @@ -829,11 +831,11 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for SubstFolder<'a, 'tcx> { // the specialized routine `ty::replace_late_regions()`. match *r { ty::ReEarlyBound(data) => { - let rk = self.substs.get(data.index as usize).map(|k| k.unpack()); + let rk = self.args.get(data.index as usize).map(|k| k.unpack()); match rk { Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt), Some(other) => region_param_invalid(data, other), - None => region_param_out_of_range(data, self.substs), + None => region_param_out_of_range(data, self.args), } } ty::ReLateBound(..) @@ -866,10 +868,10 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for SubstFolder<'a, 'tcx> { } } -impl<'a, 'tcx> SubstFolder<'a, 'tcx> { +impl<'a, 'tcx> ArgFolder<'a, 'tcx> { fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> { - // Look up the type in the substitutions. It really should be in there. - let opt_ty = self.substs.get(p.index as usize).map(|k| k.unpack()); + // Look up the type in the args. It really should be in there. + let opt_ty = self.args.get(p.index as usize).map(|k| k.unpack()); let ty = match opt_ty { Some(GenericArgKind::Type(ty)) => ty, Some(kind) => self.type_param_expected(p, source_ty, kind), @@ -883,12 +885,12 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> { #[inline(never)] fn type_param_expected(&self, p: ty::ParamTy, ty: Ty<'tcx>, kind: GenericArgKind<'tcx>) -> ! { bug!( - "expected type for `{:?}` ({:?}/{}) but found {:?} when substituting, substs={:?}", + "expected type for `{:?}` ({:?}/{}) but found {:?} when substituting, args={:?}", p, ty, p.index, kind, - self.substs, + self.args, ) } @@ -896,17 +898,17 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> { #[inline(never)] fn type_param_out_of_range(&self, p: ty::ParamTy, ty: Ty<'tcx>) -> ! { bug!( - "type parameter `{:?}` ({:?}/{}) out of range when substituting, substs={:?}", + "type parameter `{:?}` ({:?}/{}) out of range when substituting, args={:?}", p, ty, p.index, - self.substs, + self.args, ) } fn const_for_param(&self, p: ParamConst, source_ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - // Look up the const in the substitutions. It really should be in there. - let opt_ct = self.substs.get(p.index as usize).map(|k| k.unpack()); + // Look up the const in the args. It really should be in there. + let opt_ct = self.args.get(p.index as usize).map(|k| k.unpack()); let ct = match opt_ct { Some(GenericArgKind::Const(ct)) => ct, Some(kind) => self.const_param_expected(p, source_ct, kind), @@ -925,12 +927,12 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> { kind: GenericArgKind<'tcx>, ) -> ! { bug!( - "expected const for `{:?}` ({:?}/{}) but found {:?} when substituting substs={:?}", + "expected const for `{:?}` ({:?}/{}) but found {:?} when substituting args={:?}", p, ct, p.index, kind, - self.substs, + self.args, ) } @@ -938,11 +940,11 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> { #[inline(never)] fn const_param_out_of_range(&self, p: ty::ParamConst, ct: ty::Const<'tcx>) -> ! { bug!( - "const parameter `{:?}` ({:?}/{}) out of range when substituting substs={:?}", + "const parameter `{:?}` ({:?}/{}) out of range when substituting args={:?}", p, ct, p.index, - self.substs, + self.args, ) } @@ -1014,13 +1016,13 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> { } } -/// Stores the user-given substs to reach some fully qualified path +/// Stores the user-given args to reach some fully qualified path /// (e.g., `<T>::Item` or `<T as Trait>::Item`). #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct UserSubsts<'tcx> { - /// The substitutions for the item as given by the user. - pub substs: SubstsRef<'tcx>, +pub struct UserArgs<'tcx> { + /// The args for the item as given by the user. + pub args: GenericArgsRef<'tcx>, /// The self type, in the case of a `<T>::Item` path (when applied /// to an inherent impl). See `UserSelfTy` below. @@ -1040,7 +1042,7 @@ pub struct UserSubsts<'tcx> { /// when you then have a path like `<Foo<&'static u32>>::method`, /// this struct would carry the `DefId` of the impl along with the /// self type `Foo<u32>`. Then we can instantiate the parameters of -/// the impl (with the substs from `UserSubsts`) and apply those to +/// the impl (with the args from `UserArgs`) and apply those to /// the self type, giving `Foo<?A>`. Finally, we unify that with /// the self type here, which contains `?A` to be `&'static u32` #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 30f92b91cb7..70a35f137d8 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -1,12 +1,12 @@ use crate::ty; -use crate::ty::{EarlyBinder, SubstsRef}; +use crate::ty::{EarlyBinder, GenericArgsRef}; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; -use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predicate, TyCtxt}; +use super::{Clause, EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt}; #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub enum GenericParamDefKind { @@ -97,14 +97,16 @@ impl GenericParamDef { pub fn to_error<'tcx>( &self, tcx: TyCtxt<'tcx>, - preceding_substs: &[ty::GenericArg<'tcx>], + preceding_args: &[ty::GenericArg<'tcx>], ) -> ty::GenericArg<'tcx> { match &self.kind { ty::GenericParamDefKind::Lifetime => ty::Region::new_error_misc(tcx).into(), - ty::GenericParamDefKind::Type { .. } => tcx.ty_error_misc().into(), - ty::GenericParamDefKind::Const { .. } => { - tcx.const_error_misc(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into() - } + ty::GenericParamDefKind::Type { .. } => Ty::new_misc_error(tcx).into(), + ty::GenericParamDefKind::Const { .. } => ty::Const::new_misc_error( + tcx, + tcx.type_of(self.def_id).instantiate(tcx, preceding_args), + ) + .into(), } } } @@ -133,6 +135,9 @@ pub struct Generics { pub has_self: bool, pub has_late_bound_regions: Option<Span>, + + // The index of the host effect when substituted. (i.e. might be index to parent args) + pub host_effect_index: Option<usize>, } impl<'tcx> Generics { @@ -273,14 +278,14 @@ impl<'tcx> Generics { }) } - /// Returns the substs corresponding to the generic parameters + /// Returns the args corresponding to the generic parameters /// of this item, excluding `Self`. /// /// **This should only be used for diagnostics purposes.** - pub fn own_substs_no_defaults( + pub fn own_args_no_defaults( &'tcx self, tcx: TyCtxt<'tcx>, - substs: &'tcx [ty::GenericArg<'tcx>], + args: &'tcx [ty::GenericArg<'tcx>], ) -> &'tcx [ty::GenericArg<'tcx>] { let mut own_params = self.parent_count..self.count(); if self.has_self && self.parent.is_none() { @@ -299,22 +304,22 @@ impl<'tcx> Generics { .rev() .take_while(|param| { param.default_value(tcx).is_some_and(|default| { - default.subst(tcx, substs) == substs[param.index as usize] + default.instantiate(tcx, args) == args[param.index as usize] }) }) .count(); - &substs[own_params] + &args[own_params] } - /// Returns the substs corresponding to the generic parameters of this item, excluding `Self`. + /// Returns the args corresponding to the generic parameters of this item, excluding `Self`. /// /// **This should only be used for diagnostics purposes.** - pub fn own_substs( + pub fn own_args( &'tcx self, - substs: &'tcx [ty::GenericArg<'tcx>], + args: &'tcx [ty::GenericArg<'tcx>], ) -> &'tcx [ty::GenericArg<'tcx>] { - let own = &substs[self.parent_count..][..self.params.len()]; + let own = &args[self.parent_count..][..self.params.len()]; if self.has_self && self.parent.is_none() { &own[1..] } else { &own } } } @@ -323,27 +328,26 @@ impl<'tcx> Generics { #[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)] pub struct GenericPredicates<'tcx> { pub parent: Option<DefId>, - pub predicates: &'tcx [(Predicate<'tcx>, Span)], + pub predicates: &'tcx [(Clause<'tcx>, Span)], } impl<'tcx> GenericPredicates<'tcx> { pub fn instantiate( &self, tcx: TyCtxt<'tcx>, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, ) -> InstantiatedPredicates<'tcx> { let mut instantiated = InstantiatedPredicates::empty(); - self.instantiate_into(tcx, &mut instantiated, substs); + self.instantiate_into(tcx, &mut instantiated, args); instantiated } pub fn instantiate_own( &self, tcx: TyCtxt<'tcx>, - substs: SubstsRef<'tcx>, - ) -> impl Iterator<Item = (Predicate<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator - { - EarlyBinder::bind(self.predicates).subst_iter_copied(tcx, substs) + args: GenericArgsRef<'tcx>, + ) -> impl Iterator<Item = (Clause<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator { + EarlyBinder::bind(self.predicates).iter_instantiated_copied(tcx, args) } #[instrument(level = "debug", skip(self, tcx))] @@ -351,14 +355,14 @@ impl<'tcx> GenericPredicates<'tcx> { &self, tcx: TyCtxt<'tcx>, instantiated: &mut InstantiatedPredicates<'tcx>, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, ) { if let Some(def_id) = self.parent { - tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, substs); + tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, args); } - instantiated - .predicates - .extend(self.predicates.iter().map(|(p, _)| EarlyBinder::bind(*p).subst(tcx, substs))); + instantiated.predicates.extend( + self.predicates.iter().map(|(p, _)| EarlyBinder::bind(*p).instantiate(tcx, args)), + ); instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp)); } diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index 02baa395c3c..b03874a90e8 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -67,7 +67,7 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> for SimplifiedType { } } -impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArg<'tcx> { +impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::GenericArg<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { self.unpack().hash_stable(hcx, hasher); } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index d48672b2baa..f278cace99d 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -19,7 +19,7 @@ pub enum InhabitedPredicate<'tcx> { /// type has restricted visibility. NotInModule(DefId), /// Inhabited if some generic type is inhabited. - /// These are replaced by calling [`Self::subst`]. + /// These are replaced by calling [`Self::instantiate`]. GenericType(Ty<'tcx>), /// A AND B And(&'tcx [InhabitedPredicate<'tcx>; 2]), @@ -62,7 +62,18 @@ impl<'tcx> InhabitedPredicate<'tcx> { Some(1..) => Ok(false), }, Self::NotInModule(id) => in_module(id).map(|in_mod| !in_mod), - Self::GenericType(_) => Ok(true), + // `t` may be a projection, for which `inhabited_predicate` returns a `GenericType`. As + // we have a param_env available, we can do better. + Self::GenericType(t) => { + let normalized_pred = tcx + .try_normalize_erasing_regions(param_env, t) + .map_or(self, |t| t.inhabited_predicate(tcx)); + match normalized_pred { + // We don't have more information than we started with, so consider inhabited. + Self::GenericType(_) => Ok(true), + pred => pred.apply_inner(tcx, param_env, in_module), + } + } Self::And([a, b]) => try_and(a, b, |x| x.apply_inner(tcx, param_env, in_module)), Self::Or([a, b]) => try_or(a, b, |x| x.apply_inner(tcx, param_env, in_module)), } @@ -151,15 +162,15 @@ impl<'tcx> InhabitedPredicate<'tcx> { } /// Replaces generic types with its corresponding predicate - pub fn subst(self, tcx: TyCtxt<'tcx>, substs: ty::SubstsRef<'tcx>) -> Self { - self.subst_opt(tcx, substs).unwrap_or(self) + pub fn instantiate(self, tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> Self { + self.instantiate_opt(tcx, args).unwrap_or(self) } - fn subst_opt(self, tcx: TyCtxt<'tcx>, substs: ty::SubstsRef<'tcx>) -> Option<Self> { + fn instantiate_opt(self, tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> Option<Self> { match self { Self::ConstIsZero(c) => { - let c = ty::EarlyBinder::bind(c).subst(tcx, substs); - let pred = match c.kind().try_to_target_usize(tcx) { + let c = ty::EarlyBinder::bind(c).instantiate(tcx, args); + let pred = match c.try_to_target_usize(tcx) { Some(0) => Self::True, Some(1..) => Self::False, None => Self::ConstIsZero(c), @@ -167,17 +178,17 @@ impl<'tcx> InhabitedPredicate<'tcx> { Some(pred) } Self::GenericType(t) => { - Some(ty::EarlyBinder::bind(t).subst(tcx, substs).inhabited_predicate(tcx)) + Some(ty::EarlyBinder::bind(t).instantiate(tcx, args).inhabited_predicate(tcx)) } - Self::And(&[a, b]) => match a.subst_opt(tcx, substs) { - None => b.subst_opt(tcx, substs).map(|b| a.and(tcx, b)), + Self::And(&[a, b]) => match a.instantiate_opt(tcx, args) { + None => b.instantiate_opt(tcx, args).map(|b| a.and(tcx, b)), Some(InhabitedPredicate::False) => Some(InhabitedPredicate::False), - Some(a) => Some(a.and(tcx, b.subst_opt(tcx, substs).unwrap_or(b))), + Some(a) => Some(a.and(tcx, b.instantiate_opt(tcx, args).unwrap_or(b))), }, - Self::Or(&[a, b]) => match a.subst_opt(tcx, substs) { - None => b.subst_opt(tcx, substs).map(|b| a.or(tcx, b)), + Self::Or(&[a, b]) => match a.instantiate_opt(tcx, args) { + None => b.instantiate_opt(tcx, args).map(|b| a.or(tcx, b)), Some(InhabitedPredicate::True) => Some(InhabitedPredicate::True), - Some(a) => Some(a.or(tcx, b.subst_opt(tcx, substs).unwrap_or(b))), + Some(a) => Some(a.or(tcx, b.instantiate_opt(tcx, args).unwrap_or(b))), }, _ => None, } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 4223502848e..4dac6891b30 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -58,7 +58,7 @@ pub(crate) fn provide(providers: &mut Providers) { } /// Returns an `InhabitedPredicate` that is generic over type parameters and -/// requires calling [`InhabitedPredicate::subst`] +/// requires calling [`InhabitedPredicate::instantiate`] fn inhabited_predicate_adt(tcx: TyCtxt<'_>, def_id: DefId) -> InhabitedPredicate<'_> { if let Some(def_id) = def_id.as_local() { if matches!(tcx.representability(def_id), ty::Representability::Infinite) { @@ -87,7 +87,7 @@ impl<'tcx> VariantDef { InhabitedPredicate::all( tcx, self.fields.iter().map(|field| { - let pred = tcx.type_of(field.did).subst_identity().inhabited_predicate(tcx); + let pred = tcx.type_of(field.did).instantiate_identity().inhabited_predicate(tcx); if adt.is_enum() { return pred; } @@ -114,8 +114,8 @@ impl<'tcx> Ty<'tcx> { Never => InhabitedPredicate::False, Param(_) | Alias(ty::Projection, _) => InhabitedPredicate::GenericType(self), // FIXME(inherent_associated_types): Most likely we can just map to `GenericType` like above. - // However it's unclear if the substs passed to `InhabitedPredicate::subst` are of the correct - // format, i.e. don't contain parent substs. If you hit this case, please verify this beforehand. + // However it's unclear if the args passed to `InhabitedPredicate::instantiate` are of the correct + // format, i.e. don't contain parent args. If you hit this case, please verify this beforehand. Alias(ty::Inherent, _) => { bug!("unimplemented: inhabitedness checking for inherent projections") } @@ -189,7 +189,7 @@ impl<'tcx> Ty<'tcx> { /// N.B. this query should only be called through `Ty::inhabited_predicate` fn inhabited_predicate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InhabitedPredicate<'tcx> { match *ty.kind() { - Adt(adt, substs) => tcx.inhabited_predicate_adt(adt.did()).subst(tcx, substs), + Adt(adt, args) => tcx.inhabited_predicate_adt(adt.did()).instantiate(tcx, args), Tuple(tys) => { InhabitedPredicate::all(tcx, tys.iter().map(|ty| ty.inhabited_predicate(tcx))) @@ -197,7 +197,7 @@ fn inhabited_predicate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InhabitedP // If we can evaluate the array length before having a `ParamEnv`, then // we can simplify the predicate. This is an optimization. - Array(ty, len) => match len.kind().try_to_target_usize(tcx) { + Array(ty, len) => match len.try_to_target_usize(tcx) { Some(0) => InhabitedPredicate::True, Some(1..) => ty.inhabited_predicate(tcx), None => ty.inhabited_predicate(tcx).or(tcx, InhabitedPredicate::ConstIsZero(len)), diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index c0d591430f7..48e88daa890 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -1,7 +1,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable}; -use crate::ty::{EarlyBinder, InternalSubsts, SubstsRef, TypeVisitableExt}; +use crate::ty::{EarlyBinder, GenericArgs, GenericArgsRef, TypeVisitableExt}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::Namespace; use rustc_hir::def_id::{CrateNum, DefId}; @@ -16,13 +16,13 @@ use std::fmt; /// A monomorphized `InstanceDef`. /// /// Monomorphization happens on-the-fly and no monomorphized MIR is ever created. Instead, this type -/// simply couples a potentially generic `InstanceDef` with some substs, and codegen and const eval +/// simply couples a potentially generic `InstanceDef` with some args, and codegen and const eval /// will do all required substitution as they run. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable, Lift, TypeFoldable, TypeVisitable)] pub struct Instance<'tcx> { pub def: InstanceDef<'tcx>, - pub substs: SubstsRef<'tcx>, + pub args: GenericArgsRef<'tcx>, } #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] @@ -115,7 +115,7 @@ impl<'tcx> Instance<'tcx> { /// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization. pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { let ty = tcx.type_of(self.def.def_id()); - tcx.subst_and_normalize_erasing_regions(self.substs, param_env, ty) + tcx.subst_and_normalize_erasing_regions(self.args, param_env, ty) } /// Finds a crate that contains a monomorphization of this instance that @@ -139,13 +139,13 @@ impl<'tcx> Instance<'tcx> { } // If this a non-generic instance, it cannot be a shared monomorphization. - self.substs.non_erasable_generics().next()?; + self.args.non_erasable_generics().next()?; match self.def { InstanceDef::Item(def) => tcx .upstream_monomorphizations_for(def) - .and_then(|monos| monos.get(&self.substs).cloned()), - InstanceDef::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.substs), + .and_then(|monos| monos.get(&self.args).cloned()), + InstanceDef::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.args), _ => None, } } @@ -265,8 +265,8 @@ impl<'tcx> InstanceDef<'tcx> { } /// Returns `true` when the MIR body associated with this instance should be monomorphized - /// by its users (e.g. codegen or miri) by substituting the `substs` from `Instance` (see - /// `Instance::substs_for_mir_body`). + /// by its users (e.g. codegen or miri) by substituting the `args` from `Instance` (see + /// `Instance::args_for_mir_body`). /// /// Otherwise, returns `false` only for some kinds of shims where the construction of the MIR /// body should perform necessary substitutions. @@ -294,10 +294,10 @@ fn fmt_instance( type_length: rustc_session::Limit, ) -> fmt::Result { ty::tls::with(|tcx| { - let substs = tcx.lift(instance.substs).expect("could not lift for printing"); + let args = tcx.lift(instance.args).expect("could not lift for printing"); let s = FmtPrinter::new_with_limit(tcx, Namespace::ValueNS, type_length) - .print_def_path(instance.def_id(), substs)? + .print_def_path(instance.def_id(), args)? .into_buffer(); f.write_str(&s) })?; @@ -333,18 +333,18 @@ impl<'tcx> fmt::Display for Instance<'tcx> { } impl<'tcx> Instance<'tcx> { - pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> Instance<'tcx> { + pub fn new(def_id: DefId, args: GenericArgsRef<'tcx>) -> Instance<'tcx> { assert!( - !substs.has_escaping_bound_vars(), - "substs of instance {:?} not normalized for codegen: {:?}", + !args.has_escaping_bound_vars(), + "args of instance {:?} not normalized for codegen: {:?}", def_id, - substs + args ); - Instance { def: InstanceDef::Item(def_id), substs } + Instance { def: InstanceDef::Item(def_id), args } } pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> { - let substs = InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind { + let args = GenericArgs::for_item(tcx, def_id, |param, _| match param.kind { ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), ty::GenericParamDefKind::Type { .. } => { bug!("Instance::mono: {:?} has type parameters", def_id) @@ -354,7 +354,7 @@ impl<'tcx> Instance<'tcx> { } }); - Instance::new(def_id, substs) + Instance::new(def_id, args) } #[inline] @@ -362,7 +362,7 @@ impl<'tcx> Instance<'tcx> { self.def.def_id() } - /// Resolves a `(def_id, substs)` pair to an (optional) instance -- most commonly, + /// Resolves a `(def_id, args)` pair to an (optional) instance -- most commonly, /// this is used to find the precise code that will run for a trait method invocation, /// if known. /// @@ -390,29 +390,29 @@ impl<'tcx> Instance<'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, def_id: DefId, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> { // All regions in the result of this query are erased, so it's // fine to erase all of the input regions. - // HACK(eddyb) erase regions in `substs` first, so that `param_env.and(...)` + // HACK(eddyb) erase regions in `args` first, so that `param_env.and(...)` // below is more likely to ignore the bounds in scope (e.g. if the only - // generic parameters mentioned by `substs` were lifetime ones). - let substs = tcx.erase_regions(substs); - tcx.resolve_instance(tcx.erase_regions(param_env.and((def_id, substs)))) + // generic parameters mentioned by `args` were lifetime ones). + let args = tcx.erase_regions(args); + tcx.resolve_instance(tcx.erase_regions(param_env.and((def_id, args)))) } pub fn expect_resolve( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, def_id: DefId, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, ) -> Instance<'tcx> { - match ty::Instance::resolve(tcx, param_env, def_id, substs) { + match ty::Instance::resolve(tcx, param_env, def_id, args) { Ok(Some(instance)) => instance, - _ => bug!( - "failed to resolve instance for {}", - tcx.def_path_str_with_substs(def_id, substs) + instance => bug!( + "failed to resolve instance for {}: {instance:#?}", + tcx.def_path_str_with_args(def_id, args) ), } } @@ -421,12 +421,12 @@ impl<'tcx> Instance<'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, def_id: DefId, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, ) -> Option<Instance<'tcx>> { - debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); + debug!("resolve(def_id={:?}, args={:?})", def_id, args); // Use either `resolve_closure` or `resolve_for_vtable` assert!(!tcx.is_closure(def_id), "Called `resolve_for_fn_ptr` on closure: {:?}", def_id); - Instance::resolve(tcx, param_env, def_id, substs).ok().flatten().map(|mut resolved| { + Instance::resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| { match resolved.def { InstanceDef::Item(def) if resolved.def.requires_caller_location(tcx) => { debug!(" => fn pointer created for function with #[track_caller]"); @@ -447,18 +447,18 @@ impl<'tcx> Instance<'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, def_id: DefId, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, ) -> Option<Instance<'tcx>> { - debug!("resolve_for_vtable(def_id={:?}, substs={:?})", def_id, substs); - let fn_sig = tcx.fn_sig(def_id).subst_identity(); + debug!("resolve_for_vtable(def_id={:?}, args={:?})", def_id, args); + let fn_sig = tcx.fn_sig(def_id).instantiate_identity(); let is_vtable_shim = !fn_sig.inputs().skip_binder().is_empty() && fn_sig.input(0).skip_binder().is_param(0) && tcx.generics_of(def_id).has_self; if is_vtable_shim { debug!(" => associated item with unsizeable self: Self"); - Some(Instance { def: InstanceDef::VTableShim(def_id), substs }) + Some(Instance { def: InstanceDef::VTableShim(def_id), args }) } else { - Instance::resolve(tcx, param_env, def_id, substs).ok().flatten().map(|mut resolved| { + Instance::resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| { match resolved.def { InstanceDef::Item(def) => { // We need to generate a shim when we cannot guarantee that @@ -489,12 +489,12 @@ impl<'tcx> Instance<'tcx> { { if tcx.is_closure(def) { debug!(" => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}", - def, def_id, substs); + def, def_id, args); // Create a shim for the `FnOnce/FnMut/Fn` method we are calling // - unlike functions, invoking a closure always goes through a // trait. - resolved = Instance { def: InstanceDef::ReifyShim(def_id), substs }; + resolved = Instance { def: InstanceDef::ReifyShim(def_id), args }; } else { debug!( " => vtable fn pointer created for function with #[track_caller]: {:?}", def @@ -518,28 +518,28 @@ impl<'tcx> Instance<'tcx> { pub fn resolve_closure( tcx: TyCtxt<'tcx>, def_id: DefId, - substs: ty::SubstsRef<'tcx>, + args: ty::GenericArgsRef<'tcx>, requested_kind: ty::ClosureKind, ) -> Option<Instance<'tcx>> { - let actual_kind = substs.as_closure().kind(); + let actual_kind = args.as_closure().kind(); match needs_fn_once_adapter_shim(actual_kind, requested_kind) { - Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, substs), - _ => Some(Instance::new(def_id, substs)), + Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, args), + _ => Some(Instance::new(def_id, args)), } } pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> { let def_id = tcx.require_lang_item(LangItem::DropInPlace, None); - let substs = tcx.mk_substs(&[ty.into()]); - Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs) + let args = tcx.mk_args(&[ty.into()]); + Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args) } #[instrument(level = "debug", skip(tcx), ret)] pub fn fn_once_adapter_instance( tcx: TyCtxt<'tcx>, closure_did: DefId, - substs: ty::SubstsRef<'tcx>, + args: ty::GenericArgsRef<'tcx>, ) -> Option<Instance<'tcx>> { let fn_once = tcx.require_lang_item(LangItem::FnOnce, None); let call_once = tcx @@ -552,30 +552,30 @@ impl<'tcx> Instance<'tcx> { tcx.codegen_fn_attrs(closure_did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER); let def = ty::InstanceDef::ClosureOnceShim { call_once, track_caller }; - let self_ty = tcx.mk_closure(closure_did, substs); + let self_ty = Ty::new_closure(tcx, closure_did, args); - let sig = substs.as_closure().sig(); + let sig = args.as_closure().sig(); let sig = tcx.try_normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig).ok()?; assert_eq!(sig.inputs().len(), 1); - let substs = tcx.mk_substs_trait(self_ty, [sig.inputs()[0].into()]); + let args = tcx.mk_args_trait(self_ty, [sig.inputs()[0].into()]); debug!(?self_ty, ?sig); - Some(Instance { def, substs }) + Some(Instance { def, args }) } /// Depending on the kind of `InstanceDef`, the MIR body associated with an /// instance is expressed in terms of the generic parameters of `self.def_id()`, and in other /// cases the MIR body is expressed in terms of the types found in the substitution array. /// In the former case, we want to substitute those generic types and replace them with the - /// values from the substs when monomorphizing the function body. But in the latter case, we + /// values from the args when monomorphizing the function body. But in the latter case, we /// don't want to do that substitution, since it has already been done effectively. /// - /// This function returns `Some(substs)` in the former case and `None` otherwise -- i.e., if + /// This function returns `Some(args)` in the former case and `None` otherwise -- i.e., if /// this function returns `None`, then the MIR body does not require substitution during /// codegen. - fn substs_for_mir_body(&self) -> Option<SubstsRef<'tcx>> { - self.def.has_polymorphic_mir_body().then_some(self.substs) + fn args_for_mir_body(&self) -> Option<GenericArgsRef<'tcx>> { + self.def.has_polymorphic_mir_body().then_some(self.args) } pub fn subst_mir<T>(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T @@ -583,10 +583,10 @@ impl<'tcx> Instance<'tcx> { T: TypeFoldable<TyCtxt<'tcx>> + Copy, { let v = v.map_bound(|v| *v); - if let Some(substs) = self.substs_for_mir_body() { - v.subst(tcx, substs) + if let Some(args) = self.args_for_mir_body() { + v.instantiate(tcx, args) } else { - v.subst_identity() + v.instantiate_identity() } } @@ -600,8 +600,8 @@ impl<'tcx> Instance<'tcx> { where T: TypeFoldable<TyCtxt<'tcx>> + Clone, { - if let Some(substs) = self.substs_for_mir_body() { - tcx.subst_and_normalize_erasing_regions(substs, param_env, v) + if let Some(args) = self.args_for_mir_body() { + tcx.subst_and_normalize_erasing_regions(args, param_env, v) } else { tcx.normalize_erasing_regions(param_env, v.skip_binder()) } @@ -617,14 +617,14 @@ impl<'tcx> Instance<'tcx> { where T: TypeFoldable<TyCtxt<'tcx>> + Clone, { - if let Some(substs) = self.substs_for_mir_body() { - tcx.try_subst_and_normalize_erasing_regions(substs, param_env, v) + if let Some(args) = self.args_for_mir_body() { + tcx.try_subst_and_normalize_erasing_regions(args, param_env, v) } else { tcx.try_normalize_erasing_regions(param_env, v.skip_binder()) } } - /// Returns a new `Instance` where generic parameters in `instance.substs` are replaced by + /// Returns a new `Instance` where generic parameters in `instance.args` are replaced by /// identity parameters if they are determined to be unused in `instance.def`. pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self { debug!("polymorphize: running polymorphization analysis"); @@ -632,18 +632,18 @@ impl<'tcx> Instance<'tcx> { return self; } - let polymorphized_substs = polymorphize(tcx, self.def, self.substs); - debug!("polymorphize: self={:?} polymorphized_substs={:?}", self, polymorphized_substs); - Self { def: self.def, substs: polymorphized_substs } + let polymorphized_args = polymorphize(tcx, self.def, self.args); + debug!("polymorphize: self={:?} polymorphized_args={:?}", self, polymorphized_args); + Self { def: self.def, args: polymorphized_args } } } fn polymorphize<'tcx>( tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>, - substs: SubstsRef<'tcx>, -) -> SubstsRef<'tcx> { - debug!("polymorphize({:?}, {:?})", instance, substs); + args: GenericArgsRef<'tcx>, +) -> GenericArgsRef<'tcx> { + debug!("polymorphize({:?}, {:?})", instance, args); let unused = tcx.unused_generic_params(instance); debug!("polymorphize: unused={:?}", unused); @@ -653,9 +653,9 @@ fn polymorphize<'tcx>( // multiple mono items (and eventually symbol clashes). let def_id = instance.def_id(); let upvars_ty = if tcx.is_closure(def_id) { - Some(substs.as_closure().tupled_upvars_ty()) + Some(args.as_closure().tupled_upvars_ty()) } else if tcx.type_of(def_id).skip_binder().is_generator() { - Some(substs.as_generator().tupled_upvars_ty()) + Some(args.as_generator().tupled_upvars_ty()) } else { None }; @@ -674,22 +674,22 @@ fn polymorphize<'tcx>( fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { debug!("fold_ty: ty={:?}", ty); match *ty.kind() { - ty::Closure(def_id, substs) => { - let polymorphized_substs = - polymorphize(self.tcx, ty::InstanceDef::Item(def_id), substs); - if substs == polymorphized_substs { + ty::Closure(def_id, args) => { + let polymorphized_args = + polymorphize(self.tcx, ty::InstanceDef::Item(def_id), args); + if args == polymorphized_args { ty } else { - self.tcx.mk_closure(def_id, polymorphized_substs) + Ty::new_closure(self.tcx, def_id, polymorphized_args) } } - ty::Generator(def_id, substs, movability) => { - let polymorphized_substs = - polymorphize(self.tcx, ty::InstanceDef::Item(def_id), substs); - if substs == polymorphized_substs { + ty::Generator(def_id, args, movability) => { + let polymorphized_args = + polymorphize(self.tcx, ty::InstanceDef::Item(def_id), args); + if args == polymorphized_args { ty } else { - self.tcx.mk_generator(def_id, polymorphized_substs, movability) + Ty::new_generator(self.tcx, def_id, polymorphized_args, movability) } } _ => ty.super_fold_with(self), @@ -697,7 +697,7 @@ fn polymorphize<'tcx>( } } - InternalSubsts::for_item(tcx, def_id, |param, _| { + GenericArgs::for_item(tcx, def_id, |param, _| { let is_unused = unused.is_unused(param.index); debug!("polymorphize: param={:?} is_unused={:?}", param, is_unused); match param.kind { @@ -706,7 +706,7 @@ fn polymorphize<'tcx>( // ..and has upvars.. has_upvars && // ..and this param has the same type as the tupled upvars.. - upvars_ty == Some(substs[param.index as usize].expect_ty()) => { + upvars_ty == Some(args[param.index as usize].expect_ty()) => { // ..then double-check that polymorphization marked it used.. debug_assert!(!is_unused); // ..and polymorphize any closures/generators captured as upvars. @@ -725,7 +725,7 @@ fn polymorphize<'tcx>( tcx.mk_param_from_def(param), // Otherwise, use the parameter as before. - _ => substs[param.index as usize], + _ => args[param.index as usize], } }) } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index c5a306fdf1f..26137e86fa0 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2,7 +2,7 @@ use crate::error::UnsupportedFnAbi; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::TyCtxtAt; use crate::ty::normalize_erasing_regions::NormalizationError; -use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitableExt}; +use crate::ty::{self, ConstKind, ReprOptions, Ty, TyCtxt, TypeVisitableExt}; use rustc_error_messages::DiagnosticMessage; use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic}; use rustc_hir as hir; @@ -133,7 +133,7 @@ impl PrimitiveExt for Primitive { F32 => tcx.types.f32, F64 => tcx.types.f64, // FIXME(erikdesjardins): handle non-default addrspace ptr sizes - Pointer(_) => tcx.mk_mut_ptr(tcx.mk_unit()), + Pointer(_) => Ty::new_mut_ptr(tcx, Ty::new_unit(tcx)), } } @@ -310,17 +310,33 @@ impl<'tcx> SizeSkeleton<'tcx> { ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - ) -> Result<SizeSkeleton<'tcx>, LayoutError<'tcx>> { + ) -> Result<SizeSkeleton<'tcx>, &'tcx LayoutError<'tcx>> { debug_assert!(!ty.has_non_region_infer()); - // First try computing a static layout. + // First, try computing an exact naive layout (this covers simple types with generic + // references, where a full static layout would fail). + if let Ok(layout) = tcx.naive_layout_of(param_env.and(ty)) { + if layout.exact { + return Ok(SizeSkeleton::Known(layout.size)); + } + } + + // Second, try computing a full static layout (this covers cases when the naive layout + // wasn't smart enough, but cannot deal with generic references). let err = match tcx.layout_of(param_env.and(ty)) { Ok(layout) => { return Ok(SizeSkeleton::Known(layout.size)); } - Err(err) => err, + Err(err @ LayoutError::Unknown(_)) => err, + // We can't extract SizeSkeleton info from other layout errors + Err( + e @ LayoutError::Cycle + | e @ LayoutError::SizeOverflow(_) + | e @ LayoutError::NormalizationFailure(..), + ) => return Err(e), }; + // Third, fall back to ad-hoc cases. match *ty.kind() { ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => { let non_zero = !ty.is_unsafe_ptr(); @@ -347,13 +363,13 @@ impl<'tcx> SizeSkeleton<'tcx> { let size = s .bytes() .checked_mul(c) - .ok_or_else(|| LayoutError::SizeOverflow(ty))?; + .ok_or_else(|| &*tcx.arena.alloc(LayoutError::SizeOverflow(ty)))?; return Ok(SizeSkeleton::Known(Size::from_bytes(size))); } let len = tcx.expand_abstract_consts(len); let prev = ty::Const::from_target_usize(tcx, s.bytes()); let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, prev) else { - return Err(LayoutError::SizeOverflow(ty)); + return Err(tcx.arena.alloc(LayoutError::SizeOverflow(ty))); }; Ok(SizeSkeleton::Generic(gen_size)) } @@ -361,14 +377,14 @@ impl<'tcx> SizeSkeleton<'tcx> { SizeSkeleton::Generic(g) => { let len = tcx.expand_abstract_consts(len); let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, g) else { - return Err(LayoutError::SizeOverflow(ty)); + return Err(tcx.arena.alloc(LayoutError::SizeOverflow(ty))); }; Ok(SizeSkeleton::Generic(gen_size)) } } } - ty::Adt(def, substs) => { + ty::Adt(def, args) => { // Only newtypes and enums w/ nullable pointer optimization. if def.is_union() || def.variants().is_empty() || def.variants().len() > 2 { return Err(err); @@ -379,7 +395,7 @@ impl<'tcx> SizeSkeleton<'tcx> { let i = VariantIdx::from_usize(i); let fields = def.variant(i).fields.iter().map(|field| { - SizeSkeleton::compute(field.ty(tcx, substs), tcx, param_env) + SizeSkeleton::compute(field.ty(tcx, args), tcx, param_env) }); let mut ptr = None; for field in fields { @@ -474,13 +490,11 @@ fn mul_sorted_consts<'tcx>( b: ty::Const<'tcx>, ) -> Option<ty::Const<'tcx>> { use crate::mir::BinOp::Mul; - use ty::ConstKind::Expr; - use ty::Expr::Binop; let mut work = vec![a, b]; let mut done = vec![]; while let Some(n) = work.pop() { - if let Expr(Binop(Mul, l, r)) = n.kind() { + if let ConstKind::Expr(ty::Expr::Binop(Mul, l, r)) = n.kind() { work.push(l); work.push(r) } else { @@ -511,7 +525,7 @@ fn mul_sorted_consts<'tcx>( done.sort_unstable(); // create a single tree from the buffer - done.into_iter().reduce(|acc, n| tcx.mk_const(Expr(Binop(Mul, n, acc)), n.ty())) + done.into_iter().reduce(|acc, n| ty::Const::new_expr(tcx, ty::Expr::Binop(Mul, n, acc), n.ty())) } pub trait HasTyCtxt<'tcx>: HasDataLayout { @@ -617,6 +631,219 @@ impl<T, E> MaybeResult<T> for Result<T, E> { pub type TyAndLayout<'tcx> = rustc_target::abi::TyAndLayout<'tcx, Ty<'tcx>>; +#[derive(Copy, Clone, Debug, HashStable)] +pub struct TyAndNaiveLayout<'tcx> { + pub ty: Ty<'tcx>, + pub layout: NaiveLayout, +} + +impl std::ops::Deref for TyAndNaiveLayout<'_> { + type Target = NaiveLayout; + fn deref(&self) -> &Self::Target { + &self.layout + } +} + +impl std::ops::DerefMut for TyAndNaiveLayout<'_> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.layout + } +} + +/// Extremely simplified approximation of a type's layout returned by the +/// `naive_layout_of` query. +#[derive(Copy, Clone, Debug, HashStable)] +pub struct NaiveLayout { + pub abi: NaiveAbi, + /// Niche information, required for tracking non-null enum optimizations. + pub niches: NaiveNiches, + /// An underestimate of the layout's size. + pub size: Size, + /// An underestimate of the layout's required alignment. + pub align: Align, + /// If `true`, `size` and `align` must be exact values. + pub exact: bool, +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable)] +pub enum NaiveNiches { + None, + Some, + Maybe, +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable)] +pub enum NaiveAbi { + /// A scalar layout, always implies `exact` and a non-zero `size`. + Scalar(Primitive), + /// An uninhabited layout. (needed to properly track `Scalar` and niches) + Uninhabited, + /// An unsized aggregate. (needed to properly track `Scalar` and niches) + Unsized, + /// Any other sized layout. + Sized, +} + +impl NaiveAbi { + #[inline] + pub fn as_aggregate(self) -> Self { + match self { + NaiveAbi::Scalar(_) => NaiveAbi::Sized, + _ => self, + } + } +} + +impl NaiveLayout { + /// The layout of an empty aggregate, e.g. `()`. + pub const EMPTY: Self = Self { + size: Size::ZERO, + align: Align::ONE, + exact: true, + abi: NaiveAbi::Sized, + niches: NaiveNiches::None, + }; + + /// Returns whether `self` is a valid approximation of the given full `layout`. + /// + /// This should always return `true` when both layouts are computed from the same type. + pub fn is_refined_by(&self, layout: Layout<'_>) -> bool { + if self.size > layout.size() || self.align > layout.align().abi { + return false; + } + + if let NaiveAbi::Scalar(prim) = self.abi { + if !self.exact + || self.size == Size::ZERO + || !matches!(layout.abi(), Abi::Scalar(s) if s.primitive() == prim) + { + return false; + } + } + + match (self.niches, layout.largest_niche()) { + (NaiveNiches::None, Some(_)) => return false, + (NaiveNiches::Some, None) => return false, + _ => (), + } + + !self.exact || (self.size, self.align) == (layout.size(), layout.align().abi) + } + + /// Returns if this layout is known to be pointer-like (`None` if uncertain) + /// + /// See the corresponding `Layout::is_pointer_like` method. + pub fn is_pointer_like(&self, dl: &TargetDataLayout) -> Option<bool> { + match self.abi { + NaiveAbi::Scalar(_) => { + assert!(self.exact); + Some(self.size == dl.pointer_size && self.align == dl.pointer_align.abi) + } + NaiveAbi::Uninhabited | NaiveAbi::Unsized => Some(false), + NaiveAbi::Sized if self.exact => Some(false), + NaiveAbi::Sized => None, + } + } + + /// Artificially lowers the alignment of this layout. + #[must_use] + #[inline] + pub fn packed(mut self, align: Align) -> Self { + if self.align > align { + self.align = align; + self.abi = self.abi.as_aggregate(); + } + self + } + + /// Artificially raises the alignment of this layout. + #[must_use] + #[inline] + pub fn align_to(mut self, align: Align) -> Self { + if align > self.align { + self.align = align; + self.abi = self.abi.as_aggregate(); + } + self + } + + /// Artificially makes this layout inexact. + #[must_use] + #[inline] + pub fn inexact(mut self) -> Self { + self.abi = self.abi.as_aggregate(); + self.exact = false; + self + } + + /// Pads this layout so that its size is a multiple of `align`. + #[must_use] + #[inline] + pub fn pad_to_align(mut self, align: Align) -> Self { + let new_size = self.size.align_to(align); + if new_size > self.size { + self.abi = self.abi.as_aggregate(); + self.size = new_size; + } + self + } + + /// Returns the layout of `self` immediately followed by `other`, without any + /// padding between them, as in a packed `struct` or tuple. + #[must_use] + #[inline] + pub fn concat(&self, other: &Self, dl: &TargetDataLayout) -> Option<Self> { + use NaiveAbi::*; + + let size = self.size.checked_add(other.size, dl)?; + let align = cmp::max(self.align, other.align); + let exact = self.exact && other.exact; + let abi = match (self.abi, other.abi) { + // The uninhabited and unsized ABIs override everything. + (Uninhabited, _) | (_, Uninhabited) => Uninhabited, + (Unsized, _) | (_, Unsized) => Unsized, + // A scalar struct must have a single non ZST-field. + (_, s @ Scalar(_)) if exact && self.size == Size::ZERO => s, + (s @ Scalar(_), _) if exact && other.size == Size::ZERO => s, + // Default case. + (_, _) => Sized, + }; + let niches = match (self.niches, other.niches) { + (NaiveNiches::Some, _) | (_, NaiveNiches::Some) => NaiveNiches::Some, + (NaiveNiches::None, NaiveNiches::None) => NaiveNiches::None, + (_, _) => NaiveNiches::Maybe, + }; + Some(Self { abi, size, align, exact, niches }) + } + + /// Returns the layout of `self` superposed with `other`, as in an `enum` + /// or an `union`. + /// + /// Note: This always ignore niche information from `other`. + #[must_use] + #[inline] + pub fn union(&self, other: &Self) -> Self { + use NaiveAbi::*; + + let size = cmp::max(self.size, other.size); + let align = cmp::max(self.align, other.align); + let exact = self.exact && other.exact; + let abi = match (self.abi, other.abi) { + // The unsized ABI overrides everything. + (Unsized, _) | (_, Unsized) => Unsized, + // A scalar union must have a single non ZST-field... + (_, s @ Scalar(_)) if exact && self.size == Size::ZERO => s, + (s @ Scalar(_), _) if exact && other.size == Size::ZERO => s, + // ...or identical scalar fields. + (Scalar(s1), Scalar(s2)) if s1 == s2 => Scalar(s1), + // Default cases. + (Uninhabited, Uninhabited) => Uninhabited, + (_, _) => Sized, + }; + Self { abi, size, align, exact, niches: self.niches } + } +} + /// Trait for contexts that want to be able to compute layouts of types. /// This automatically gives access to `LayoutOf`, through a blanket `impl`. pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasParamEnv<'tcx> { @@ -666,24 +893,42 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> { MaybeResult::from( tcx.layout_of(self.param_env().and(ty)) - .map_err(|err| self.handle_layout_err(err, span, ty)), + .map_err(|err| self.handle_layout_err(*err, span, ty)), ) } + + /// Computes the naive layout estimate of a type. Note that this implicitly + /// executes in "reveal all" mode, and will normalize the input type. + /// + /// Unlike `layout_of`, this doesn't look past references (beyond the `Pointee::Metadata` + /// projection), and as such can be called on generic types like `Option<&T>`. + #[inline] + fn naive_layout_of( + &self, + ty: Ty<'tcx>, + ) -> Result<TyAndNaiveLayout<'tcx>, &'tcx LayoutError<'tcx>> { + self.tcx().naive_layout_of(self.param_env().and(ty)) + } } impl<'tcx, C: LayoutOfHelpers<'tcx>> LayoutOf<'tcx> for C {} impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> { - type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>; + type LayoutOfResult = Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>>; #[inline] - fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> { - err + fn handle_layout_err( + &self, + err: LayoutError<'tcx>, + _: Span, + _: Ty<'tcx>, + ) -> &'tcx LayoutError<'tcx> { + self.tcx.arena.alloc(err) } } impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxtAt<'tcx>> { - type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>; + type LayoutOfResult = Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>>; #[inline] fn layout_tcx_at_span(&self) -> Span { @@ -691,8 +936,13 @@ impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxtAt<'tcx>> { } #[inline] - fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> { - err + fn handle_layout_err( + &self, + err: LayoutError<'tcx>, + _: Span, + _: Ty<'tcx>, + ) -> &'tcx LayoutError<'tcx> { + self.tcx.arena.alloc(err) } } @@ -741,6 +991,8 @@ where largest_niche: None, align: tcx.data_layout.i8_align, size: Size::ZERO, + max_repr_align: None, + unadjusted_abi_align: tcx.data_layout.i8_align.abi, }) } @@ -796,11 +1048,11 @@ where // (which may have no non-DST form), and will work as long // as the `Abi` or `FieldsShape` is checked by users. if i == 0 { - let nil = tcx.mk_unit(); + let nil = Ty::new_unit(tcx); let unit_ptr_ty = if this.ty.is_unsafe_ptr() { - tcx.mk_mut_ptr(nil) + Ty::new_mut_ptr(tcx, nil) } else { - tcx.mk_mut_ref(tcx.lifetimes.re_static, nil) + Ty::new_mut_ref(tcx, tcx.lifetimes.re_static, nil) }; // NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing @@ -813,7 +1065,11 @@ where } let mk_dyn_vtable = || { - tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.usize, 3)) + Ty::new_imm_ref( + tcx, + tcx.lifetimes.re_static, + Ty::new_array(tcx, tcx.types.usize, 3), + ) /* FIXME: use actual fn pointers Warning: naively computing the number of entries in the vtable by counting the methods on the trait + methods on @@ -822,9 +1078,9 @@ where Increase this counter if you tried to implement this but failed to do it without duplicating a lot of code from other places in the compiler: 2 - tcx.mk_tup(&[ - tcx.mk_array(tcx.types.usize, 3), - tcx.mk_array(Option<fn()>), + Ty::new_tup(tcx,&[ + Ty::new_array(tcx,tcx.types.usize, 3), + Ty::new_array(tcx,Option<fn()>), ]) */ }; @@ -836,16 +1092,16 @@ where { let metadata = tcx.normalize_erasing_regions( cx.param_env(), - tcx.mk_projection(metadata_def_id, [pointee]), + Ty::new_projection(tcx,metadata_def_id, [pointee]), ); // Map `Metadata = DynMetadata<dyn Trait>` back to a vtable, since it // offers better information than `std::ptr::metadata::VTable`, // and we rely on this layout information to trigger a panic in // `std::mem::uninitialized::<&dyn Trait>()`, for example. - if let ty::Adt(def, substs) = metadata.kind() + if let ty::Adt(def, args) = metadata.kind() && Some(def.did()) == tcx.lang_items().dyn_metadata() - && substs.type_at(0).is_trait() + && args.type_at(0).is_trait() { mk_dyn_vtable() } else { @@ -867,16 +1123,15 @@ where ty::Str => TyMaybeWithLayout::Ty(tcx.types.u8), // Tuples, generators and closures. - ty::Closure(_, ref substs) => field_ty_or_layout( - TyAndLayout { ty: substs.as_closure().tupled_upvars_ty(), ..this }, + ty::Closure(_, ref args) => field_ty_or_layout( + TyAndLayout { ty: args.as_closure().tupled_upvars_ty(), ..this }, cx, i, ), - ty::Generator(def_id, ref substs, _) => match this.variants { + ty::Generator(def_id, ref args, _) => match this.variants { Variants::Single { index } => TyMaybeWithLayout::Ty( - substs - .as_generator() + args.as_generator() .state_tys(def_id, tcx) .nth(index.as_usize()) .unwrap() @@ -887,18 +1142,18 @@ where if i == tag_field { return TyMaybeWithLayout::TyAndLayout(tag_layout(tag)); } - TyMaybeWithLayout::Ty(substs.as_generator().prefix_tys().nth(i).unwrap()) + TyMaybeWithLayout::Ty(args.as_generator().prefix_tys().nth(i).unwrap()) } }, ty::Tuple(tys) => TyMaybeWithLayout::Ty(tys[i]), // ADTs. - ty::Adt(def, substs) => { + ty::Adt(def, args) => { match this.variants { Variants::Single { index } => { let field = &def.variant(index).fields[FieldIdx::from_usize(i)]; - TyMaybeWithLayout::Ty(field.ty(tcx, substs)) + TyMaybeWithLayout::Ty(field.ty(tcx, args)) } // Discriminant field for enums (where applicable). @@ -911,15 +1166,14 @@ where ty::Dynamic(_, _, ty::DynStar) => { if i == 0 { - TyMaybeWithLayout::Ty(tcx.mk_mut_ptr(tcx.types.unit)) + TyMaybeWithLayout::Ty(Ty::new_mut_ptr(tcx, tcx.types.unit)) } else if i == 1 { // FIXME(dyn-star) same FIXME as above applies here too - TyMaybeWithLayout::Ty( - tcx.mk_imm_ref( - tcx.lifetimes.re_static, - tcx.mk_array(tcx.types.usize, 3), - ), - ) + TyMaybeWithLayout::Ty(Ty::new_imm_ref( + tcx, + tcx.lifetimes.re_static, + Ty::new_array(tcx, tcx.types.usize, 3), + )) } else { bug!("no field {i} on dyn*") } @@ -951,6 +1205,9 @@ where this: TyAndLayout<'tcx>, cx: &C, offset: Size, + // If true, assume that pointers are either null or valid (according to their type), + // enabling extra optimizations. + mut assume_valid_ptr: bool, ) -> Option<PointeeInfo> { let tcx = cx.tcx(); let param_env = cx.param_env(); @@ -964,10 +1221,8 @@ where }) } ty::FnPtr(fn_sig) if offset.bytes() == 0 => { - tcx.layout_of(param_env.and(tcx.mk_fn_ptr(fn_sig))).ok().map(|layout| PointeeInfo { - size: layout.size, - align: layout.align.abi, - safe: None, + tcx.layout_of(param_env.and(Ty::new_fn_ptr(tcx, fn_sig))).ok().map(|layout| { + PointeeInfo { size: layout.size, align: layout.align.abi, safe: None } }) } ty::Ref(_, ty, mt) if offset.bytes() == 0 => { @@ -975,19 +1230,19 @@ where // Freeze/Unpin queries, and can save time in the codegen backend (noalias // attributes in LLVM have compile-time cost even in unoptimized builds). let optimize = tcx.sess.opts.optimize != OptLevel::No; - let kind = match mt { - hir::Mutability::Not => PointerKind::SharedRef { + let safe = match (assume_valid_ptr, mt) { + (true, hir::Mutability::Not) => Some(PointerKind::SharedRef { frozen: optimize && ty.is_freeze(tcx, cx.param_env()), - }, - hir::Mutability::Mut => PointerKind::MutableRef { + }), + (true, hir::Mutability::Mut) => Some(PointerKind::MutableRef { unpin: optimize && ty.is_unpin(tcx, cx.param_env()), - }, + }), + (false, _) => None, }; - tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo { size: layout.size, align: layout.align.abi, - safe: Some(kind), + safe, }) } @@ -996,19 +1251,21 @@ where // Within the discriminant field, only the niche itself is // always initialized, so we only check for a pointer at its // offset. - // - // If the niche is a pointer, it's either valid (according - // to its type), or null (which the niche field's scalar - // validity range encodes). This allows using - // `dereferenceable_or_null` for e.g., `Option<&T>`, and - // this will continue to work as long as we don't start - // using more niches than just null (e.g., the first page of - // the address space, or unaligned pointers). Variants::Multiple { - tag_encoding: TagEncoding::Niche { untagged_variant, .. }, + tag_encoding: + TagEncoding::Niche { + untagged_variant, + niche_variants: ref variants, + niche_start, + }, tag_field, .. } if this.fields.offset(tag_field) == offset => { + // We can only continue assuming pointer validity if the only possible + // discriminant value is null. The null special-case is permitted by LLVM's + // `dereferenceable_or_null`, and allow types like `Option<&T>` to benefit + // from optimizations. + assume_valid_ptr &= niche_start == 0 && variants.start() == variants.end(); Some(this.for_variant(cx, untagged_variant)) } _ => Some(this), @@ -1034,9 +1291,12 @@ where result = field.to_result().ok().and_then(|field| { if ptr_end <= field_start + field.size { // We found the right field, look inside it. - let field_info = - field.pointee_info_at(cx, offset - field_start); - field_info + Self::ty_and_layout_pointee_info_at( + field, + cx, + offset - field_start, + assume_valid_ptr, + ) } else { None } @@ -1051,7 +1311,7 @@ where // FIXME(eddyb) This should be for `ptr::Unique<T>`, not `Box<T>`. if let Some(ref mut pointee) = result { if let ty::Adt(def, _) = this.ty.kind() { - if def.is_box() && offset.bytes() == 0 { + if assume_valid_ptr && def.is_box() && offset.bytes() == 0 { let optimize = tcx.sess.opts.optimize != OptLevel::No; pointee.safe = Some(PointerKind::Box { unpin: optimize && this.ty.boxed_ty().is_unpin(tcx, cx.param_env()), @@ -1095,12 +1355,11 @@ where /// /// This takes two primary parameters: /// -/// * `codegen_fn_attr_flags` - these are flags calculated as part of the -/// codegen attrs for a defined function. For function pointers this set of -/// flags is the empty set. This is only applicable for Rust-defined -/// functions, and generally isn't needed except for small optimizations where -/// we try to say a function which otherwise might look like it could unwind -/// doesn't actually unwind (such as for intrinsics and such). +/// * `fn_def_id` - the `DefId` of the function. If this is provided then we can +/// determine more precisely if the function can unwind. If this is not provided +/// then we will only infer whether the function can unwind or not based on the +/// ABI of the function. For example, a function marked with `#[rustc_nounwind]` +/// is known to not unwind even if it's using Rust ABI. /// /// * `abi` - this is the ABI that the function is defined with. This is the /// primary factor for determining whether a function can unwind or not. @@ -1132,11 +1391,6 @@ where /// aborts the process. /// * This affects whether functions have the LLVM `nounwind` attribute, which /// affects various optimizations and codegen. -/// -/// FIXME: this is actually buggy with respect to Rust functions. Rust functions -/// compiled with `-Cpanic=unwind` and referenced from another crate compiled -/// with `-Cpanic=abort` will look like they can't unwind when in fact they -/// might (from a foreign exception or similar). #[inline] #[tracing::instrument(level = "debug", skip(tcx))] pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool { @@ -1244,18 +1498,6 @@ pub enum FnAbiError<'tcx> { AdjustForForeignAbi(call::AdjustForForeignAbiError), } -impl<'tcx> From<LayoutError<'tcx>> for FnAbiError<'tcx> { - fn from(err: LayoutError<'tcx>) -> Self { - Self::Layout(err) - } -} - -impl From<call::AdjustForForeignAbiError> for FnAbiError<'_> { - fn from(err: call::AdjustForForeignAbiError) -> Self { - Self::AdjustForForeignAbi(err) - } -} - impl<'a, 'b> IntoDiagnostic<'a, !> for FnAbiError<'b> { fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> { match self { @@ -1315,7 +1557,7 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { let tcx = self.tcx().at(span); MaybeResult::from(tcx.fn_abi_of_fn_ptr(self.param_env().and((sig, extra_args))).map_err( - |err| self.handle_fn_abi_err(err, span, FnAbiRequest::OfFnPtr { sig, extra_args }), + |err| self.handle_fn_abi_err(*err, span, FnAbiRequest::OfFnPtr { sig, extra_args }), )) } @@ -1342,7 +1584,11 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { // However, we don't do this early in order to avoid calling // `def_span` unconditionally (which may have a perf penalty). let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) }; - self.handle_fn_abi_err(err, span, FnAbiRequest::OfInstance { instance, extra_args }) + self.handle_fn_abi_err( + *err, + span, + FnAbiRequest::OfInstance { instance, extra_args }, + ) }), ) } diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index 71911a5a618..7a32cfb1085 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -1,6 +1,7 @@ use crate::arena::Arena; use rustc_data_structures::aligned::{align_of, Aligned}; use rustc_serialize::{Encodable, Encoder}; +use rustc_type_ir::{InferCtxtLike, OptWithInfcx}; use std::alloc::Layout; use std::cmp::Ordering; use std::fmt; @@ -119,6 +120,14 @@ impl<T: fmt::Debug> fmt::Debug for List<T> { (**self).fmt(f) } } +impl<'tcx, T: super::DebugWithInfcx<TyCtxt<'tcx>>> super::DebugWithInfcx<TyCtxt<'tcx>> for List<T> { + fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + fmt::Debug::fmt(&this.map(|this| this.as_slice()), f) + } +} impl<S: Encoder, T: Encodable<S>> Encodable<S> for List<T> { #[inline] @@ -202,6 +211,8 @@ unsafe impl<T: Sync> Sync for List<T> {} // We need this since `List` uses extern type `OpaqueListContents`. #[cfg(parallel_compiler)] use rustc_data_structures::sync::DynSync; + +use super::TyCtxt; #[cfg(parallel_compiler)] unsafe impl<T: DynSync> DynSync for List<T> {} diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 72341e656e2..0411890ab51 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -28,6 +28,7 @@ use crate::ty::fast_reject::SimplifiedType; use crate::ty::util::Discr; pub use adt::*; pub use assoc::*; +pub use generic_args::*; pub use generics::*; use rustc_ast as ast; use rustc_ast::node_id::NodeMap; @@ -53,7 +54,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ExpnId, ExpnKind, Span}; use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx}; pub use rustc_target::abi::{ReprFlags, ReprOptions}; -pub use subst::*; +pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, OptWithInfcx}; pub use vtable::*; use std::fmt::Debug; @@ -66,6 +67,10 @@ use std::{fmt, str}; pub use crate::ty::diagnostics::*; pub use rustc_type_ir::AliasKind::*; +pub use rustc_type_ir::ConstKind::{ + Bound as BoundCt, Error as ErrorCt, Expr as ExprCt, Infer as InferCt, Param as ParamCt, + Placeholder as PlaceholderCt, Unevaluated, Value, +}; pub use rustc_type_ir::DynKind::*; pub use rustc_type_ir::InferTy::*; pub use rustc_type_ir::RegionKind::*; @@ -77,11 +82,10 @@ pub use self::binding::BindingMode::*; pub use self::closure::{ is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo, CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList, - RootVariableMinCaptureList, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap, UpvarPath, - CAPTURE_STRUCT_LOCAL, + RootVariableMinCaptureList, UpvarCapture, UpvarId, UpvarPath, CAPTURE_STRUCT_LOCAL, }; pub use self::consts::{ - Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree, + Const, ConstData, ConstInt, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree, }; pub use self::context::{ tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, @@ -93,12 +97,12 @@ pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::BoundRegionKind::*; pub use self::sty::{ AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, - BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, + BoundVariableKind, CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, ConstKind, ConstVid, EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, - FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, - InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate, - PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, - Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo, + FreeRegion, GenSig, GeneratorArgs, GeneratorArgsParts, InlineConstArgs, InlineConstArgsParts, + ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection, + PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, Region, RegionKind, RegionVid, + TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ @@ -122,7 +126,6 @@ pub mod layout; pub mod normalize_erasing_regions; pub mod print; pub mod relate; -pub mod subst; pub mod trait_def; pub mod util; pub mod visit; @@ -136,6 +139,7 @@ mod consts; mod context; mod diagnostics; mod erase_regions; +mod generic_args; mod generics; mod impls_ty; mod instance; @@ -144,7 +148,7 @@ mod opaque_types; mod parameterized; mod rvalue_scopes; mod structural_impls; -#[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))] +#[allow(hidden_glob_reexports)] mod sty; mod typeck_results; @@ -456,6 +460,11 @@ impl ty::EarlyBoundRegion { } } +/// A statement that can be proven by a trait solver. This includes things that may +/// show up in where clauses, such as trait predicates and projection predicates, +/// and also things that are emitted as part of type checking such as `ObjectSafe` +/// predicate which is emitted when a type is coerced to a trait object. +/// /// Use this rather than `PredicateKind`, whenever possible. #[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] #[rustc_pass_by_value] @@ -487,11 +496,11 @@ impl<'tcx> Predicate<'tcx> { let kind = self .kind() .map_bound(|kind| match kind { - PredicateKind::Clause(Clause::Trait(TraitPredicate { + PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { trait_ref, constness, polarity, - })) => Some(PredicateKind::Clause(Clause::Trait(TraitPredicate { + })) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { trait_ref, constness, polarity: polarity.flip()?, @@ -505,10 +514,10 @@ impl<'tcx> Predicate<'tcx> { } pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self { - if let PredicateKind::Clause(Clause::Trait(TraitPredicate { trait_ref, constness, polarity })) = self.kind().skip_binder() + if let PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { trait_ref, constness, polarity })) = self.kind().skip_binder() && constness != BoundConstness::NotConst { - self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Clause(Clause::Trait(TraitPredicate { + self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { trait_ref, constness: BoundConstness::NotConst, polarity, @@ -520,10 +529,10 @@ impl<'tcx> Predicate<'tcx> { #[instrument(level = "debug", skip(tcx), ret)] pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool { match self.kind().skip_binder() { - ty::PredicateKind::Clause(ty::Clause::Trait(data)) => { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { tcx.trait_is_coinductive(data.def_id()) } - ty::PredicateKind::WellFormed(_) => true, + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => true, _ => false, } } @@ -536,21 +545,20 @@ impl<'tcx> Predicate<'tcx> { #[inline] pub fn allow_normalization(self) -> bool { match self.kind().skip_binder() { - PredicateKind::WellFormed(_) => false, - PredicateKind::Clause(Clause::Trait(_)) - | PredicateKind::Clause(Clause::RegionOutlives(_)) - | PredicateKind::Clause(Clause::TypeOutlives(_)) - | PredicateKind::Clause(Clause::Projection(_)) - | PredicateKind::Clause(Clause::ConstArgHasType(..)) + PredicateKind::Clause(ClauseKind::WellFormed(_)) => false, + PredicateKind::Clause(ClauseKind::Trait(_)) + | PredicateKind::Clause(ClauseKind::RegionOutlives(_)) + | PredicateKind::Clause(ClauseKind::TypeOutlives(_)) + | PredicateKind::Clause(ClauseKind::Projection(_)) + | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) | PredicateKind::AliasRelate(..) | PredicateKind::ObjectSafe(_) | PredicateKind::ClosureKind(_, _, _) | PredicateKind::Subtype(_) | PredicateKind::Coerce(_) - | PredicateKind::ConstEvaluatable(_) + | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_)) | PredicateKind::ConstEquate(_, _) - | PredicateKind::Ambiguous - | PredicateKind::TypeWellFormedFromEnv(_) => true, + | PredicateKind::Ambiguous => true, } } } @@ -561,11 +569,77 @@ impl rustc_errors::IntoDiagnosticArg for Predicate<'_> { } } +impl rustc_errors::IntoDiagnosticArg for Clause<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) + } +} + +/// A subset of predicates which can be assumed by the trait solver. They show up in +/// an item's where clauses, hence the name `Clause`, and may either be user-written +/// (such as traits) or may be inserted during lowering. +#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] +#[rustc_pass_by_value] +pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>); + +impl<'tcx> Clause<'tcx> { + pub fn as_predicate(self) -> Predicate<'tcx> { + Predicate(self.0) + } + + pub fn kind(self) -> Binder<'tcx, ClauseKind<'tcx>> { + self.0.internee.map_bound(|kind| match kind { + PredicateKind::Clause(clause) => clause, + _ => unreachable!(), + }) + } + + pub fn as_trait_clause(self) -> Option<Binder<'tcx, TraitPredicate<'tcx>>> { + let clause = self.kind(); + if let ty::ClauseKind::Trait(trait_clause) = clause.skip_binder() { + Some(clause.rebind(trait_clause)) + } else { + None + } + } + + pub fn as_projection_clause(self) -> Option<Binder<'tcx, ProjectionPredicate<'tcx>>> { + let clause = self.kind(); + if let ty::ClauseKind::Projection(projection_clause) = clause.skip_binder() { + Some(clause.rebind(projection_clause)) + } else { + None + } + } + + pub fn as_type_outlives_clause(self) -> Option<Binder<'tcx, TypeOutlivesPredicate<'tcx>>> { + let clause = self.kind(); + if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() { + Some(clause.rebind(o)) + } else { + None + } + } + + pub fn as_region_outlives_clause(self) -> Option<Binder<'tcx, RegionOutlivesPredicate<'tcx>>> { + let clause = self.kind(); + if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() { + Some(clause.rebind(o)) + } else { + None + } + } + + pub fn without_const(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + self.as_predicate().without_const(tcx).expect_clause() + } +} + #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] /// A clause is something that can appear in where bounds or be inferred /// by implied bounds. -pub enum Clause<'tcx> { +pub enum ClauseKind<'tcx> { /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` /// would be the type parameters. @@ -584,24 +658,27 @@ pub enum Clause<'tcx> { /// Ensures that a const generic argument to a parameter `const N: u8` /// is of type `u8`. ConstArgHasType(Const<'tcx>, Ty<'tcx>), + + /// No syntax: `T` well-formed. + WellFormed(GenericArg<'tcx>), + + /// Constant initializer must evaluate successfully. + ConstEvaluatable(ty::Const<'tcx>), } #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub enum PredicateKind<'tcx> { /// Prove a clause - Clause(Clause<'tcx>), - - /// No syntax: `T` well-formed. - WellFormed(GenericArg<'tcx>), + Clause(ClauseKind<'tcx>), /// Trait must be object-safe. ObjectSafe(DefId), /// No direct syntax. May be thought of as `where T: FnFoo<...>` - /// for some substitutions `...` and `T` being a closure type. + /// for some generic args `...` and `T` being a closure type. /// Satisfied (or refuted) once we know the closure's kind. - ClosureKind(DefId, SubstsRef<'tcx>, ClosureKind), + ClosureKind(DefId, GenericArgsRef<'tcx>, ClosureKind), /// `T1 <: T2` /// @@ -620,22 +697,14 @@ pub enum PredicateKind<'tcx> { /// logic. Coerce(CoercePredicate<'tcx>), - /// Constant initializer must evaluate successfully. - ConstEvaluatable(ty::Const<'tcx>), - /// Constants must be equal. The first component is the const that is expected. ConstEquate(Const<'tcx>, Const<'tcx>), - /// Represents a type found in the environment that we can use for implied bounds. - /// - /// Only used for Chalk. - TypeWellFormedFromEnv(Ty<'tcx>), - /// A marker predicate that is always ambiguous. /// Used for coherence to mark opaque types as possibly equal to each other but ambiguous. Ambiguous, - /// Separate from `Clause::Projection` which is used for normalization in new solver. + /// Separate from `ClauseKind::Projection` which is used for normalization in new solver. /// This predicate requires two terms to be equal to eachother. /// /// Only used for new solver @@ -672,7 +741,7 @@ pub struct CratePredicatesMap<'tcx> { pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>, } -impl<'tcx> Predicate<'tcx> { +impl<'tcx> Clause<'tcx> { /// Performs a substitution suitable for going from a /// poly-trait-ref to supertraits that must hold if that /// poly-trait-ref holds. This is slightly different from a normal @@ -682,7 +751,7 @@ impl<'tcx> Predicate<'tcx> { self, tcx: TyCtxt<'tcx>, trait_ref: &ty::PolyTraitRef<'tcx>, - ) -> Predicate<'tcx> { + ) -> Clause<'tcx> { // The interaction between HRTB and supertraits is not entirely // obvious. Let me walk you (and myself) through an example. // @@ -744,15 +813,15 @@ impl<'tcx> Predicate<'tcx> { // this trick achieves that). // Working through the second example: - // trait_ref: for<'x> T: Foo1<'^0.0>; substs: [T, '^0.0] - // predicate: for<'b> Self: Bar1<'a, '^0.0>; substs: [Self, 'a, '^0.0] + // trait_ref: for<'x> T: Foo1<'^0.0>; args: [T, '^0.0] + // predicate: for<'b> Self: Bar1<'a, '^0.0>; args: [Self, 'a, '^0.0] // We want to end up with: // for<'x, 'b> T: Bar1<'^0.0, '^0.1> // To do this: // 1) We must shift all bound vars in predicate by the length // of trait ref's bound vars. So, we would end up with predicate like // Self: Bar1<'a, '^0.1> - // 2) We can then apply the trait substs to this, ending up with + // 2) We can then apply the trait args to this, ending up with // T: Bar1<'^0.0, '^0.1> // 3) Finally, to create the final bound vars, we concatenate the bound // vars of the trait ref with those of the predicate: @@ -764,11 +833,17 @@ impl<'tcx> Predicate<'tcx> { let shifted_pred = tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder()); // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1> - let new = EarlyBinder::bind(shifted_pred).subst(tcx, trait_ref.skip_binder().substs); + let new = EarlyBinder::bind(shifted_pred).instantiate(tcx, trait_ref.skip_binder().args); // 3) ['x] + ['b] -> ['x, 'b] let bound_vars = tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars)); - tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars)) + + // FIXME: Is it really perf sensitive to use reuse_or_mk_predicate here? + tcx.reuse_or_mk_predicate( + self.as_predicate(), + ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars), + ) + .expect_clause() } } @@ -1004,7 +1079,7 @@ impl<'tcx> Term<'tcx> { _ => None, }, TermKind::Const(ct) => match ct.kind() { - ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def, uv.substs)), + ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def, uv.args)), _ => None, }, } @@ -1189,13 +1264,41 @@ impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { } } -impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> { +impl<'tcx> ToPredicate<'tcx> for ClauseKind<'tcx> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self))) } } +impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, ClauseKind<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + tcx.mk_predicate(self.map_bound(ty::PredicateKind::Clause)) + } +} + +impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> { + #[inline(always)] + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + self.as_predicate() + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ClauseKind<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + tcx.mk_predicate(Binder::dummy(ty::PredicateKind::Clause(self))).expect_clause() + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, ClauseKind<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + tcx.mk_predicate(self.map_bound(|clause| ty::PredicateKind::Clause(clause))).expect_clause() + } +} + impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { @@ -1203,6 +1306,29 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { } } +impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> { + #[inline(always)] + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> { + self.without_const() + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() + } +} + impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { @@ -1211,6 +1337,14 @@ impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { } } +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); + pred.to_predicate(tcx) + } +} + impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { #[inline(always)] fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { @@ -1236,31 +1370,45 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for TraitPredicate<'tcx> impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(Clause::Trait(p))).to_predicate(tcx) + self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() } } impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx) + self.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).to_predicate(tcx) } } impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(Clause::TypeOutlives(p))).to_predicate(tcx) + self.map_bound(|p| PredicateKind::Clause(ClauseKind::TypeOutlives(p))).to_predicate(tcx) } } impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(Clause::Projection(p))).to_predicate(tcx) + self.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() } } impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - PredicateKind::Clause(Clause::Trait(self)).to_predicate(tcx) + PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx) } } @@ -1268,63 +1416,76 @@ impl<'tcx> Predicate<'tcx> { pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> { let predicate = self.kind(); match predicate.skip_binder() { - PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)), - PredicateKind::Clause(Clause::Projection(..)) - | PredicateKind::Clause(Clause::ConstArgHasType(..)) + PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)), + PredicateKind::Clause(ClauseKind::Projection(..)) + | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) | PredicateKind::AliasRelate(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) - | PredicateKind::Clause(Clause::RegionOutlives(..)) - | PredicateKind::WellFormed(..) + | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) + | PredicateKind::Clause(ClauseKind::WellFormed(..)) | PredicateKind::ObjectSafe(..) | PredicateKind::ClosureKind(..) - | PredicateKind::Clause(Clause::TypeOutlives(..)) - | PredicateKind::ConstEvaluatable(..) + | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) + | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) | PredicateKind::ConstEquate(..) - | PredicateKind::Ambiguous - | PredicateKind::TypeWellFormedFromEnv(..) => None, + | PredicateKind::Ambiguous => None, } } pub fn to_opt_poly_projection_pred(self) -> Option<PolyProjectionPredicate<'tcx>> { let predicate = self.kind(); match predicate.skip_binder() { - PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)), - PredicateKind::Clause(Clause::Trait(..)) - | PredicateKind::Clause(Clause::ConstArgHasType(..)) + PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)), + PredicateKind::Clause(ClauseKind::Trait(..)) + | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) | PredicateKind::AliasRelate(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) - | PredicateKind::Clause(Clause::RegionOutlives(..)) - | PredicateKind::WellFormed(..) + | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) + | PredicateKind::Clause(ClauseKind::WellFormed(..)) | PredicateKind::ObjectSafe(..) | PredicateKind::ClosureKind(..) - | PredicateKind::Clause(Clause::TypeOutlives(..)) - | PredicateKind::ConstEvaluatable(..) + | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) + | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) | PredicateKind::ConstEquate(..) - | PredicateKind::Ambiguous - | PredicateKind::TypeWellFormedFromEnv(..) => None, + | PredicateKind::Ambiguous => None, } } pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> { let predicate = self.kind(); match predicate.skip_binder() { - PredicateKind::Clause(Clause::TypeOutlives(data)) => Some(predicate.rebind(data)), - PredicateKind::Clause(Clause::Trait(..)) - | PredicateKind::Clause(Clause::ConstArgHasType(..)) - | PredicateKind::Clause(Clause::Projection(..)) + PredicateKind::Clause(ClauseKind::TypeOutlives(data)) => Some(predicate.rebind(data)), + PredicateKind::Clause(ClauseKind::Trait(..)) + | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) + | PredicateKind::Clause(ClauseKind::Projection(..)) | PredicateKind::AliasRelate(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) - | PredicateKind::Clause(Clause::RegionOutlives(..)) - | PredicateKind::WellFormed(..) + | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) + | PredicateKind::Clause(ClauseKind::WellFormed(..)) | PredicateKind::ObjectSafe(..) | PredicateKind::ClosureKind(..) - | PredicateKind::ConstEvaluatable(..) + | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) | PredicateKind::ConstEquate(..) - | PredicateKind::Ambiguous - | PredicateKind::TypeWellFormedFromEnv(..) => None, + | PredicateKind::Ambiguous => None, + } + } + + /// Matches a `PredicateKind::Clause` and turns it into a `Clause`, otherwise returns `None`. + pub fn as_clause(self) -> Option<Clause<'tcx>> { + match self.kind().skip_binder() { + PredicateKind::Clause(..) => Some(self.expect_clause()), + _ => None, + } + } + + /// Assert that the predicate is a clause. + pub fn expect_clause(self) -> Clause<'tcx> { + match self.kind().skip_binder() { + PredicateKind::Clause(..) => Clause(self.0), + _ => bug!("{self} is not a clause"), } } } @@ -1350,7 +1511,7 @@ impl<'tcx> Predicate<'tcx> { /// [usize:Bar<isize>]]`. #[derive(Clone, Debug, TypeFoldable, TypeVisitable)] pub struct InstantiatedPredicates<'tcx> { - pub predicates: Vec<Predicate<'tcx>>, + pub predicates: Vec<Clause<'tcx>>, pub spans: Vec<Span>, } @@ -1369,9 +1530,9 @@ impl<'tcx> InstantiatedPredicates<'tcx> { } impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> { - type Item = (Predicate<'tcx>, Span); + type Item = (Clause<'tcx>, Span); - type IntoIter = std::iter::Zip<std::vec::IntoIter<Predicate<'tcx>>, std::vec::IntoIter<Span>>; + type IntoIter = std::iter::Zip<std::vec::IntoIter<Clause<'tcx>>, std::vec::IntoIter<Span>>; fn into_iter(self) -> Self::IntoIter { debug_assert_eq!(self.predicates.len(), self.spans.len()); @@ -1380,10 +1541,10 @@ impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> { } impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> { - type Item = (Predicate<'tcx>, Span); + type Item = (Clause<'tcx>, Span); type IntoIter = std::iter::Zip< - std::iter::Copied<std::slice::Iter<'a, Predicate<'tcx>>>, + std::iter::Copied<std::slice::Iter<'a, Clause<'tcx>>>, std::iter::Copied<std::slice::Iter<'a, Span>>, >; @@ -1397,7 +1558,7 @@ impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> { #[derive(TypeFoldable, TypeVisitable)] pub struct OpaqueTypeKey<'tcx> { pub def_id: LocalDefId, - pub substs: SubstsRef<'tcx>, + pub args: GenericArgsRef<'tcx>, } #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)] @@ -1468,21 +1629,21 @@ impl<'tcx> OpaqueHiddenType<'tcx> { // typeck errors have subpar spans for opaque types, so delay error reporting until borrowck. ignore_errors: bool, ) -> Self { - let OpaqueTypeKey { def_id, substs } = opaque_type_key; + let OpaqueTypeKey { def_id, args } = opaque_type_key; - // Use substs to build up a reverse map from regions to their + // Use args to build up a reverse map from regions to their // identity mappings. This is necessary because of `impl // Trait` lifetimes are computed by replacing existing // lifetimes with 'static and remapping only those used in the // `impl Trait` return type, resulting in the parameters // shifting. - let id_substs = InternalSubsts::identity_for_item(tcx, def_id); - debug!(?id_substs); + let id_args = GenericArgs::identity_for_item(tcx, def_id); + debug!(?id_args); - // This zip may have several times the same lifetime in `substs` paired with a different - // lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour: + // This zip may have several times the same lifetime in `args` paired with a different + // lifetime from `id_args`. Simply `collect`ing the iterator is the correct behaviour: // it will pick the last one, which is the one we introduced in the impl-trait desugaring. - let map = substs.iter().zip(id_substs).collect(); + let map = args.iter().zip(id_args).collect(); debug!("map = {:#?}", map); // Convert the type from the function into a type valid outside @@ -1533,7 +1694,7 @@ pub struct ParamEnv<'tcx> { /// want `Reveal::All`. /// /// Note: This is packed, use the reveal() method to access it. - packed: CopyTaggedPtr<&'tcx List<Predicate<'tcx>>, ParamTag, true>, + packed: CopyTaggedPtr<&'tcx List<Clause<'tcx>>, ParamTag, true>, } #[derive(Copy, Clone)] @@ -1599,7 +1760,7 @@ impl<'tcx> ParamEnv<'tcx> { } #[inline] - pub fn caller_bounds(self) -> &'tcx List<Predicate<'tcx>> { + pub fn caller_bounds(self) -> &'tcx List<Clause<'tcx>> { self.packed.pointer() } @@ -1633,7 +1794,7 @@ impl<'tcx> ParamEnv<'tcx> { /// Construct a trait environment with the given set of predicates. #[inline] pub fn new( - caller_bounds: &'tcx List<Predicate<'tcx>>, + caller_bounds: &'tcx List<Clause<'tcx>>, reveal: Reveal, constness: hir::Constness, ) -> Self { @@ -1874,6 +2035,22 @@ impl VariantDef { &self.fields[FieldIdx::from_u32(0)] } + + /// Returns the last field in this variant, if present. + #[inline] + pub fn tail_opt(&self) -> Option<&FieldDef> { + self.fields.raw.last() + } + + /// Returns the last field in this variant. + /// + /// # Panics + /// + /// Panics, if the variant has no fields. + #[inline] + pub fn tail(&self) -> &FieldDef { + self.tail_opt().expect("expected unsized ADT to have a tail field") + } } impl PartialEq for VariantDef { @@ -1987,10 +2164,10 @@ impl Hash for FieldDef { } impl<'tcx> FieldDef { - /// Returns the type of this field. The resulting type is not normalized. The `subst` is + /// Returns the type of this field. The resulting type is not normalized. The `arg` is /// typically obtained via the second field of [`TyKind::Adt`]. - pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> { - tcx.type_of(self.did).subst(tcx, subst) + pub fn ty(&self, tcx: TyCtxt<'tcx>, arg: GenericArgsRef<'tcx>) -> Ty<'tcx> { + tcx.type_of(self.did).instantiate(tcx, arg) } /// Computes the `Ident` of this variant by looking up the `Span` @@ -2214,8 +2391,8 @@ impl<'tcx> TyCtxt<'tcx> { let impl_trait_ref2 = self.impl_trait_ref(def_id2); // If either trait impl references an error, they're allowed to overlap, // as one of them essentially doesn't exist. - if impl_trait_ref1.is_some_and(|tr| tr.subst_identity().references_error()) - || impl_trait_ref2.is_some_and(|tr| tr.subst_identity().references_error()) + if impl_trait_ref1.is_some_and(|tr| tr.instantiate_identity().references_error()) + || impl_trait_ref2.is_some_and(|tr| tr.instantiate_identity().references_error()) { return Some(ImplOverlapKind::Permitted { marker: false }); } @@ -2511,7 +2688,6 @@ impl<'tcx> TyCtxt<'tcx> { | Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) => fn_def_id, None => { while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn { - debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder); def_id = self.parent(def_id); } def_id @@ -2536,33 +2712,20 @@ impl<'tcx> TyCtxt<'tcx> { return false; } - let Some(item) = self.opt_associated_item(def_id) else { return false; }; + let Some(item) = self.opt_associated_item(def_id) else { + return false; + }; if item.container != ty::AssocItemContainer::ImplContainer { return false; } - let Some(trait_item_def_id) = item.trait_item_def_id else { return false; }; - - if self.lower_impl_trait_in_trait_to_assoc_ty() { - return !self - .associated_types_for_impl_traits_in_associated_fn(trait_item_def_id) - .is_empty(); - } + let Some(trait_item_def_id) = item.trait_item_def_id else { + return false; + }; - // FIXME(RPITIT): This does a somewhat manual walk through the signature - // of the trait fn to look for any RPITITs, but that's kinda doing a lot - // of work. We can probably remove this when we refactor RPITITs to be - // associated types. - self.fn_sig(trait_item_def_id).subst_identity().skip_binder().output().walk().any(|arg| { - if let ty::GenericArgKind::Type(ty) = arg.unpack() - && let ty::Alias(ty::Projection, data) = ty.kind() - && self.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder - { - true - } else { - false - } - }) + return !self + .associated_types_for_impl_traits_in_associated_fn(trait_item_def_id) + .is_empty(); } } diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index a0c8d299f48..3c2c4483c73 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -9,7 +9,7 @@ use crate::traits::query::NoSolution; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder}; -use crate::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt, TypeVisitableExt}; +use crate::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt}; #[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)] pub enum NormalizationError<'tcx> { @@ -137,7 +137,7 @@ impl<'tcx> TyCtxt<'tcx> { /// use `try_subst_and_normalize_erasing_regions` instead. pub fn subst_and_normalize_erasing_regions<T>( self, - param_substs: SubstsRef<'tcx>, + param_args: GenericArgsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, value: EarlyBinder<T>, ) -> T @@ -146,12 +146,12 @@ impl<'tcx> TyCtxt<'tcx> { { debug!( "subst_and_normalize_erasing_regions(\ - param_substs={:?}, \ + param_args={:?}, \ value={:?}, \ param_env={:?})", - param_substs, value, param_env, + param_args, value, param_env, ); - let substituted = value.subst(self, param_substs); + let substituted = value.instantiate(self, param_args); self.normalize_erasing_regions(param_env, substituted) } @@ -161,7 +161,7 @@ impl<'tcx> TyCtxt<'tcx> { /// not assume that normalization succeeds. pub fn try_subst_and_normalize_erasing_regions<T>( self, - param_substs: SubstsRef<'tcx>, + param_args: GenericArgsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, value: EarlyBinder<T>, ) -> Result<T, NormalizationError<'tcx>> @@ -170,12 +170,12 @@ impl<'tcx> TyCtxt<'tcx> { { debug!( "subst_and_normalize_erasing_regions(\ - param_substs={:?}, \ + param_args={:?}, \ value={:?}, \ param_env={:?})", - param_substs, value, param_env, + param_args, value, param_env, ); - let substituted = value.subst(self, param_substs); + let substituted = value.instantiate(self, param_args); self.try_normalize_erasing_regions(param_env, substituted) } } diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index d1ed7be3d2e..7ae8be2dab3 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -1,7 +1,7 @@ use crate::error::ConstNotUsedTraitAlias; use crate::ty::fold::{TypeFolder, TypeSuperFoldable}; -use crate::ty::subst::{GenericArg, GenericArgKind}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{GenericArg, GenericArgKind}; use rustc_data_structures::fx::FxHashMap; use rustc_span::def_id::DefId; use rustc_span::Span; @@ -49,11 +49,11 @@ impl<'tcx> ReverseMapper<'tcx> { kind.fold_with(self) } - fn fold_closure_substs( + fn fold_closure_args( &mut self, def_id: DefId, - substs: ty::SubstsRef<'tcx>, - ) -> ty::SubstsRef<'tcx> { + args: ty::GenericArgsRef<'tcx>, + ) -> ty::GenericArgsRef<'tcx> { // I am a horrible monster and I pray for death. When // we encounter a closure here, it is always a closure // from within the function that we are currently @@ -79,7 +79,7 @@ impl<'tcx> ReverseMapper<'tcx> { // during codegen. let generics = self.tcx.generics_of(def_id); - self.tcx.mk_substs_from_iter(substs.iter().enumerate().map(|(index, kind)| { + self.tcx.mk_args_from_iter(args.iter().enumerate().map(|(index, kind)| { if index < generics.parent_count { // Accommodate missing regions in the parent kinds... self.fold_kind_no_missing_regions_error(kind) @@ -148,19 +148,19 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> { fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { match *ty.kind() { - ty::Closure(def_id, substs) => { - let substs = self.fold_closure_substs(def_id, substs); - self.tcx.mk_closure(def_id, substs) + ty::Closure(def_id, args) => { + let args = self.fold_closure_args(def_id, args); + Ty::new_closure(self.tcx, def_id, args) } - ty::Generator(def_id, substs, movability) => { - let substs = self.fold_closure_substs(def_id, substs); - self.tcx.mk_generator(def_id, substs, movability) + ty::Generator(def_id, args, movability) => { + let args = self.fold_closure_args(def_id, args); + Ty::new_generator(self.tcx, def_id, args, movability) } - ty::GeneratorWitnessMIR(def_id, substs) => { - let substs = self.fold_closure_substs(def_id, substs); - self.tcx.mk_generator_witness_mir(def_id, substs) + ty::GeneratorWitnessMIR(def_id, args) => { + let args = self.fold_closure_args(def_id, args); + Ty::new_generator_witness_mir(self.tcx, def_id, args) } ty::Param(param) => { @@ -186,7 +186,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> { .emit(); } - self.interner().ty_error_misc() + Ty::new_misc_error(self.tcx) } } } @@ -216,7 +216,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> { }) .emit_unless(self.ignore_errors); - self.interner().const_error(ct.ty(), guar) + ty::Const::new_error(self.tcx, guar, ct.ty()) } } } diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 13be15269f4..f1c38984296 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -52,6 +52,7 @@ trivially_parameterized_over_tcx! { usize, (), u32, + u64, bool, std::string::String, crate::metadata::ModChild, @@ -129,5 +130,6 @@ parameterized_over_tcx! { ty::Const, ty::Predicate, ty::Clause, + ty::ClauseKind, ty::GeneratorDiagnosticData, } diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 2de0a3f75dc..83a75d0c6b9 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -42,19 +42,19 @@ pub trait Printer<'tcx>: Sized { fn print_def_path( self, def_id: DefId, - substs: &'tcx [GenericArg<'tcx>], + args: &'tcx [GenericArg<'tcx>], ) -> Result<Self::Path, Self::Error> { - self.default_print_def_path(def_id, substs) + self.default_print_def_path(def_id, args) } fn print_impl_path( self, impl_def_id: DefId, - substs: &'tcx [GenericArg<'tcx>], + args: &'tcx [GenericArg<'tcx>], self_ty: Ty<'tcx>, trait_ref: Option<ty::TraitRef<'tcx>>, ) -> Result<Self::Path, Self::Error> { - self.default_print_impl_path(impl_def_id, substs, self_ty, trait_ref) + self.default_print_impl_path(impl_def_id, args, self_ty, trait_ref) } fn print_region(self, region: ty::Region<'tcx>) -> Result<Self::Region, Self::Error>; @@ -102,7 +102,7 @@ pub trait Printer<'tcx>: Sized { fn default_print_def_path( self, def_id: DefId, - substs: &'tcx [GenericArg<'tcx>], + args: &'tcx [GenericArg<'tcx>], ) -> Result<Self::Path, Self::Error> { let key = self.tcx().def_key(def_id); debug!(?key); @@ -117,25 +117,28 @@ pub trait Printer<'tcx>: Sized { let generics = self.tcx().generics_of(def_id); let self_ty = self.tcx().type_of(def_id); let impl_trait_ref = self.tcx().impl_trait_ref(def_id); - let (self_ty, impl_trait_ref) = if substs.len() >= generics.count() { + let (self_ty, impl_trait_ref) = if args.len() >= generics.count() { ( - self_ty.subst(self.tcx(), substs), - impl_trait_ref.map(|i| i.subst(self.tcx(), substs)), + self_ty.instantiate(self.tcx(), args), + impl_trait_ref.map(|i| i.instantiate(self.tcx(), args)), ) } else { - (self_ty.subst_identity(), impl_trait_ref.map(|i| i.subst_identity())) + ( + self_ty.instantiate_identity(), + impl_trait_ref.map(|i| i.instantiate_identity()), + ) }; - self.print_impl_path(def_id, substs, self_ty, impl_trait_ref) + self.print_impl_path(def_id, args, self_ty, impl_trait_ref) } _ => { let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; - let mut parent_substs = substs; + let mut parent_args = args; let mut trait_qualify_parent = false; - if !substs.is_empty() { + if !args.is_empty() { let generics = self.tcx().generics_of(def_id); - parent_substs = &substs[..generics.parent_count.min(substs.len())]; + parent_args = &args[..generics.parent_count.min(args.len())]; match key.disambiguated_data.data { // Closures' own generics are only captures, don't print them. @@ -148,10 +151,10 @@ pub trait Printer<'tcx>: Sized { // If we have any generic arguments to print, we do that // on top of the same path, but without its own generics. _ => { - if !generics.params.is_empty() && substs.len() >= generics.count() { - let args = generics.own_substs_no_defaults(self.tcx(), substs); + if !generics.params.is_empty() && args.len() >= generics.count() { + let args = generics.own_args_no_defaults(self.tcx(), args); return self.path_generic_args( - |cx| cx.print_def_path(def_id, parent_substs), + |cx| cx.print_def_path(def_id, parent_args), args, ); } @@ -162,7 +165,7 @@ pub trait Printer<'tcx>: Sized { // logic, instead of doing it when printing the child. trait_qualify_parent = generics.has_self && generics.parent == Some(parent_def_id) - && parent_substs.len() == generics.parent_count + && parent_args.len() == generics.parent_count && self.tcx().generics_of(parent_def_id).parent_count == 0; } @@ -172,11 +175,11 @@ pub trait Printer<'tcx>: Sized { let trait_ref = ty::TraitRef::new( cx.tcx(), parent_def_id, - parent_substs.iter().copied(), + parent_args.iter().copied(), ); cx.path_qualified(trait_ref.self_ty(), Some(trait_ref)) } else { - cx.print_def_path(parent_def_id, parent_substs) + cx.print_def_path(parent_def_id, parent_args) } }, &key.disambiguated_data, @@ -188,7 +191,7 @@ pub trait Printer<'tcx>: Sized { fn default_print_impl_path( self, impl_def_id: DefId, - _substs: &'tcx [GenericArg<'tcx>], + _args: &'tcx [GenericArg<'tcx>], self_ty: Ty<'tcx>, impl_trait_ref: Option<ty::TraitRef<'tcx>>, ) -> Result<Self::Path, Self::Error> { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 6156fdf7eac..e5633223464 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -94,6 +94,10 @@ macro_rules! define_helper { $tl.with(|c| c.set(self.0)) } } + + pub fn $name() -> bool { + $tl.with(|c| c.get()) + } )+ } } @@ -220,9 +224,9 @@ pub trait PrettyPrinter<'tcx>: fn print_value_path( self, def_id: DefId, - substs: &'tcx [GenericArg<'tcx>], + args: &'tcx [GenericArg<'tcx>], ) -> Result<Self::Path, Self::Error> { - self.print_def_path(def_id, substs) + self.print_def_path(def_id, args) } fn in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, Self::Error> @@ -675,12 +679,12 @@ pub trait PrettyPrinter<'tcx>: } p!(")") } - ty::FnDef(def_id, substs) => { - if NO_QUERIES.with(|q| q.get()) { - p!(print_def_path(def_id, substs)); + ty::FnDef(def_id, args) => { + if with_no_queries() { + p!(print_def_path(def_id, args)); } else { - let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs); - p!(print(sig), " {{", print_value_path(def_id, substs), "}}"); + let sig = self.tcx().fn_sig(def_id).instantiate(self.tcx(), args); + p!(print(sig), " {{", print_value_path(def_id, args), "}}"); } } ty::FnPtr(ref bare_fn) => p!(print(bare_fn)), @@ -711,8 +715,8 @@ pub trait PrettyPrinter<'tcx>: false => p!(write("{s}")), }, }, - ty::Adt(def, substs) => { - p!(print_def_path(def.did(), substs)); + ty::Adt(def, args) => { + p!(print_def_path(def.did(), args)); } ty::Dynamic(data, r, repr) => { let print_r = self.should_print_region(r); @@ -731,11 +735,11 @@ pub trait PrettyPrinter<'tcx>: ty::Foreign(def_id) => { p!(print_def_path(def_id, &[])); } - ty::Alias(ty::Projection | ty::Inherent, ref data) => { - if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get())) + ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ref data) => { + if !(self.should_print_verbose() || with_no_queries()) && self.tcx().is_impl_trait_in_trait(data.def_id) { - return self.pretty_print_opaque_impl_type(data.def_id, data.substs); + return self.pretty_print_opaque_impl_type(data.def_id, data.args); } else { p!(print(data)) } @@ -747,7 +751,7 @@ pub trait PrettyPrinter<'tcx>: false => p!(write("{name}")), }, }, - ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { + ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { // We use verbose printing in 'NO_QUERIES' mode, to // avoid needing to call `predicates_of`. This should // only affect certain debug messages (e.g. messages printed @@ -755,7 +759,7 @@ pub trait PrettyPrinter<'tcx>: // and should have no effect on any compiler output. if self.should_print_verbose() { // FIXME(eddyb) print this with `print_def_path`. - p!(write("Opaque({:?}, {:?})", def_id, substs)); + p!(write("Opaque({:?}, {:?})", def_id, args)); return Ok(self); } @@ -765,31 +769,31 @@ pub trait PrettyPrinter<'tcx>: // NOTE: I know we should check for NO_QUERIES here, but it's alright. // `type_of` on a type alias or assoc type should never cause a cycle. if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) = - *self.tcx().type_of(parent).subst_identity().kind() + *self.tcx().type_of(parent).instantiate_identity().kind() { if d == def_id { // If the type alias directly starts with the `impl` of the // opaque type we're printing, then skip the `::{opaque#1}`. - p!(print_def_path(parent, substs)); + p!(print_def_path(parent, args)); return Ok(self); } } // Complex opaque type, e.g. `type Foo = (i32, impl Debug);` - p!(print_def_path(def_id, substs)); + p!(print_def_path(def_id, args)); return Ok(self); } _ => { - if NO_QUERIES.with(|q| q.get()) { + if with_no_queries() { p!(print_def_path(def_id, &[])); return Ok(self); } else { - return self.pretty_print_opaque_impl_type(def_id, substs); + return self.pretty_print_opaque_impl_type(def_id, args); } } } } ty::Str => p!("str"), - ty::Generator(did, substs, movability) => { + ty::Generator(did, args, movability) => { p!(write("[")); let generator_kind = self.tcx().generator_kind(did).unwrap(); let should_print_movability = @@ -814,20 +818,20 @@ pub trait PrettyPrinter<'tcx>: self.tcx().sess.source_map().span_to_embeddable_string(span) )); } else { - p!(write("@"), print_def_path(did, substs)); + p!(write("@"), print_def_path(did, args)); } } else { - p!(print_def_path(did, substs)); + p!(print_def_path(did, args)); p!(" upvar_tys=("); - if !substs.as_generator().is_valid() { + if !args.as_generator().is_valid() { p!("unavailable"); } else { - self = self.comma_sep(substs.as_generator().upvar_tys())?; + self = self.comma_sep(args.as_generator().upvar_tys())?; } p!(")"); - if substs.as_generator().is_valid() { - p!(" ", print(substs.as_generator().witness())); + if args.as_generator().is_valid() { + p!(" ", print(args.as_generator().witness())); } } @@ -836,7 +840,7 @@ pub trait PrettyPrinter<'tcx>: ty::GeneratorWitness(types) => { p!(in_binder(&types)); } - ty::GeneratorWitnessMIR(did, substs) => { + ty::GeneratorWitnessMIR(did, args) => { p!(write("[")); if !self.tcx().sess.verbose() { p!("generator witness"); @@ -850,22 +854,22 @@ pub trait PrettyPrinter<'tcx>: self.tcx().sess.source_map().span_to_embeddable_string(span) )); } else { - p!(write("@"), print_def_path(did, substs)); + p!(write("@"), print_def_path(did, args)); } } else { - p!(print_def_path(did, substs)); + p!(print_def_path(did, args)); } p!("]") } - ty::Closure(did, substs) => { + ty::Closure(did, args) => { p!(write("[")); if !self.should_print_verbose() { p!(write("closure")); // FIXME(eddyb) should use `def_span`. if let Some(did) = did.as_local() { if self.tcx().sess.opts.unstable_opts.span_free_formats { - p!("@", print_def_path(did.to_def_id(), substs)); + p!("@", print_def_path(did.to_def_id(), args)); } else { let span = self.tcx().def_span(did); let preference = if FORCE_TRIMMED_PATH.with(|flag| flag.get()) { @@ -881,21 +885,21 @@ pub trait PrettyPrinter<'tcx>: )); } } else { - p!(write("@"), print_def_path(did, substs)); + p!(write("@"), print_def_path(did, args)); } } else { - p!(print_def_path(did, substs)); - if !substs.as_closure().is_valid() { - p!(" closure_substs=(unavailable)"); - p!(write(" substs={:?}", substs)); + p!(print_def_path(did, args)); + if !args.as_closure().is_valid() { + p!(" closure_args=(unavailable)"); + p!(write(" args={:?}", args)); } else { - p!(" closure_kind_ty=", print(substs.as_closure().kind_ty())); + p!(" closure_kind_ty=", print(args.as_closure().kind_ty())); p!( " closure_sig_as_fn_ptr_ty=", - print(substs.as_closure().sig_as_fn_ptr_ty()) + print(args.as_closure().sig_as_fn_ptr_ty()) ); p!(" upvar_tys=("); - self = self.comma_sep(substs.as_closure().upvar_tys())?; + self = self.comma_sep(args.as_closure().upvar_tys())?; p!(")"); } } @@ -911,7 +915,7 @@ pub trait PrettyPrinter<'tcx>: fn pretty_print_opaque_impl_type( mut self, def_id: DefId, - substs: &'tcx ty::List<ty::GenericArg<'tcx>>, + args: &'tcx ty::List<ty::GenericArg<'tcx>>, ) -> Result<Self::Type, Self::Error> { let tcx = self.tcx(); @@ -924,11 +928,11 @@ pub trait PrettyPrinter<'tcx>: let mut is_sized = false; let mut lifetimes = SmallVec::<[ty::Region<'tcx>; 1]>::new(); - for (predicate, _) in bounds.subst_iter_copied(tcx, substs) { + for (predicate, _) in bounds.iter_instantiated_copied(tcx, args) { let bound_predicate = predicate.kind(); match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => { + ty::ClauseKind::Trait(pred) => { let trait_ref = bound_predicate.rebind(pred.trait_ref); // Don't print + Sized, but rather + ?Sized if absent. @@ -939,7 +943,7 @@ pub trait PrettyPrinter<'tcx>: self.insert_trait_and_projection(trait_ref, None, &mut traits, &mut fn_traits); } - ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => { + ty::ClauseKind::Projection(pred) => { let proj_ref = bound_predicate.rebind(pred); let trait_ref = proj_ref.required_poly_trait_ref(tcx); @@ -953,7 +957,7 @@ pub trait PrettyPrinter<'tcx>: &mut fn_traits, ); } - ty::PredicateKind::Clause(ty::Clause::TypeOutlives(outlives)) => { + ty::ClauseKind::TypeOutlives(outlives) => { lifetimes.push(outlives.1); } _ => {} @@ -974,9 +978,9 @@ pub trait PrettyPrinter<'tcx>: define_scoped_cx!(cx); // Get the (single) generic ty (the args) of this FnOnce trait ref. let generics = tcx.generics_of(trait_ref.def_id); - let args = generics.own_substs_no_defaults(tcx, trait_ref.substs); + let own_args = generics.own_args_no_defaults(tcx, trait_ref.args); - match (entry.return_ty, args[0].expect_ty()) { + match (entry.return_ty, own_args[0].expect_ty()) { // We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded // a return type. (Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => { @@ -1040,12 +1044,12 @@ pub trait PrettyPrinter<'tcx>: p!(print(trait_ref.print_only_trait_name())); let generics = tcx.generics_of(trait_ref.def_id); - let args = generics.own_substs_no_defaults(tcx, trait_ref.substs); + let own_args = generics.own_args_no_defaults(tcx, trait_ref.args); - if !args.is_empty() || !assoc_items.is_empty() { + if !own_args.is_empty() || !assoc_items.is_empty() { let mut first = true; - for ty in args { + for ty in own_args { if first { p!("<"); first = false; @@ -1064,8 +1068,8 @@ pub trait PrettyPrinter<'tcx>: && assoc.trait_container(tcx) == tcx.lang_items().gen_trait() && assoc.name == rustc_span::sym::Return { - if let ty::Generator(_, substs, _) = substs.type_at(0).kind() { - let return_ty = substs.as_generator().return_ty(); + if let ty::Generator(_, args, _) = args.type_at(0).kind() { + let return_ty = args.as_generator().return_ty(); if !return_ty.is_ty_var() { return_ty.into() } else { @@ -1178,7 +1182,7 @@ pub trait PrettyPrinter<'tcx>: &def_key.disambiguated_data, ) }, - &alias_ty.substs[1..], + &alias_ty.args[1..], ) } @@ -1207,7 +1211,7 @@ pub trait PrettyPrinter<'tcx>: // Special-case `Fn(...) -> ...` and re-sugar it. let fn_trait_kind = cx.tcx().fn_trait_kind_from_def_id(principal.def_id); if !cx.should_print_verbose() && fn_trait_kind.is_some() { - if let ty::Tuple(tys) = principal.substs.type_at(0).kind() { + if let ty::Tuple(tys) = principal.args.type_at(0).kind() { let mut projections = predicates.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { p!(pretty_fn_sig( @@ -1224,13 +1228,13 @@ pub trait PrettyPrinter<'tcx>: // in order to place the projections inside the `<...>`. if !resugared { // Use a type that can't appear in defaults of type parameters. - let dummy_cx = cx.tcx().mk_fresh_ty(0); + let dummy_cx = Ty::new_fresh(cx.tcx(), 0); let principal = principal.with_self_ty(cx.tcx(), dummy_cx); let args = cx .tcx() .generics_of(principal.def_id) - .own_substs_no_defaults(cx.tcx(), principal.substs); + .own_args_no_defaults(cx.tcx(), principal.args); let mut projections = predicates.projection_bounds(); @@ -1337,10 +1341,10 @@ pub trait PrettyPrinter<'tcx>: } match ct.kind() { - ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => { + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => { match self.tcx().def_kind(def) { DefKind::Const | DefKind::AssocConst => { - p!(print_value_path(def, substs)) + p!(print_value_path(def, args)) } DefKind::AnonConst => { if def.is_local() @@ -1389,11 +1393,12 @@ pub trait PrettyPrinter<'tcx>: self, scalar: Scalar, ty: Ty<'tcx>, - print_ty: bool, ) -> Result<Self::Const, Self::Error> { match scalar { - Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty, print_ty), - Scalar::Int(int) => self.pretty_print_const_scalar_int(int, ty, print_ty), + Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty), + Scalar::Int(int) => { + self.pretty_print_const_scalar_int(int, ty, /* print_ty */ true) + } } } @@ -1401,7 +1406,6 @@ pub trait PrettyPrinter<'tcx>: mut self, ptr: Pointer, ty: Ty<'tcx>, - print_ty: bool, ) -> Result<Self::Const, Self::Error> { define_scoped_cx!(self); @@ -1445,7 +1449,7 @@ pub trait PrettyPrinter<'tcx>: self.tcx().try_get_global_alloc(alloc_id) { self = self.typed_value( - |this| this.print_value_path(instance.def_id(), instance.substs), + |this| this.print_value_path(instance.def_id(), instance.args), |this| this.print_type(ty), " as ", )?; @@ -1455,7 +1459,7 @@ pub trait PrettyPrinter<'tcx>: _ => {} } // Any pointer values not covered by a branch above - self = self.pretty_print_const_pointer(ptr, ty, print_ty)?; + self = self.pretty_print_const_pointer(ptr, ty)?; Ok(self) } @@ -1523,24 +1527,18 @@ pub trait PrettyPrinter<'tcx>: /// This is overridden for MIR printing because we only want to hide alloc ids from users, not /// from MIR where it is actually useful. fn pretty_print_const_pointer<Prov: Provenance>( - mut self, + self, _: Pointer<Prov>, ty: Ty<'tcx>, - print_ty: bool, ) -> Result<Self::Const, Self::Error> { - if print_ty { - self.typed_value( - |mut this| { - this.write_str("&_")?; - Ok(this) - }, - |this| this.print_type(ty), - ": ", - ) - } else { - self.write_str("&_")?; - Ok(self) - } + self.typed_value( + |mut this| { + this.write_str("&_")?; + Ok(this) + }, + |this| this.print_type(ty), + ": ", + ) } fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result<Self::Const, Self::Error> { @@ -1597,7 +1595,8 @@ pub trait PrettyPrinter<'tcx>: } // Aggregates, printed as array/tuple/struct/variant construction syntax. (ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) => { - let contents = self.tcx().destructure_const(self.tcx().mk_const(valtree, ty)); + let contents = + self.tcx().destructure_const(ty::Const::new_value(self.tcx(), valtree, ty)); let fields = contents.fields.iter().copied(); match *ty.kind() { ty::Array(..) => { @@ -1620,11 +1619,11 @@ pub trait PrettyPrinter<'tcx>: ": ", )?; } - ty::Adt(def, substs) => { + ty::Adt(def, args) => { let variant_idx = contents.variant.expect("destructed const of adt without variant idx"); let variant_def = &def.variant(variant_idx); - p!(print_value_path(variant_def.def_id, substs)); + p!(print_value_path(variant_def.def_id, args)); match variant_def.ctor_kind() { Some(CtorKind::Const) => {} Some(CtorKind::Fn) => { @@ -1674,7 +1673,7 @@ pub trait PrettyPrinter<'tcx>: fn pretty_closure_as_impl( mut self, - closure: ty::ClosureSubsts<'tcx>, + closure: ty::ClosureArgs<'tcx>, ) -> Result<Self::Const, Self::Error> { let sig = closure.sig(); let kind = closure.kind_ty().to_opt_closure_kind().unwrap_or(ty::ClosureKind::Fn); @@ -1746,7 +1745,8 @@ impl DerefMut for FmtPrinter<'_, '_> { impl<'a, 'tcx> FmtPrinter<'a, 'tcx> { pub fn new(tcx: TyCtxt<'tcx>, ns: Namespace) -> Self { - Self::new_with_limit(tcx, ns, tcx.type_length_limit()) + let limit = if with_no_queries() { Limit::new(1048576) } else { tcx.type_length_limit() }; + Self::new_with_limit(tcx, ns, limit) } pub fn new_with_limit(tcx: TyCtxt<'tcx>, ns: Namespace, type_length_limit: Limit) -> Self { @@ -1798,29 +1798,29 @@ impl<'t> TyCtxt<'t> { /// Returns a string identifying this `DefId`. This string is /// suitable for user output. pub fn def_path_str(self, def_id: impl IntoQueryParam<DefId>) -> String { - self.def_path_str_with_substs(def_id, &[]) + self.def_path_str_with_args(def_id, &[]) } - pub fn def_path_str_with_substs( + pub fn def_path_str_with_args( self, def_id: impl IntoQueryParam<DefId>, - substs: &'t [GenericArg<'t>], + args: &'t [GenericArg<'t>], ) -> String { let def_id = def_id.into_query_param(); let ns = guess_def_namespace(self, def_id); debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); - FmtPrinter::new(self, ns).print_def_path(def_id, substs).unwrap().into_buffer() + FmtPrinter::new(self, ns).print_def_path(def_id, args).unwrap().into_buffer() } - pub fn value_path_str_with_substs( + pub fn value_path_str_with_args( self, def_id: impl IntoQueryParam<DefId>, - substs: &'t [GenericArg<'t>], + args: &'t [GenericArg<'t>], ) -> String { let def_id = def_id.into_query_param(); let ns = guess_def_namespace(self, def_id); debug!("value_path_str: def_id={:?}, ns={:?}", def_id, ns); - FmtPrinter::new(self, ns).print_value_path(def_id, substs).unwrap().into_buffer() + FmtPrinter::new(self, ns).print_value_path(def_id, args).unwrap().into_buffer() } } @@ -1847,11 +1847,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn print_def_path( mut self, def_id: DefId, - substs: &'tcx [GenericArg<'tcx>], + args: &'tcx [GenericArg<'tcx>], ) -> Result<Self::Path, Self::Error> { define_scoped_cx!(self); - if substs.is_empty() { + if args.is_empty() { match self.try_print_trimmed_def_path(def_id)? { (cx, true) => return Ok(cx), (cx, false) => self = cx, @@ -1900,7 +1900,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { } } - self.default_print_def_path(def_id, substs) + self.default_print_def_path(def_id, args) } fn print_region(self, region: ty::Region<'tcx>) -> Result<Self::Region, Self::Error> { @@ -1932,7 +1932,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> { self.empty_path = true; if cnum == LOCAL_CRATE { - if self.tcx.sess.rust_2018() { + if self.tcx.sess.at_least_rust_2018() { // We add the `crate::` keyword on Rust 2018, only when desired. if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { write!(self, "{}", kw::Crate)?; @@ -2044,10 +2044,10 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { fn print_value_path( mut self, def_id: DefId, - substs: &'tcx [GenericArg<'tcx>], + args: &'tcx [GenericArg<'tcx>], ) -> Result<Self::Path, Self::Error> { let was_in_value = std::mem::replace(&mut self.in_value, true); - self = self.print_def_path(def_id, substs)?; + self = self.print_def_path(def_id, args)?; self.in_value = was_in_value; Ok(self) @@ -2150,7 +2150,6 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { self, p: Pointer<Prov>, ty: Ty<'tcx>, - print_ty: bool, ) -> Result<Self::Const, Self::Error> { let print = |mut this: Self| { define_scoped_cx!(this); @@ -2161,11 +2160,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { } Ok(this) }; - if print_ty { - self.typed_value(print, |this| this.print_type(ty), ": ") - } else { - print(self) - } + self.typed_value(print, |this| this.print_type(ty), ": ") } } @@ -2700,7 +2695,7 @@ impl<'tcx> ty::PolyTraitPredicate<'tcx> { #[derive(Debug, Copy, Clone, Lift)] pub struct PrintClosureAsImpl<'tcx> { - pub closure: ty::ClosureSubsts<'tcx>, + pub closure: ty::ClosureArgs<'tcx>, } forward_display_to_print! { @@ -2741,7 +2736,7 @@ define_print_and_forward_display! { ty::ExistentialTraitRef<'tcx> { // Use a type that can't appear in defaults of type parameters. - let dummy_self = cx.tcx().mk_fresh_ty(0); + let dummy_self = Ty::new_fresh(cx.tcx(),0); let trait_ref = self.with_self_ty(cx.tcx(), dummy_self); p!(print(trait_ref.print_only_trait_path())) } @@ -2776,7 +2771,7 @@ define_print_and_forward_display! { } TraitRefPrintOnlyTraitPath<'tcx> { - p!(print_def_path(self.0.def_id, self.0.substs)); + p!(print_def_path(self.0.def_id, self.0.args)); } TraitRefPrintOnlyTraitName<'tcx> { @@ -2847,7 +2842,7 @@ define_print_and_forward_display! { if let DefKind::Impl { of_trait: false } = cx.tcx().def_kind(cx.tcx().parent(self.def_id)) { p!(pretty_print_inherent_projection(self)) } else { - p!(print_def_path(self.def_id, self.substs)); + p!(print_def_path(self.def_id, self.args)); } } @@ -2864,37 +2859,46 @@ define_print_and_forward_display! { p!(print(binder)) } + ty::Clause<'tcx> { + p!(print(self.kind())) + } + + ty::ClauseKind<'tcx> { + match *self { + ty::ClauseKind::Trait(ref data) => { + p!(print(data)) + } + ty::ClauseKind::RegionOutlives(predicate) => p!(print(predicate)), + ty::ClauseKind::TypeOutlives(predicate) => p!(print(predicate)), + ty::ClauseKind::Projection(predicate) => p!(print(predicate)), + ty::ClauseKind::ConstArgHasType(ct, ty) => { + p!("the constant `", print(ct), "` has type `", print(ty), "`") + }, + ty::ClauseKind::WellFormed(arg) => p!(print(arg), " well-formed"), + ty::ClauseKind::ConstEvaluatable(ct) => { + p!("the constant `", print(ct), "` can be evaluated") + } + } + } + ty::PredicateKind<'tcx> { match *self { - ty::PredicateKind::Clause(ty::Clause::Trait(ref data)) => { + ty::PredicateKind::Clause(data) => { p!(print(data)) } ty::PredicateKind::Subtype(predicate) => p!(print(predicate)), ty::PredicateKind::Coerce(predicate) => p!(print(predicate)), - ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => p!(print(predicate)), - ty::PredicateKind::Clause(ty::Clause::TypeOutlives(predicate)) => p!(print(predicate)), - ty::PredicateKind::Clause(ty::Clause::Projection(predicate)) => p!(print(predicate)), - ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { - p!("the constant `", print(ct), "` has type `", print(ty), "`") - }, - ty::PredicateKind::WellFormed(arg) => p!(print(arg), " well-formed"), ty::PredicateKind::ObjectSafe(trait_def_id) => { p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe") } - ty::PredicateKind::ClosureKind(closure_def_id, _closure_substs, kind) => p!( + ty::PredicateKind::ClosureKind(closure_def_id, _closure_args, kind) => p!( "the closure `", print_value_path(closure_def_id, &[]), write("` implements the trait `{}`", kind) ), - ty::PredicateKind::ConstEvaluatable(ct) => { - p!("the constant `", print(ct), "` can be evaluated") - } ty::PredicateKind::ConstEquate(c1, c2) => { p!("the constant `", print(c1), "` equals `", print(c2), "`") } - ty::PredicateKind::TypeWellFormedFromEnv(ty) => { - p!("the type `", print(ty), "` is found in the environment") - } ty::PredicateKind::Ambiguous => p!("ambiguous"), ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)), } @@ -2987,7 +2991,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N /// /// The implementation uses similar import discovery logic to that of 'use' suggestions. /// -/// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths`]. +/// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths!`]. fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> { let mut map: FxHashMap<DefId, Symbol> = FxHashMap::default(); diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 8bcae3d9ab7..bf9adabdab1 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -6,7 +6,7 @@ use crate::ty::error::{ExpectedFound, TypeError}; use crate::ty::{self, Expr, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable}; -use crate::ty::{GenericArg, GenericArgKind, SubstsRef}; +use crate::ty::{GenericArg, GenericArgKind, GenericArgsRef}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_target::spec::abi; @@ -43,23 +43,23 @@ pub trait TypeRelation<'tcx>: Sized { Relate::relate(self, a, b) } - /// Relate the two substitutions for the given item. The default + /// Relate the two args for the given item. The default /// is to look up the variance for the item and proceed /// accordingly. - fn relate_item_substs( + fn relate_item_args( &mut self, item_def_id: DefId, - a_subst: SubstsRef<'tcx>, - b_subst: SubstsRef<'tcx>, - ) -> RelateResult<'tcx, SubstsRef<'tcx>> { + a_arg: GenericArgsRef<'tcx>, + b_arg: GenericArgsRef<'tcx>, + ) -> RelateResult<'tcx, GenericArgsRef<'tcx>> { debug!( - "relate_item_substs(item_def_id={:?}, a_subst={:?}, b_subst={:?})", - item_def_id, a_subst, b_subst + "relate_item_args(item_def_id={:?}, a_arg={:?}, b_arg={:?})", + item_def_id, a_arg, b_arg ); let tcx = self.tcx(); let opt_variances = tcx.variances_of(item_def_id); - relate_substs_with_variances(self, item_def_id, opt_variances, a_subst, b_subst, true) + relate_args_with_variances(self, item_def_id, opt_variances, a_arg, b_arg, true) } /// Switch variance for the purpose of relating `a` and `b`. @@ -134,31 +134,32 @@ pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>( } #[inline] -pub fn relate_substs<'tcx, R: TypeRelation<'tcx>>( +pub fn relate_args<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, - a_subst: SubstsRef<'tcx>, - b_subst: SubstsRef<'tcx>, -) -> RelateResult<'tcx, SubstsRef<'tcx>> { - relation.tcx().mk_substs_from_iter(iter::zip(a_subst, b_subst).map(|(a, b)| { + a_arg: GenericArgsRef<'tcx>, + b_arg: GenericArgsRef<'tcx>, +) -> RelateResult<'tcx, GenericArgsRef<'tcx>> { + relation.tcx().mk_args_from_iter(iter::zip(a_arg, b_arg).map(|(a, b)| { relation.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b) })) } -pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>( +pub fn relate_args_with_variances<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, ty_def_id: DefId, variances: &[ty::Variance], - a_subst: SubstsRef<'tcx>, - b_subst: SubstsRef<'tcx>, + a_arg: GenericArgsRef<'tcx>, + b_arg: GenericArgsRef<'tcx>, fetch_ty_for_diag: bool, -) -> RelateResult<'tcx, SubstsRef<'tcx>> { +) -> RelateResult<'tcx, GenericArgsRef<'tcx>> { let tcx = relation.tcx(); let mut cached_ty = None; - let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| { + let params = iter::zip(a_arg, b_arg).enumerate().map(|(i, (a, b))| { let variance = variances[i]; let variance_info = if variance == ty::Invariant && fetch_ty_for_diag { - let ty = *cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst)); + let ty = + *cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).instantiate(tcx, a_arg)); ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() } } else { ty::VarianceDiagInfo::default() @@ -166,7 +167,7 @@ pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>( relation.relate_with_variance(variance, variance_info, a, b) }); - tcx.mk_substs_from_iter(params) + tcx.mk_args_from_iter(params) } impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { @@ -272,8 +273,8 @@ impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> { if a.def_id != b.def_id { Err(TypeError::ProjectionMismatched(expected_found(relation, a.def_id, b.def_id))) } else { - let substs = relation.relate(a.substs, b.substs)?; - Ok(relation.tcx().mk_alias_ty(a.def_id, substs)) + let args = relation.relate(a.args, b.args)?; + Ok(relation.tcx().mk_alias_ty(a.def_id, args)) } } } @@ -293,13 +294,13 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { a.term, b.term, )?; - let substs = relation.relate_with_variance( + let args = relation.relate_with_variance( ty::Invariant, ty::VarianceDiagInfo::default(), - a.substs, - b.substs, + a.args, + b.args, )?; - Ok(ty::ExistentialProjection { def_id: a.def_id, substs, term }) + Ok(ty::ExistentialProjection { def_id: a.def_id, args, term }) } } } @@ -314,8 +315,8 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { if a.def_id != b.def_id { Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id))) } else { - let substs = relate_substs(relation, a.substs, b.substs)?; - Ok(ty::TraitRef::new(relation.tcx(), a.def_id, substs)) + let args = relate_args(relation, a.args, b.args)?; + Ok(ty::TraitRef::new(relation.tcx(), a.def_id, args)) } } } @@ -330,8 +331,8 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { if a.def_id != b.def_id { Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id))) } else { - let substs = relate_substs(relation, a.substs, b.substs)?; - Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs }) + let args = relate_args(relation, a.args, b.args)?; + Ok(ty::ExistentialTraitRef { def_id: a.def_id, args }) } } } @@ -391,13 +392,13 @@ impl<'tcx> Relate<'tcx> for Ty<'tcx> { /// Relates `a` and `b` structurally, calling the relation for all nested values. /// Any semantic equality, e.g. of projections, and inference variables have to be /// handled by the caller. +#[instrument(level = "trace", skip(relation), ret)] pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, a: Ty<'tcx>, b: Ty<'tcx>, ) -> RelateResult<'tcx, Ty<'tcx>> { let tcx = relation.tcx(); - debug!("structurally_relate_tys: a={:?} b={:?}", a, b); match (a.kind(), b.kind()) { (&ty::Infer(_), _) | (_, &ty::Infer(_)) => { // The caller should handle these cases! @@ -408,7 +409,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( bug!("bound types encountered in structurally_relate_tys") } - (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error(guar)), + (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(tcx, guar)), (&ty::Never, _) | (&ty::Char, _) @@ -426,12 +427,12 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( (ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a), - (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs)) if a_def == b_def => { - let substs = relation.relate_item_substs(a_def.did(), a_substs, b_substs)?; - Ok(tcx.mk_adt(a_def, substs)) + (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args)) if a_def == b_def => { + let args = relation.relate_item_args(a_def.did(), a_args, b_args)?; + Ok(Ty::new_adt(tcx, a_def, args)) } - (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(tcx.mk_foreign(a_id)), + (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(tcx, a_id)), (&ty::Dynamic(a_obj, a_region, a_repr), &ty::Dynamic(b_obj, b_region, b_repr)) if a_repr == b_repr => @@ -439,17 +440,17 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| { relation.relate(a_region, b_region) })?; - Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound, a_repr)) + Ok(Ty::new_dynamic(tcx, relation.relate(a_obj, b_obj)?, region_bound, a_repr)) } - (&ty::Generator(a_id, a_substs, movability), &ty::Generator(b_id, b_substs, _)) + (&ty::Generator(a_id, a_args, movability), &ty::Generator(b_id, b_args, _)) if a_id == b_id => { // All Generator types with the same id represent // the (anonymous) type of the same generator expression. So // all of their regions should be equated. - let substs = relation.relate(a_substs, b_substs)?; - Ok(tcx.mk_generator(a_id, substs, movability)) + let args = relation.relate(a_args, b_args)?; + Ok(Ty::new_generator(tcx, a_id, args, movability)) } (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => { @@ -459,30 +460,30 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( let b_types = b_types.map_bound(GeneratorWitness); // Then remove the GeneratorWitness for the result let types = relation.relate(a_types, b_types)?.map_bound(|witness| witness.0); - Ok(tcx.mk_generator_witness(types)) + Ok(Ty::new_generator_witness(tcx, types)) } - (&ty::GeneratorWitnessMIR(a_id, a_substs), &ty::GeneratorWitnessMIR(b_id, b_substs)) + (&ty::GeneratorWitnessMIR(a_id, a_args), &ty::GeneratorWitnessMIR(b_id, b_args)) if a_id == b_id => { // All GeneratorWitness types with the same id represent // the (anonymous) type of the same generator expression. So // all of their regions should be equated. - let substs = relation.relate(a_substs, b_substs)?; - Ok(tcx.mk_generator_witness_mir(a_id, substs)) + let args = relation.relate(a_args, b_args)?; + Ok(Ty::new_generator_witness_mir(tcx, a_id, args)) } - (&ty::Closure(a_id, a_substs), &ty::Closure(b_id, b_substs)) if a_id == b_id => { + (&ty::Closure(a_id, a_args), &ty::Closure(b_id, b_args)) if a_id == b_id => { // All Closure types with the same id represent // the (anonymous) type of the same closure expression. So // all of their regions should be equated. - let substs = relation.relate(a_substs, b_substs)?; - Ok(tcx.mk_closure(a_id, &substs)) + let args = relation.relate(a_args, b_args)?; + Ok(Ty::new_closure(tcx, a_id, &args)) } (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => { let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?; - Ok(tcx.mk_ptr(mt)) + Ok(Ty::new_ptr(tcx, mt)) } (&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => { @@ -490,13 +491,13 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl }; let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl }; let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?; - Ok(tcx.mk_ref(r, mt)) + Ok(Ty::new_ref(tcx, r, mt)) } (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => { let t = relation.relate(a_t, b_t)?; match relation.relate(sz_a, sz_b) { - Ok(sz) => Ok(tcx.mk_array_with_const_len(t, sz)), + Ok(sz) => Ok(Ty::new_array_with_const_len(tcx, t, sz)), Err(err) => { // Check whether the lengths are both concrete/known values, // but are unequal, for better diagnostics. @@ -519,12 +520,15 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( (&ty::Slice(a_t), &ty::Slice(b_t)) => { let t = relation.relate(a_t, b_t)?; - Ok(tcx.mk_slice(t)) + Ok(Ty::new_slice(tcx, t)) } (&ty::Tuple(as_), &ty::Tuple(bs)) => { if as_.len() == bs.len() { - Ok(tcx.mk_tup_from_iter(iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)))?) + Ok(Ty::new_tup_from_iter( + tcx, + 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 { @@ -532,43 +536,39 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( } } - (&ty::FnDef(a_def_id, a_substs), &ty::FnDef(b_def_id, b_substs)) - if a_def_id == b_def_id => - { - let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?; - Ok(tcx.mk_fn_def(a_def_id, substs)) + (&ty::FnDef(a_def_id, a_args), &ty::FnDef(b_def_id, b_args)) if a_def_id == b_def_id => { + let args = relation.relate_item_args(a_def_id, a_args, b_args)?; + Ok(Ty::new_fn_def(tcx, a_def_id, args)) } (&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) => { let fty = relation.relate(a_fty, b_fty)?; - Ok(tcx.mk_fn_ptr(fty)) - } - - // these two are already handled downstream in case of lazy normalization - (&ty::Alias(ty::Projection, a_data), &ty::Alias(ty::Projection, b_data)) => { - let projection_ty = relation.relate(a_data, b_data)?; - Ok(tcx.mk_projection(projection_ty.def_id, projection_ty.substs)) - } - - (&ty::Alias(ty::Inherent, a_data), &ty::Alias(ty::Inherent, b_data)) => { - let alias_ty = relation.relate(a_data, b_data)?; - Ok(tcx.mk_alias(ty::Inherent, tcx.mk_alias_ty(alias_ty.def_id, alias_ty.substs))) + Ok(Ty::new_fn_ptr(tcx, fty)) } + // The args of opaque types may not all be invariant, so we have + // to treat them separately from other aliases. ( - &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, substs: a_substs, .. }), - &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, substs: b_substs, .. }), + &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, args: a_args, .. }), + &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, args: b_args, .. }), ) if a_def_id == b_def_id => { let opt_variances = tcx.variances_of(a_def_id); - let substs = relate_substs_with_variances( + let args = relate_args_with_variances( relation, a_def_id, opt_variances, - a_substs, - b_substs, + a_args, + b_args, false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle )?; - Ok(tcx.mk_opaque(a_def_id, substs)) + Ok(Ty::new_opaque(tcx, a_def_id, args)) + } + + // Alias tend to mostly already be handled downstream due to normalization. + (&ty::Alias(a_kind, a_data), &ty::Alias(b_kind, b_data)) => { + let alias_ty = relation.relate(a_data, b_data)?; + assert_eq!(a_kind, b_kind); + Ok(Ty::new_alias(tcx, a_kind, alias_ty)) } _ => Err(TypeError::Sorts(expected_found(relation, a, b))), @@ -617,13 +617,17 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>( // be stabilized. (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => { assert_eq!(a.ty(), b.ty()); - let substs = relation.relate_with_variance( + let args = relation.relate_with_variance( ty::Variance::Invariant, ty::VarianceDiagInfo::default(), - au.substs, - bu.substs, + au.args, + bu.args, )?; - return Ok(tcx.mk_const(ty::UnevaluatedConst { def: au.def, substs }, a.ty())); + return Ok(ty::Const::new_unevaluated( + tcx, + ty::UnevaluatedConst { def: au.def, args }, + a.ty(), + )); } // Before calling relate on exprs, it is necessary to ensure that the nested consts // have identical types. @@ -635,7 +639,7 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>( // FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to // ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought // of as being generic over the argument types, however this is implicit so these types don't get - // related when we relate the substs of the item this const arg is for. + // related when we relate the args of the item this const arg is for. let expr = match (ae, be) { (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) if a_op == b_op => { r.relate(al.ty(), bl.ty())?; @@ -664,8 +668,7 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>( } _ => return Err(TypeError::ConstMismatch(expected_found(r, a, b))), }; - let kind = ty::ConstKind::Expr(expr); - return Ok(tcx.mk_const(kind, a.ty())); + return Ok(ty::Const::new_expr(tcx, expr, a.ty())); } _ => false, }; @@ -710,35 +713,35 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> { } } -impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> { +impl<'tcx> Relate<'tcx> for ty::ClosureArgs<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: ty::ClosureSubsts<'tcx>, - b: ty::ClosureSubsts<'tcx>, - ) -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>> { - let substs = relate_substs(relation, a.substs, b.substs)?; - Ok(ty::ClosureSubsts { substs }) + a: ty::ClosureArgs<'tcx>, + b: ty::ClosureArgs<'tcx>, + ) -> RelateResult<'tcx, ty::ClosureArgs<'tcx>> { + let args = relate_args(relation, a.args, b.args)?; + Ok(ty::ClosureArgs { args }) } } -impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> { +impl<'tcx> Relate<'tcx> for ty::GeneratorArgs<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: ty::GeneratorSubsts<'tcx>, - b: ty::GeneratorSubsts<'tcx>, - ) -> RelateResult<'tcx, ty::GeneratorSubsts<'tcx>> { - let substs = relate_substs(relation, a.substs, b.substs)?; - Ok(ty::GeneratorSubsts { substs }) + a: ty::GeneratorArgs<'tcx>, + b: ty::GeneratorArgs<'tcx>, + ) -> RelateResult<'tcx, ty::GeneratorArgs<'tcx>> { + let args = relate_args(relation, a.args, b.args)?; + Ok(ty::GeneratorArgs { args }) } } -impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> { +impl<'tcx> Relate<'tcx> for GenericArgsRef<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: SubstsRef<'tcx>, - b: SubstsRef<'tcx>, - ) -> RelateResult<'tcx, SubstsRef<'tcx>> { - relate_substs(relation, a, b) + a: GenericArgsRef<'tcx>, + b: GenericArgsRef<'tcx>, + ) -> RelateResult<'tcx, GenericArgsRef<'tcx>> { + relate_args(relation, a, b) } } diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs index e79b79a25ae..17eabec257e 100644 --- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs +++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs @@ -1,12 +1,12 @@ use crate::middle::region::{Scope, ScopeData, ScopeTree}; -use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; +use rustc_hir::ItemLocalMap; /// `RvalueScopes` is a mapping from sub-expressions to _extended_ lifetime as determined by /// rules laid out in `rustc_hir_analysis::check::rvalue_scopes`. #[derive(TyEncodable, TyDecodable, Clone, Debug, Default, Eq, PartialEq, HashStable)] pub struct RvalueScopes { - map: FxHashMap<hir::ItemLocalId, Option<Scope>>, + map: ItemLocalMap<Option<Scope>>, } impl RvalueScopes { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index a965450d27d..9d380a58d9f 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -11,12 +11,15 @@ use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; use rustc_hir::def::Namespace; use rustc_index::{Idx, IndexVec}; use rustc_target::abi::TyAndLayout; +use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, OptWithInfcx}; -use std::fmt; +use std::fmt::{self, Debug}; use std::ops::ControlFlow; use std::rc::Rc; use std::sync::Arc; +use super::{GenericArg, GenericArgKind, Region}; + impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { @@ -88,7 +91,16 @@ impl fmt::Debug for ty::FreeRegion { impl<'tcx> fmt::Debug for ty::FnSig<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let ty::FnSig { inputs_and_output: _, c_variadic, unsafety, abi } = self; + OptWithInfcx::new_no_ctx(self).fmt(f) + } +} +impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::FnSig<'tcx> { + fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + let sig = this.data; + let ty::FnSig { inputs_and_output: _, c_variadic, unsafety, abi } = sig; write!(f, "{}", unsafety.prefix_str())?; match abi { @@ -97,15 +109,15 @@ impl<'tcx> fmt::Debug for ty::FnSig<'tcx> { }; write!(f, "fn(")?; - let inputs = self.inputs(); + let inputs = sig.inputs(); match inputs.len() { 0 if *c_variadic => write!(f, "...)")?, 0 => write!(f, ")")?, _ => { - for ty in &self.inputs()[0..(self.inputs().len() - 1)] { - write!(f, "{ty:?}, ")?; + for ty in &sig.inputs()[0..(sig.inputs().len() - 1)] { + write!(f, "{:?}, ", &this.wrap(ty))?; } - write!(f, "{:?}", self.inputs().last().unwrap())?; + write!(f, "{:?}", &this.wrap(sig.inputs().last().unwrap()))?; if *c_variadic { write!(f, "...")?; } @@ -113,9 +125,9 @@ impl<'tcx> fmt::Debug for ty::FnSig<'tcx> { } } - match self.output().kind() { + match sig.output().kind() { ty::Tuple(list) if list.is_empty() => Ok(()), - _ => write!(f, " -> {:?}", self.output()), + _ => write!(f, " -> {:?}", &this.wrap(sig.output())), } } } @@ -132,6 +144,14 @@ impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> { } } +impl<'tcx> ty::DebugWithInfcx<TyCtxt<'tcx>> for Ty<'tcx> { + fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + this.data.fmt(f) + } +} impl<'tcx> fmt::Debug for Ty<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { with_no_trimmed_paths!(fmt::Display::fmt(self, f)) @@ -173,12 +193,22 @@ impl<'tcx> fmt::Debug for ty::Predicate<'tcx> { impl<'tcx> fmt::Debug for ty::Clause<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self.kind()) + } +} + +impl<'tcx> fmt::Debug for ty::ClauseKind<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - ty::Clause::ConstArgHasType(ct, ty) => write!(f, "ConstArgHasType({ct:?}, {ty:?})"), - ty::Clause::Trait(ref a) => a.fmt(f), - ty::Clause::RegionOutlives(ref pair) => pair.fmt(f), - ty::Clause::TypeOutlives(ref pair) => pair.fmt(f), - ty::Clause::Projection(ref pair) => pair.fmt(f), + ty::ClauseKind::ConstArgHasType(ct, ty) => write!(f, "ConstArgHasType({ct:?}, {ty:?})"), + ty::ClauseKind::Trait(ref a) => a.fmt(f), + ty::ClauseKind::RegionOutlives(ref pair) => pair.fmt(f), + ty::ClauseKind::TypeOutlives(ref pair) => pair.fmt(f), + ty::ClauseKind::Projection(ref pair) => pair.fmt(f), + ty::ClauseKind::WellFormed(ref data) => write!(f, "WellFormed({:?})", data), + ty::ClauseKind::ConstEvaluatable(ct) => { + write!(f, "ConstEvaluatable({ct:?})") + } } } } @@ -189,20 +219,13 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { ty::PredicateKind::Clause(ref a) => a.fmt(f), ty::PredicateKind::Subtype(ref pair) => pair.fmt(f), ty::PredicateKind::Coerce(ref pair) => pair.fmt(f), - ty::PredicateKind::WellFormed(data) => write!(f, "WellFormed({:?})", data), ty::PredicateKind::ObjectSafe(trait_def_id) => { write!(f, "ObjectSafe({:?})", trait_def_id) } - ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => { - write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind) - } - ty::PredicateKind::ConstEvaluatable(ct) => { - write!(f, "ConstEvaluatable({ct:?})") + ty::PredicateKind::ClosureKind(closure_def_id, closure_args, kind) => { + write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_args, kind) } ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2), - ty::PredicateKind::TypeWellFormedFromEnv(ty) => { - write!(f, "TypeWellFormedFromEnv({:?})", ty) - } ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"), ty::PredicateKind::AliasRelate(t1, t2, dir) => { write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})") @@ -213,9 +236,17 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { impl<'tcx> fmt::Debug for AliasTy<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + OptWithInfcx::new_no_ctx(self).fmt(f) + } +} +impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for AliasTy<'tcx> { + fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { f.debug_struct("AliasTy") - .field("substs", &self.substs) - .field("def_id", &self.def_id) + .field("args", &this.map(|data| data.args)) + .field("def_id", &this.data.def_id) .finish() } } @@ -228,34 +259,96 @@ impl<'tcx> fmt::Debug for ty::InferConst<'tcx> { } } } +impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::InferConst<'tcx> { + fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + use ty::InferConst::*; + match this.infcx.and_then(|infcx| infcx.universe_of_ct(*this.data)) { + None => write!(f, "{:?}", this.data), + Some(universe) => match *this.data { + Var(vid) => write!(f, "?{}_{}c", vid.index, universe.index()), + Fresh(_) => { + unreachable!() + } + }, + } + } +} -impl<'tcx> fmt::Debug for ty::Const<'tcx> { +impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // This reflects what `Const` looked liked before `Interned` was - // introduced. We print it like this to avoid having to update expected - // output in a lot of tests. - write!(f, "Const {{ ty: {:?}, kind: {:?} }}", self.ty(), self.kind()) + OptWithInfcx::new_no_ctx(self).fmt(f) } } +impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::consts::Expr<'tcx> { + fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match this.data { + ty::Expr::Binop(op, lhs, rhs) => { + write!(f, "({op:?}: {:?}, {:?})", &this.wrap(lhs), &this.wrap(rhs)) + } + ty::Expr::UnOp(op, rhs) => write!(f, "({op:?}: {:?})", &this.wrap(rhs)), + ty::Expr::FunctionCall(func, args) => { + write!(f, "{:?}(", &this.wrap(func))?; + for arg in args.as_slice().iter().rev().skip(1).rev() { + write!(f, "{:?}, ", &this.wrap(arg))?; + } + if let Some(arg) = args.last() { + write!(f, "{:?}", &this.wrap(arg))?; + } -impl<'tcx> fmt::Debug for ty::ConstKind<'tcx> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - use ty::ConstKind::*; - match self { - Param(param) => write!(f, "{param:?}"), - Infer(var) => write!(f, "{var:?}"), - Bound(debruijn, var) => rustc_type_ir::debug_bound_var(f, *debruijn, *var), - Placeholder(placeholder) => write!(f, "{placeholder:?}"), - Unevaluated(uv) => { - f.debug_tuple("Unevaluated").field(&uv.substs).field(&uv.def).finish() + write!(f, ")") + } + ty::Expr::Cast(cast_kind, lhs, rhs) => { + write!(f, "({cast_kind:?}: {:?}, {:?})", &this.wrap(lhs), &this.wrap(rhs)) } - Value(valtree) => write!(f, "{valtree:?}"), - Error(_) => write!(f, "{{const error}}"), - Expr(expr) => write!(f, "{expr:?}"), } } } +impl<'tcx> fmt::Debug for ty::UnevaluatedConst<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + OptWithInfcx::new_no_ctx(self).fmt(f) + } +} +impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::UnevaluatedConst<'tcx> { + fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_struct("UnevaluatedConst") + .field("def", &this.data.def) + .field("args", &this.wrap(this.data.args)) + .finish() + } +} + +impl<'tcx> fmt::Debug for ty::Const<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + OptWithInfcx::new_no_ctx(self).fmt(f) + } +} +impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::Const<'tcx> { + fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + // This reflects what `Const` looked liked before `Interned` was + // introduced. We print it like this to avoid having to update expected + // output in a lot of tests. + write!( + f, + "Const {{ ty: {:?}, kind: {:?} }}", + &this.map(|data| data.ty()), + &this.map(|data| data.kind()) + ) + } +} + impl fmt::Debug for ty::BoundTy { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.kind { @@ -275,6 +368,66 @@ impl<T: fmt::Debug> fmt::Debug for ty::Placeholder<T> { } } +impl<'tcx> fmt::Debug for GenericArg<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.unpack() { + GenericArgKind::Lifetime(lt) => lt.fmt(f), + GenericArgKind::Type(ty) => ty.fmt(f), + GenericArgKind::Const(ct) => ct.fmt(f), + } + } +} +impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for GenericArg<'tcx> { + fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match this.data.unpack() { + GenericArgKind::Lifetime(lt) => write!(f, "{:?}", &this.wrap(lt)), + GenericArgKind::Const(ct) => write!(f, "{:?}", &this.wrap(ct)), + GenericArgKind::Type(ty) => write!(f, "{:?}", &this.wrap(ty)), + } + } +} + +impl<'tcx> fmt::Debug for Region<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self.kind()) + } +} +impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for Region<'tcx> { + fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + write!(f, "{:?}", &this.map(|data| data.kind())) + } +} + +impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::RegionVid { + fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match this.infcx.and_then(|infcx| infcx.universe_of_lt(*this.data)) { + Some(universe) => write!(f, "'?{}_{}", this.data.index(), universe.index()), + None => write!(f, "{:?}", this.data), + } + } +} + +impl<'tcx, T: DebugWithInfcx<TyCtxt<'tcx>>> DebugWithInfcx<TyCtxt<'tcx>> for ty::Binder<'tcx, T> { + fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_tuple("Binder") + .field(&this.map(|data| data.as_ref().skip_binder())) + .field(&this.data.bound_vars()) + .finish() + } +} + /////////////////////////////////////////////////////////////////////////// // Atomic structs // @@ -346,7 +499,7 @@ TrivialTypeTraversalAndLiftImpls! { crate::ty::IntVarValue, crate::ty::ParamConst, crate::ty::ParamTy, - crate::ty::adjustment::PointerCast, + crate::ty::adjustment::PointerCoercion, crate::ty::RegionVid, crate::ty::UniverseIndex, crate::ty::Variance, @@ -542,26 +695,26 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for Ty<'tcx> { ty::RawPtr(tm) => ty::RawPtr(tm.try_fold_with(folder)?), ty::Array(typ, sz) => ty::Array(typ.try_fold_with(folder)?, sz.try_fold_with(folder)?), ty::Slice(typ) => ty::Slice(typ.try_fold_with(folder)?), - ty::Adt(tid, substs) => ty::Adt(tid, substs.try_fold_with(folder)?), + ty::Adt(tid, args) => ty::Adt(tid, args.try_fold_with(folder)?), ty::Dynamic(trait_ty, region, representation) => ty::Dynamic( trait_ty.try_fold_with(folder)?, region.try_fold_with(folder)?, representation, ), ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?), - ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.try_fold_with(folder)?), + ty::FnDef(def_id, args) => ty::FnDef(def_id, args.try_fold_with(folder)?), ty::FnPtr(f) => ty::FnPtr(f.try_fold_with(folder)?), ty::Ref(r, ty, mutbl) => { ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl) } - ty::Generator(did, substs, movability) => { - ty::Generator(did, substs.try_fold_with(folder)?, movability) + ty::Generator(did, args, movability) => { + ty::Generator(did, args.try_fold_with(folder)?, movability) } ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?), - ty::GeneratorWitnessMIR(did, substs) => { - ty::GeneratorWitnessMIR(did, substs.try_fold_with(folder)?) + ty::GeneratorWitnessMIR(did, args) => { + ty::GeneratorWitnessMIR(did, args.try_fold_with(folder)?) } - ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?), + ty::Closure(did, args) => ty::Closure(did, args.try_fold_with(folder)?), ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?), ty::Bool @@ -595,22 +748,22 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> { sz.visit_with(visitor) } ty::Slice(typ) => typ.visit_with(visitor), - ty::Adt(_, substs) => substs.visit_with(visitor), + ty::Adt(_, args) => args.visit_with(visitor), ty::Dynamic(ref trait_ty, ref reg, _) => { trait_ty.visit_with(visitor)?; reg.visit_with(visitor) } ty::Tuple(ts) => ts.visit_with(visitor), - ty::FnDef(_, substs) => substs.visit_with(visitor), + ty::FnDef(_, args) => args.visit_with(visitor), ty::FnPtr(ref f) => f.visit_with(visitor), ty::Ref(r, ty, _) => { r.visit_with(visitor)?; ty.visit_with(visitor) } - ty::Generator(_did, ref substs, _) => substs.visit_with(visitor), + ty::Generator(_did, ref args, _) => args.visit_with(visitor), ty::GeneratorWitness(ref types) => types.visit_with(visitor), - ty::GeneratorWitnessMIR(_did, ref substs) => substs.visit_with(visitor), - ty::Closure(_did, ref substs) => substs.visit_with(visitor), + ty::GeneratorWitnessMIR(_did, ref args) => args.visit_with(visitor), + ty::Closure(_did, ref args) => args.visit_with(visitor), ty::Alias(_, ref data) => data.visit_with(visitor), ty::Bool @@ -654,12 +807,28 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> { } } +// FIXME(clause): This is wonky +impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Clause<'tcx> { + fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( + self, + folder: &mut F, + ) -> Result<Self, F::Error> { + Ok(folder.try_fold_predicate(self.as_predicate())?.expect_clause()) + } +} + impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> { fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { visitor.visit_predicate(*self) } } +impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Clause<'tcx> { + fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { + visitor.visit_predicate(self.as_predicate()) + } +} + impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> { fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( self, @@ -679,12 +848,12 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> { } } -impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Predicate<'tcx>> { +impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Clause<'tcx>> { fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( self, folder: &mut F, ) -> Result<Self, F::Error> { - ty::util::fold_list(self, folder, |tcx, v| tcx.mk_predicates(v)) + ty::util::fold_list(self, folder, |tcx, v| tcx.mk_clauses(v)) } } @@ -709,9 +878,20 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> { folder: &mut F, ) -> Result<Self, F::Error> { let ty = self.ty().try_fold_with(folder)?; - let kind = self.kind().try_fold_with(folder)?; + let kind = match self.kind() { + ConstKind::Param(p) => ConstKind::Param(p.try_fold_with(folder)?), + ConstKind::Infer(i) => ConstKind::Infer(i.try_fold_with(folder)?), + ConstKind::Bound(d, b) => { + ConstKind::Bound(d.try_fold_with(folder)?, b.try_fold_with(folder)?) + } + ConstKind::Placeholder(p) => ConstKind::Placeholder(p.try_fold_with(folder)?), + ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?), + ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?), + ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?), + ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?), + }; if ty != self.ty() || kind != self.kind() { - Ok(folder.interner().mk_const(kind, ty)) + Ok(folder.interner().mk_ct_from_kind(kind, ty)) } else { Ok(self) } @@ -724,7 +904,19 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> { visitor: &mut V, ) -> ControlFlow<V::BreakTy> { self.ty().visit_with(visitor)?; - self.kind().visit_with(visitor) + match self.kind() { + ConstKind::Param(p) => p.visit_with(visitor), + ConstKind::Infer(i) => i.visit_with(visitor), + ConstKind::Bound(d, b) => { + d.visit_with(visitor)?; + b.visit_with(visitor) + } + ConstKind::Placeholder(p) => p.visit_with(visitor), + ConstKind::Unevaluated(uv) => uv.visit_with(visitor), + ConstKind::Value(v) => v.visit_with(visitor), + ConstKind::Error(e) => e.visit_with(visitor), + ConstKind::Expr(e) => e.visit_with(visitor), + } } } @@ -751,7 +943,7 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::UnevaluatedConst<'tcx> { &self, visitor: &mut V, ) -> ControlFlow<V::BreakTy> { - self.substs.visit_with(visitor) + self.args.visit_with(visitor) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index d19a7bcde79..f9c1ca9a8b1 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -3,13 +3,13 @@ #![allow(rustc::usage_of_ty_tykind)] use crate::infer::canonical::Canonical; -use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use crate::ty::visit::ValidateBoundVars; use crate::ty::InferTy::*; use crate::ty::{ self, AdtDef, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; +use crate::ty::{GenericArg, GenericArgs, GenericArgsRef}; use crate::ty::{List, ParamEnv}; use hir::def::DefKind; use polonius_engine::Atom; @@ -25,6 +25,7 @@ use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use rustc_target::spec::abi::{self, Abi}; +use std::assert_matches::debug_assert_matches; use std::borrow::Cow; use std::cmp::Ordering; use std::fmt; @@ -33,13 +34,20 @@ use std::ops::{ControlFlow, Deref, Range}; use ty::util::IntTypeExt; use rustc_type_ir::sty::TyKind::*; +use rustc_type_ir::CollectAndApply; +use rustc_type_ir::ConstKind as IrConstKind; +use rustc_type_ir::DebugWithInfcx; +use rustc_type_ir::DynKind; use rustc_type_ir::RegionKind as IrRegionKind; use rustc_type_ir::TyKind as IrTyKind; +use super::GenericParamDefKind; + // Re-export the `TyKind` from `rustc_type_ir` here for convenience #[rustc_diagnostic_item = "TyKind"] pub type TyKind<'tcx> = IrTyKind<TyCtxt<'tcx>>; pub type RegionKind<'tcx> = IrRegionKind<TyCtxt<'tcx>>; +pub type ConstKind<'tcx> = IrConstKind<TyCtxt<'tcx>>; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] @@ -209,7 +217,7 @@ impl<'tcx> Article for TyKind<'tcx> { /// /// ## Generators /// -/// Generators are handled similarly in `GeneratorSubsts`. The set of +/// Generators are handled similarly in `GeneratorArgs`. The set of /// type parameters is similar, but `CK` and `CS` are replaced by the /// following type parameters: /// @@ -222,33 +230,30 @@ impl<'tcx> Article for TyKind<'tcx> { /// completion of the generator. /// * `GW`: The "generator witness". #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)] -pub struct ClosureSubsts<'tcx> { +pub struct ClosureArgs<'tcx> { /// Lifetime and type parameters from the enclosing function, /// concatenated with a tuple containing the types of the upvars. /// /// These are separated out because codegen wants to pass them around /// when monomorphizing. - pub substs: SubstsRef<'tcx>, + pub args: GenericArgsRef<'tcx>, } /// Struct returned by `split()`. -pub struct ClosureSubstsParts<'tcx, T> { - pub parent_substs: &'tcx [GenericArg<'tcx>], +pub struct ClosureArgsParts<'tcx, T> { + pub parent_args: &'tcx [GenericArg<'tcx>], pub closure_kind_ty: T, pub closure_sig_as_fn_ptr_ty: T, pub tupled_upvars_ty: T, } -impl<'tcx> ClosureSubsts<'tcx> { - /// Construct `ClosureSubsts` from `ClosureSubstsParts`, containing `Substs` +impl<'tcx> ClosureArgs<'tcx> { + /// Construct `ClosureArgs` from `ClosureArgsParts`, containing `Args` /// for the closure parent, alongside additional closure-specific components. - pub fn new( - tcx: TyCtxt<'tcx>, - parts: ClosureSubstsParts<'tcx, Ty<'tcx>>, - ) -> ClosureSubsts<'tcx> { - ClosureSubsts { - substs: tcx.mk_substs_from_iter( - parts.parent_substs.iter().copied().chain( + pub fn new(tcx: TyCtxt<'tcx>, parts: ClosureArgsParts<'tcx, Ty<'tcx>>) -> ClosureArgs<'tcx> { + ClosureArgs { + args: tcx.mk_args_from_iter( + parts.parent_args.iter().copied().chain( [parts.closure_kind_ty, parts.closure_sig_as_fn_ptr_ty, parts.tupled_upvars_ty] .iter() .map(|&ty| ty.into()), @@ -257,38 +262,34 @@ impl<'tcx> ClosureSubsts<'tcx> { } } - /// Divides the closure substs into their respective components. - /// The ordering assumed here must match that used by `ClosureSubsts::new` above. - fn split(self) -> ClosureSubstsParts<'tcx, GenericArg<'tcx>> { - match self.substs[..] { - [ - ref parent_substs @ .., - closure_kind_ty, - closure_sig_as_fn_ptr_ty, - tupled_upvars_ty, - ] => ClosureSubstsParts { - parent_substs, - closure_kind_ty, - closure_sig_as_fn_ptr_ty, - tupled_upvars_ty, - }, - _ => bug!("closure substs missing synthetics"), + /// Divides the closure args into their respective components. + /// The ordering assumed here must match that used by `ClosureArgs::new` above. + fn split(self) -> ClosureArgsParts<'tcx, GenericArg<'tcx>> { + match self.args[..] { + [ref parent_args @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => { + ClosureArgsParts { + parent_args, + closure_kind_ty, + closure_sig_as_fn_ptr_ty, + tupled_upvars_ty, + } + } + _ => bug!("closure args missing synthetics"), } } /// Returns `true` only if enough of the synthetic types are known to - /// allow using all of the methods on `ClosureSubsts` without panicking. + /// allow using all of the methods on `ClosureArgs` without panicking. /// /// Used primarily by `ty::print::pretty` to be able to handle closure /// types that haven't had their synthetic types substituted in. pub fn is_valid(self) -> bool { - self.substs.len() >= 3 - && matches!(self.split().tupled_upvars_ty.expect_ty().kind(), Tuple(_)) + self.args.len() >= 3 && matches!(self.split().tupled_upvars_ty.expect_ty().kind(), Tuple(_)) } /// Returns the substitutions of the closure's parent. - pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] { - self.split().parent_substs + pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] { + self.split().parent_args } /// Returns an iterator over the list of types of captured paths by the closure. @@ -314,7 +315,7 @@ impl<'tcx> ClosureSubsts<'tcx> { /// Returns the closure kind for this closure; may return a type /// variable during inference. To get the closure kind during - /// inference, use `infcx.closure_kind(substs)`. + /// inference, use `infcx.closure_kind(args)`. pub fn kind_ty(self) -> Ty<'tcx> { self.split().closure_kind_ty.expect_ty() } @@ -322,7 +323,7 @@ impl<'tcx> ClosureSubsts<'tcx> { /// Returns the `fn` pointer type representing the closure signature for this /// closure. // FIXME(eddyb) this should be unnecessary, as the shallowly resolved - // type is known at the time of the creation of `ClosureSubsts`, + // type is known at the time of the creation of `ClosureArgs`, // see `rustc_hir_analysis::check::closure`. pub fn sig_as_fn_ptr_ty(self) -> Ty<'tcx> { self.split().closure_sig_as_fn_ptr_ty.expect_ty() @@ -351,14 +352,14 @@ impl<'tcx> ClosureSubsts<'tcx> { } } -/// Similar to `ClosureSubsts`; see the above documentation for more. +/// Similar to `ClosureArgs`; see the above documentation for more. #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)] -pub struct GeneratorSubsts<'tcx> { - pub substs: SubstsRef<'tcx>, +pub struct GeneratorArgs<'tcx> { + pub args: GenericArgsRef<'tcx>, } -pub struct GeneratorSubstsParts<'tcx, T> { - pub parent_substs: &'tcx [GenericArg<'tcx>], +pub struct GeneratorArgsParts<'tcx, T> { + pub parent_args: &'tcx [GenericArg<'tcx>], pub resume_ty: T, pub yield_ty: T, pub return_ty: T, @@ -366,16 +367,16 @@ pub struct GeneratorSubstsParts<'tcx, T> { pub tupled_upvars_ty: T, } -impl<'tcx> GeneratorSubsts<'tcx> { - /// Construct `GeneratorSubsts` from `GeneratorSubstsParts`, containing `Substs` +impl<'tcx> GeneratorArgs<'tcx> { + /// Construct `GeneratorArgs` from `GeneratorArgsParts`, containing `Args` /// for the generator parent, alongside additional generator-specific components. pub fn new( tcx: TyCtxt<'tcx>, - parts: GeneratorSubstsParts<'tcx, Ty<'tcx>>, - ) -> GeneratorSubsts<'tcx> { - GeneratorSubsts { - substs: tcx.mk_substs_from_iter( - parts.parent_substs.iter().copied().chain( + parts: GeneratorArgsParts<'tcx, Ty<'tcx>>, + ) -> GeneratorArgs<'tcx> { + GeneratorArgs { + args: tcx.mk_args_from_iter( + parts.parent_args.iter().copied().chain( [ parts.resume_ty, parts.yield_ty, @@ -390,13 +391,13 @@ impl<'tcx> GeneratorSubsts<'tcx> { } } - /// Divides the generator substs into their respective components. - /// The ordering assumed here must match that used by `GeneratorSubsts::new` above. - fn split(self) -> GeneratorSubstsParts<'tcx, GenericArg<'tcx>> { - match self.substs[..] { - [ref parent_substs @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => { - GeneratorSubstsParts { - parent_substs, + /// Divides the generator args into their respective components. + /// The ordering assumed here must match that used by `GeneratorArgs::new` above. + fn split(self) -> GeneratorArgsParts<'tcx, GenericArg<'tcx>> { + match self.args[..] { + [ref parent_args @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => { + GeneratorArgsParts { + parent_args, resume_ty, yield_ty, return_ty, @@ -404,23 +405,22 @@ impl<'tcx> GeneratorSubsts<'tcx> { tupled_upvars_ty, } } - _ => bug!("generator substs missing synthetics"), + _ => bug!("generator args missing synthetics"), } } /// Returns `true` only if enough of the synthetic types are known to - /// allow using all of the methods on `GeneratorSubsts` without panicking. + /// allow using all of the methods on `GeneratorArgs` without panicking. /// /// Used primarily by `ty::print::pretty` to be able to handle generator /// types that haven't had their synthetic types substituted in. pub fn is_valid(self) -> bool { - self.substs.len() >= 5 - && matches!(self.split().tupled_upvars_ty.expect_ty().kind(), Tuple(_)) + self.args.len() >= 5 && matches!(self.split().tupled_upvars_ty.expect_ty().kind(), Tuple(_)) } /// Returns the substitutions of the generator's parent. - pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] { - self.split().parent_substs + pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] { + self.split().parent_args } /// This describes the types that can be contained in a generator. @@ -489,7 +489,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { } } -impl<'tcx> GeneratorSubsts<'tcx> { +impl<'tcx> GeneratorArgs<'tcx> { /// Generator has not been resumed yet. pub const UNRESUMED: usize = 0; /// Generator has returned or is completed. @@ -568,7 +568,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { let layout = tcx.generator_layout(def_id).unwrap(); layout.variant_fields.iter().map(move |variant| { variant.iter().map(move |field| { - ty::EarlyBinder::bind(layout.field_tys[*field].ty).subst(tcx, self.substs) + ty::EarlyBinder::bind(layout.field_tys[*field].ty).instantiate(tcx, self.args) }) }) } @@ -582,20 +582,20 @@ impl<'tcx> GeneratorSubsts<'tcx> { } #[derive(Debug, Copy, Clone, HashStable)] -pub enum UpvarSubsts<'tcx> { - Closure(SubstsRef<'tcx>), - Generator(SubstsRef<'tcx>), +pub enum UpvarArgs<'tcx> { + Closure(GenericArgsRef<'tcx>), + Generator(GenericArgsRef<'tcx>), } -impl<'tcx> UpvarSubsts<'tcx> { +impl<'tcx> UpvarArgs<'tcx> { /// Returns an iterator over the list of types of captured paths by the closure/generator. /// In case there was a type error in figuring out the types of the captured path, an /// empty iterator is returned. #[inline] pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx { let tupled_tys = match self { - UpvarSubsts::Closure(substs) => substs.as_closure().tupled_upvars_ty(), - UpvarSubsts::Generator(substs) => substs.as_generator().tupled_upvars_ty(), + UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(), + UpvarArgs::Generator(args) => args.as_generator().tupled_upvars_ty(), }; match tupled_tys.kind() { @@ -611,8 +611,8 @@ impl<'tcx> UpvarSubsts<'tcx> { #[inline] pub fn tupled_upvars_ty(self) -> Ty<'tcx> { match self { - UpvarSubsts::Closure(substs) => substs.as_closure().tupled_upvars_ty(), - UpvarSubsts::Generator(substs) => substs.as_generator().tupled_upvars_ty(), + UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(), + UpvarArgs::Generator(args) => args.as_generator().tupled_upvars_ty(), } } } @@ -629,46 +629,46 @@ impl<'tcx> UpvarSubsts<'tcx> { /// /// When the inline const is instantiated, `R` is substituted as the actual inferred /// type of the constant. The reason that `R` is represented as an extra type parameter -/// is the same reason that [`ClosureSubsts`] have `CS` and `U` as type parameters: +/// is the same reason that [`ClosureArgs`] have `CS` and `U` as type parameters: /// inline const can reference lifetimes that are internal to the creating function. #[derive(Copy, Clone, Debug)] -pub struct InlineConstSubsts<'tcx> { +pub struct InlineConstArgs<'tcx> { /// Generic parameters from the enclosing item, /// concatenated with the inferred type of the constant. - pub substs: SubstsRef<'tcx>, + pub args: GenericArgsRef<'tcx>, } /// Struct returned by `split()`. -pub struct InlineConstSubstsParts<'tcx, T> { - pub parent_substs: &'tcx [GenericArg<'tcx>], +pub struct InlineConstArgsParts<'tcx, T> { + pub parent_args: &'tcx [GenericArg<'tcx>], pub ty: T, } -impl<'tcx> InlineConstSubsts<'tcx> { - /// Construct `InlineConstSubsts` from `InlineConstSubstsParts`. +impl<'tcx> InlineConstArgs<'tcx> { + /// Construct `InlineConstArgs` from `InlineConstArgsParts`. pub fn new( tcx: TyCtxt<'tcx>, - parts: InlineConstSubstsParts<'tcx, Ty<'tcx>>, - ) -> InlineConstSubsts<'tcx> { - InlineConstSubsts { - substs: tcx.mk_substs_from_iter( - parts.parent_substs.iter().copied().chain(std::iter::once(parts.ty.into())), + parts: InlineConstArgsParts<'tcx, Ty<'tcx>>, + ) -> InlineConstArgs<'tcx> { + InlineConstArgs { + args: tcx.mk_args_from_iter( + parts.parent_args.iter().copied().chain(std::iter::once(parts.ty.into())), ), } } - /// Divides the inline const substs into their respective components. - /// The ordering assumed here must match that used by `InlineConstSubsts::new` above. - fn split(self) -> InlineConstSubstsParts<'tcx, GenericArg<'tcx>> { - match self.substs[..] { - [ref parent_substs @ .., ty] => InlineConstSubstsParts { parent_substs, ty }, - _ => bug!("inline const substs missing synthetics"), + /// Divides the inline const args into their respective components. + /// The ordering assumed here must match that used by `InlineConstArgs::new` above. + fn split(self) -> InlineConstArgsParts<'tcx, GenericArg<'tcx>> { + match self.args[..] { + [ref parent_args @ .., ty] => InlineConstArgsParts { parent_args, ty }, + _ => bug!("inline const args missing synthetics"), } } /// Returns the substitutions of the inline const's parent. - pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] { - self.split().parent_substs + pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] { + self.split().parent_args } /// Returns the type of this inline const. @@ -688,6 +688,15 @@ pub enum ExistentialPredicate<'tcx> { AutoTrait(DefId), } +impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ExistentialPredicate<'tcx> { + fn fmt<InfCtx: rustc_type_ir::InferCtxtLike<TyCtxt<'tcx>>>( + this: rustc_type_ir::OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + fmt::Debug::fmt(&this.data, f) + } +} + impl<'tcx> ExistentialPredicate<'tcx> { /// Compares via an ordering that will not change if modules are reordered or other changes are /// made to the tree. In particular, this ordering is preserved across incremental compilations. @@ -715,7 +724,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> { /// Given an existential predicate like `?Self: PartialEq<u32>` (e.g., derived from `dyn PartialEq<u32>`), /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self` /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq<u32>`, in our example). - pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> { + pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Clause<'tcx> { use crate::ty::ToPredicate; match self.skip_binder() { ExistentialPredicate::Trait(tr) => { @@ -730,10 +739,9 @@ impl<'tcx> PolyExistentialPredicate<'tcx> { ty::TraitRef::new(tcx, did, [self_ty]) } else { // If this is an ill-formed auto trait, then synthesize - // new error substs for the missing generics. - let err_substs = - ty::InternalSubsts::extend_with_error(tcx, did, &[self_ty.into()]); - ty::TraitRef::new(tcx, did, err_substs) + // new error args for the missing generics. + let err_args = ty::GenericArgs::extend_with_error(tcx, did, &[self_ty.into()]); + ty::TraitRef::new(tcx, did, err_args) }; self.rebind(trait_ref).without_const().to_predicate(tcx) } @@ -809,7 +817,7 @@ impl<'tcx> List<ty::PolyExistentialPredicate<'tcx>> { /// T: Foo<U> /// ``` /// This would be represented by a trait-reference where the `DefId` is the -/// `DefId` for the trait `Foo` and the substs define `T` as parameter 0, +/// `DefId` for the trait `Foo` and the args define `T` as parameter 0, /// and `U` as parameter 1. /// /// Trait references also appear in object types like `Foo<U>`, but in @@ -818,7 +826,7 @@ impl<'tcx> List<ty::PolyExistentialPredicate<'tcx>> { #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct TraitRef<'tcx> { pub def_id: DefId, - pub substs: SubstsRef<'tcx>, + pub args: GenericArgsRef<'tcx>, /// This field exists to prevent the creation of `TraitRef` without /// calling [`TraitRef::new`]. pub(super) _use_trait_ref_new_instead: (), @@ -828,42 +836,42 @@ impl<'tcx> TraitRef<'tcx> { pub fn new( tcx: TyCtxt<'tcx>, trait_def_id: DefId, - substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, + args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, ) -> Self { - let substs = tcx.check_and_mk_substs(trait_def_id, substs); - Self { def_id: trait_def_id, substs, _use_trait_ref_new_instead: () } + let args = tcx.check_and_mk_args(trait_def_id, args); + Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () } } pub fn from_lang_item( tcx: TyCtxt<'tcx>, trait_lang_item: LangItem, span: Span, - substs: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>, + args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>, ) -> Self { let trait_def_id = tcx.require_lang_item(trait_lang_item, Some(span)); - Self::new(tcx, trait_def_id, substs) + Self::new(tcx, trait_def_id, args) } pub fn from_method( tcx: TyCtxt<'tcx>, trait_id: DefId, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, ) -> ty::TraitRef<'tcx> { let defs = tcx.generics_of(trait_id); - ty::TraitRef::new(tcx, trait_id, tcx.mk_substs(&substs[..defs.params.len()])) + ty::TraitRef::new(tcx, trait_id, tcx.mk_args(&args[..defs.params.len()])) } /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi` /// are the parameters defined on trait. pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> TraitRef<'tcx> { - ty::TraitRef::new(tcx, def_id, InternalSubsts::identity_for_item(tcx, def_id)) + ty::TraitRef::new(tcx, def_id, GenericArgs::identity_for_item(tcx, def_id)) } pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { ty::TraitRef::new( tcx, self.def_id, - [self_ty.into()].into_iter().chain(self.substs.iter().skip(1)), + [self_ty.into()].into_iter().chain(self.args.iter().skip(1)), ) } @@ -881,7 +889,7 @@ impl<'tcx> TraitRef<'tcx> { #[inline] pub fn self_ty(&self) -> Ty<'tcx> { - self.substs.type_at(0) + self.args.type_at(0) } } @@ -914,7 +922,7 @@ impl<'tcx> IntoDiagnosticArg for TraitRef<'tcx> { #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct ExistentialTraitRef<'tcx> { pub def_id: DefId, - pub substs: SubstsRef<'tcx>, + pub args: GenericArgsRef<'tcx>, } impl<'tcx> ExistentialTraitRef<'tcx> { @@ -923,11 +931,11 @@ impl<'tcx> ExistentialTraitRef<'tcx> { trait_ref: ty::TraitRef<'tcx>, ) -> ty::ExistentialTraitRef<'tcx> { // Assert there is a Self. - trait_ref.substs.type_at(0); + trait_ref.args.type_at(0); ty::ExistentialTraitRef { def_id: trait_ref.def_id, - substs: tcx.mk_substs(&trait_ref.substs[1..]), + args: tcx.mk_args(&trait_ref.args[1..]), } } @@ -939,7 +947,7 @@ impl<'tcx> ExistentialTraitRef<'tcx> { // otherwise the escaping vars would be captured by the binder // debug_assert!(!self_ty.has_escaping_bound_vars()); - ty::TraitRef::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter())) + ty::TraitRef::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter())) } } @@ -1007,7 +1015,10 @@ impl BoundVariableKind { /// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(HashStable, Lift)] -pub struct Binder<'tcx, T>(T, &'tcx List<BoundVariableKind>); +pub struct Binder<'tcx, T> { + value: T, + bound_vars: &'tcx List<BoundVariableKind>, +} impl<'tcx, T> Binder<'tcx, T> where @@ -1023,15 +1034,15 @@ where !value.has_escaping_bound_vars(), "`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder." ); - Binder(value, ty::List::empty()) + Binder { value, bound_vars: ty::List::empty() } } - pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> { + pub fn bind_with_vars(value: T, bound_vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> { if cfg!(debug_assertions) { - let mut validator = ValidateBoundVars::new(vars); + let mut validator = ValidateBoundVars::new(bound_vars); value.visit_with(&mut validator); } - Binder(value, vars) + Binder { value, bound_vars } } } @@ -1053,30 +1064,30 @@ impl<'tcx, T> Binder<'tcx, T> { /// - comparing the self type of a PolyTraitRef to see if it is equal to /// a type parameter `X`, since the type `X` does not reference any regions pub fn skip_binder(self) -> T { - self.0 + self.value } pub fn bound_vars(&self) -> &'tcx List<BoundVariableKind> { - self.1 + self.bound_vars } pub fn as_ref(&self) -> Binder<'tcx, &T> { - Binder(&self.0, self.1) + Binder { value: &self.value, bound_vars: self.bound_vars } } pub fn as_deref(&self) -> Binder<'tcx, &T::Target> where T: Deref, { - Binder(&self.0, self.1) + Binder { value: &self.value, bound_vars: self.bound_vars } } pub fn map_bound_ref_unchecked<F, U>(&self, f: F) -> Binder<'tcx, U> where F: FnOnce(&T) -> U, { - let value = f(&self.0); - Binder(value, self.1) + let value = f(&self.value); + Binder { value, bound_vars: self.bound_vars } } pub fn map_bound_ref<F, U: TypeVisitable<TyCtxt<'tcx>>>(&self, f: F) -> Binder<'tcx, U> @@ -1090,12 +1101,13 @@ impl<'tcx, T> Binder<'tcx, T> { where F: FnOnce(T) -> U, { - let value = f(self.0); + let Binder { value, bound_vars } = self; + let value = f(value); if cfg!(debug_assertions) { - let mut validator = ValidateBoundVars::new(self.1); + let mut validator = ValidateBoundVars::new(bound_vars); value.visit_with(&mut validator); } - Binder(value, self.1) + Binder { value, bound_vars } } pub fn try_map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>, E>( @@ -1105,12 +1117,13 @@ impl<'tcx, T> Binder<'tcx, T> { where F: FnOnce(T) -> Result<U, E>, { - let value = f(self.0)?; + let Binder { value, bound_vars } = self; + let value = f(value)?; if cfg!(debug_assertions) { - let mut validator = ValidateBoundVars::new(self.1); + let mut validator = ValidateBoundVars::new(bound_vars); value.visit_with(&mut validator); } - Ok(Binder(value, self.1)) + Ok(Binder { value, bound_vars }) } /// Wraps a `value` in a binder, using the same bound variables as the @@ -1126,11 +1139,7 @@ impl<'tcx, T> Binder<'tcx, T> { where U: TypeVisitable<TyCtxt<'tcx>>, { - if cfg!(debug_assertions) { - let mut validator = ValidateBoundVars::new(self.bound_vars()); - value.visit_with(&mut validator); - } - Binder(value, self.1) + Binder::bind_with_vars(value, self.bound_vars) } /// Unwraps and returns the value within, but only if it contains @@ -1147,7 +1156,7 @@ impl<'tcx, T> Binder<'tcx, T> { where T: TypeVisitable<TyCtxt<'tcx>>, { - if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } + if self.value.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } } /// Splits the contents into two things that share the same binder @@ -1160,22 +1169,23 @@ impl<'tcx, T> Binder<'tcx, T> { where F: FnOnce(T) -> (U, V), { - let (u, v) = f(self.0); - (Binder(u, self.1), Binder(v, self.1)) + let Binder { value, bound_vars } = self; + let (u, v) = f(value); + (Binder { value: u, bound_vars }, Binder { value: v, bound_vars }) } } impl<'tcx, T> Binder<'tcx, Option<T>> { pub fn transpose(self) -> Option<Binder<'tcx, T>> { - let bound_vars = self.1; - self.0.map(|v| Binder(v, bound_vars)) + let Binder { value, bound_vars } = self; + value.map(|value| Binder { value, bound_vars }) } } impl<'tcx, T: IntoIterator> Binder<'tcx, T> { pub fn iter(self) -> impl Iterator<Item = ty::Binder<'tcx, T::Item>> { - let bound_vars = self.1; - self.0.into_iter().map(|v| Binder(v, bound_vars)) + let Binder { value, bound_vars } = self; + value.into_iter().map(|value| Binder { value, bound_vars }) } } @@ -1184,7 +1194,7 @@ where T: IntoDiagnosticArg, { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { - self.0.into_diagnostic_arg() + self.value.into_diagnostic_arg() } } @@ -1206,7 +1216,7 @@ pub struct AliasTy<'tcx> { /// /// For RPIT the substitutions are for the generics of the function, /// while for TAIT it is used for the generic parameters of the alias. - pub substs: SubstsRef<'tcx>, + pub args: GenericArgsRef<'tcx>, /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if @@ -1229,25 +1239,26 @@ impl<'tcx> AliasTy<'tcx> { pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind { match tcx.def_kind(self.def_id) { DefKind::AssocTy if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) => ty::Inherent, - DefKind::AssocTy | DefKind::ImplTraitPlaceholder => ty::Projection, + DefKind::AssocTy => ty::Projection, DefKind::OpaqueTy => ty::Opaque, + DefKind::TyAlias => ty::Weak, kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), } } pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - tcx.mk_alias(self.kind(tcx), self) + Ty::new_alias(tcx, self.kind(tcx), self) } } /// The following methods work only with associated type projections. impl<'tcx> AliasTy<'tcx> { pub fn self_ty(self) -> Ty<'tcx> { - self.substs.type_at(0) + self.args.type_at(0) } pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { - tcx.mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter().skip(1))) + tcx.mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.args.iter().skip(1))) } } @@ -1256,17 +1267,14 @@ impl<'tcx> AliasTy<'tcx> { pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { match tcx.def_kind(self.def_id) { DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id), - DefKind::ImplTraitPlaceholder => { - tcx.parent(tcx.impl_trait_in_trait_parent_fn(self.def_id)) - } kind => bug!("expected a projection AliasTy; found {kind:?}"), } } - /// Extracts the underlying trait reference and own substs from this projection. + /// Extracts the underlying trait reference and own args from this projection. /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`, - /// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own substs - pub fn trait_ref_and_own_substs( + /// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own args + pub fn trait_ref_and_own_args( self, tcx: TyCtxt<'tcx>, ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) { @@ -1274,8 +1282,8 @@ impl<'tcx> AliasTy<'tcx> { let trait_def_id = self.trait_def_id(tcx); let trait_generics = tcx.generics_of(trait_def_id); ( - ty::TraitRef::new(tcx, trait_def_id, self.substs.truncate_to(tcx, trait_generics)), - &self.substs[trait_generics.count()..], + ty::TraitRef::new(tcx, trait_def_id, self.args.truncate_to(tcx, trait_generics)), + &self.args[trait_generics.count()..], ) } @@ -1283,18 +1291,18 @@ impl<'tcx> AliasTy<'tcx> { /// For example, if this is a projection of `<T as Iterator>::Item`, /// then this function would return a `T: Iterator` trait reference. /// - /// WARNING: This will drop the substs for generic associated types - /// consider calling [Self::trait_ref_and_own_substs] to get those + /// WARNING: This will drop the args for generic associated types + /// consider calling [Self::trait_ref_and_own_args] to get those /// as well. pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> { let def_id = self.trait_def_id(tcx); - ty::TraitRef::new(tcx, def_id, self.substs.truncate_to(tcx, tcx.generics_of(def_id))) + ty::TraitRef::new(tcx, def_id, self.args.truncate_to(tcx, tcx.generics_of(def_id))) } } /// The following methods work only with inherent associated type projections. impl<'tcx> AliasTy<'tcx> { - /// Transform the substitutions to have the given `impl` substs as the base and the GAT substs on top of that. + /// Transform the substitutions to have the given `impl` args as the base and the GAT args on top of that. /// /// Does the following transformation: /// @@ -1304,14 +1312,14 @@ impl<'tcx> AliasTy<'tcx> { /// I_i impl subst /// P_j GAT subst /// ``` - pub fn rebase_substs_onto_impl( + pub fn rebase_inherent_args_onto_impl( self, - impl_substs: ty::SubstsRef<'tcx>, + impl_args: ty::GenericArgsRef<'tcx>, tcx: TyCtxt<'tcx>, - ) -> ty::SubstsRef<'tcx> { + ) -> ty::GenericArgsRef<'tcx> { debug_assert_eq!(self.kind(tcx), ty::Inherent); - tcx.mk_substs_from_iter(impl_substs.into_iter().chain(self.substs.into_iter().skip(1))) + tcx.mk_args_from_iter(impl_args.into_iter().chain(self.args.into_iter().skip(1))) } } @@ -1427,7 +1435,7 @@ impl<'tcx> ParamTy { #[inline] pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - tcx.mk_ty_param(self.index, self.name) + Ty::new_param(tcx, self.index, self.name) } pub fn span_from_generics(&self, tcx: TyCtxt<'tcx>, item_with_generics: DefId) -> Span { @@ -1565,12 +1573,6 @@ impl<'tcx> Deref for Region<'tcx> { } } -impl<'tcx> fmt::Debug for Region<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:?}", self.kind()) - } -} - #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)] #[derive(HashStable)] pub struct EarlyBoundRegion { @@ -1581,7 +1583,7 @@ pub struct EarlyBoundRegion { impl fmt::Debug for EarlyBoundRegion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}, {}", self.index, self.name) + write!(f, "{:?}, {}, {}", self.def_id, self.index, self.name) } } @@ -1637,7 +1639,7 @@ impl From<BoundVar> for BoundTy { #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct ExistentialProjection<'tcx> { pub def_id: DefId, - pub substs: SubstsRef<'tcx>, + pub args: GenericArgsRef<'tcx>, pub term: Term<'tcx>, } @@ -1651,8 +1653,8 @@ impl<'tcx> ExistentialProjection<'tcx> { pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> { let def_id = tcx.parent(self.def_id); let subst_count = tcx.generics_of(def_id).count() - 1; - let substs = tcx.mk_substs(&self.substs[..subst_count]); - ty::ExistentialTraitRef { def_id, substs } + let args = tcx.mk_args(&self.args[..subst_count]); + ty::ExistentialTraitRef { def_id, args } } pub fn with_self_ty( @@ -1665,7 +1667,7 @@ impl<'tcx> ExistentialProjection<'tcx> { ty::ProjectionPredicate { projection_ty: tcx - .mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs)), + .mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.args)), term: self.term, } } @@ -1675,11 +1677,11 @@ impl<'tcx> ExistentialProjection<'tcx> { projection_predicate: ty::ProjectionPredicate<'tcx>, ) -> Self { // Assert there is a Self. - projection_predicate.projection_ty.substs.type_at(0); + projection_predicate.projection_ty.args.type_at(0); Self { def_id: projection_predicate.projection_ty.def_id, - substs: tcx.mk_substs(&projection_predicate.projection_ty.substs[1..]), + args: tcx.mk_args(&projection_predicate.projection_ty.args[1..]), term: projection_predicate.term, } } @@ -1868,6 +1870,388 @@ impl<'tcx> Region<'tcx> { } } +/// Constructors for `Ty` +impl<'tcx> Ty<'tcx> { + // Avoid this in favour of more specific `new_*` methods, where possible. + #[allow(rustc::usage_of_ty_tykind)] + #[inline] + pub fn new(tcx: TyCtxt<'tcx>, st: TyKind<'tcx>) -> Ty<'tcx> { + tcx.mk_ty_from_kind(st) + } + + #[inline] + pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferTy) -> Ty<'tcx> { + Ty::new(tcx, TyKind::Infer(infer)) + } + + #[inline] + pub fn new_var(tcx: TyCtxt<'tcx>, v: ty::TyVid) -> Ty<'tcx> { + // Use a pre-interned one when possible. + tcx.types + .ty_vars + .get(v.as_usize()) + .copied() + .unwrap_or_else(|| Ty::new(tcx, Infer(TyVar(v)))) + } + + #[inline] + pub fn new_int_var(tcx: TyCtxt<'tcx>, v: ty::IntVid) -> Ty<'tcx> { + Ty::new_infer(tcx, IntVar(v)) + } + + #[inline] + pub fn new_float_var(tcx: TyCtxt<'tcx>, v: ty::FloatVid) -> Ty<'tcx> { + Ty::new_infer(tcx, FloatVar(v)) + } + + #[inline] + pub fn new_fresh(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> { + // Use a pre-interned one when possible. + tcx.types + .fresh_tys + .get(n as usize) + .copied() + .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshTy(n))) + } + + #[inline] + pub fn new_fresh_int(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> { + // Use a pre-interned one when possible. + tcx.types + .fresh_int_tys + .get(n as usize) + .copied() + .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshIntTy(n))) + } + + #[inline] + pub fn new_fresh_float(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> { + // Use a pre-interned one when possible. + tcx.types + .fresh_float_tys + .get(n as usize) + .copied() + .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshFloatTy(n))) + } + + #[inline] + pub fn new_param(tcx: TyCtxt<'tcx>, index: u32, name: Symbol) -> Ty<'tcx> { + tcx.mk_ty_from_kind(Param(ParamTy { index, name })) + } + + #[inline] + pub fn new_bound( + tcx: TyCtxt<'tcx>, + index: ty::DebruijnIndex, + bound_ty: ty::BoundTy, + ) -> Ty<'tcx> { + Ty::new(tcx, Bound(index, bound_ty)) + } + + #[inline] + pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderType) -> Ty<'tcx> { + Ty::new(tcx, Placeholder(placeholder)) + } + + #[inline] + pub fn new_alias( + tcx: TyCtxt<'tcx>, + kind: ty::AliasKind, + alias_ty: ty::AliasTy<'tcx>, + ) -> Ty<'tcx> { + debug_assert_matches!( + (kind, tcx.def_kind(alias_ty.def_id)), + (ty::Opaque, DefKind::OpaqueTy) + | (ty::Projection | ty::Inherent, DefKind::AssocTy) + | (ty::Weak, DefKind::TyAlias) + ); + Ty::new(tcx, Alias(kind, alias_ty)) + } + + #[inline] + pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>) -> Ty<'tcx> { + Ty::new_alias(tcx, ty::Opaque, tcx.mk_alias_ty(def_id, args)) + } + + /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed` + pub fn new_error(tcx: TyCtxt<'tcx>, reported: ErrorGuaranteed) -> Ty<'tcx> { + Ty::new(tcx, Error(reported)) + } + + /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. + #[track_caller] + pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + Ty::new_error_with_message(tcx, DUMMY_SP, "TyKind::Error constructed but no error reported") + } + + /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to + /// ensure it gets used. + #[track_caller] + pub fn new_error_with_message<S: Into<MultiSpan>>( + tcx: TyCtxt<'tcx>, + span: S, + msg: impl Into<String>, + ) -> Ty<'tcx> { + let reported = tcx.sess.delay_span_bug(span, msg); + Ty::new(tcx, Error(reported)) + } + + #[inline] + pub fn new_int(tcx: TyCtxt<'tcx>, i: ty::IntTy) -> Ty<'tcx> { + use ty::IntTy::*; + match i { + Isize => tcx.types.isize, + I8 => tcx.types.i8, + I16 => tcx.types.i16, + I32 => tcx.types.i32, + I64 => tcx.types.i64, + I128 => tcx.types.i128, + } + } + + #[inline] + pub fn new_uint(tcx: TyCtxt<'tcx>, ui: ty::UintTy) -> Ty<'tcx> { + use ty::UintTy::*; + match ui { + Usize => tcx.types.usize, + U8 => tcx.types.u8, + U16 => tcx.types.u16, + U32 => tcx.types.u32, + U64 => tcx.types.u64, + U128 => tcx.types.u128, + } + } + + #[inline] + pub fn new_float(tcx: TyCtxt<'tcx>, f: ty::FloatTy) -> Ty<'tcx> { + use ty::FloatTy::*; + match f { + F32 => tcx.types.f32, + F64 => tcx.types.f64, + } + } + + #[inline] + pub fn new_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { + Ty::new(tcx, Ref(r, tm.ty, tm.mutbl)) + } + + #[inline] + pub fn new_mut_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + Ty::new_ref(tcx, r, TypeAndMut { ty, mutbl: hir::Mutability::Mut }) + } + + #[inline] + pub fn new_imm_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + Ty::new_ref(tcx, r, TypeAndMut { ty, mutbl: hir::Mutability::Not }) + } + + #[inline] + pub fn new_ptr(tcx: TyCtxt<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { + Ty::new(tcx, RawPtr(tm)) + } + + #[inline] + pub fn new_mut_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + Ty::new_ptr(tcx, TypeAndMut { ty, mutbl: hir::Mutability::Mut }) + } + + #[inline] + pub fn new_imm_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + Ty::new_ptr(tcx, TypeAndMut { ty, mutbl: hir::Mutability::Not }) + } + + #[inline] + pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> { + Ty::new(tcx, Adt(def, args)) + } + + #[inline] + pub fn new_foreign(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> { + Ty::new(tcx, Foreign(def_id)) + } + + #[inline] + pub fn new_array(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> { + Ty::new(tcx, Array(ty, ty::Const::from_target_usize(tcx, n))) + } + + #[inline] + pub fn new_array_with_const_len( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + ct: ty::Const<'tcx>, + ) -> Ty<'tcx> { + Ty::new(tcx, Array(ty, ct)) + } + + #[inline] + pub fn new_slice(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + Ty::new(tcx, Slice(ty)) + } + + #[inline] + pub fn new_tup(tcx: TyCtxt<'tcx>, ts: &[Ty<'tcx>]) -> Ty<'tcx> { + if ts.is_empty() { tcx.types.unit } else { Ty::new(tcx, Tuple(tcx.mk_type_list(&ts))) } + } + + pub fn new_tup_from_iter<I, T>(tcx: TyCtxt<'tcx>, iter: I) -> T::Output + where + I: Iterator<Item = T>, + T: CollectAndApply<Ty<'tcx>, Ty<'tcx>>, + { + T::collect_and_apply(iter, |ts| Ty::new_tup(tcx, ts)) + } + + #[inline] + pub fn new_fn_def( + tcx: TyCtxt<'tcx>, + def_id: DefId, + args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, + ) -> Ty<'tcx> { + let args = tcx.check_and_mk_args(def_id, args); + Ty::new(tcx, FnDef(def_id, args)) + } + + #[inline] + pub fn new_fn_ptr(tcx: TyCtxt<'tcx>, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { + Ty::new(tcx, FnPtr(fty)) + } + + #[inline] + pub fn new_dynamic( + tcx: TyCtxt<'tcx>, + obj: &'tcx List<PolyExistentialPredicate<'tcx>>, + reg: ty::Region<'tcx>, + repr: DynKind, + ) -> Ty<'tcx> { + Ty::new(tcx, Dynamic(obj, reg, repr)) + } + + #[inline] + pub fn new_projection( + tcx: TyCtxt<'tcx>, + item_def_id: DefId, + args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, + ) -> Ty<'tcx> { + Ty::new_alias(tcx, ty::Projection, tcx.mk_alias_ty(item_def_id, args)) + } + + #[inline] + pub fn new_closure( + tcx: TyCtxt<'tcx>, + def_id: DefId, + closure_args: GenericArgsRef<'tcx>, + ) -> Ty<'tcx> { + debug_assert_eq!( + closure_args.len(), + tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 3, + "closure constructed with incorrect substitutions" + ); + Ty::new(tcx, Closure(def_id, closure_args)) + } + + #[inline] + pub fn new_generator( + tcx: TyCtxt<'tcx>, + def_id: DefId, + generator_args: GenericArgsRef<'tcx>, + movability: hir::Movability, + ) -> Ty<'tcx> { + debug_assert_eq!( + generator_args.len(), + tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5, + "generator constructed with incorrect number of substitutions" + ); + Ty::new(tcx, Generator(def_id, generator_args, movability)) + } + + #[inline] + pub fn new_generator_witness( + tcx: TyCtxt<'tcx>, + types: ty::Binder<'tcx, &'tcx List<Ty<'tcx>>>, + ) -> Ty<'tcx> { + Ty::new(tcx, GeneratorWitness(types)) + } + + #[inline] + pub fn new_generator_witness_mir( + tcx: TyCtxt<'tcx>, + id: DefId, + args: GenericArgsRef<'tcx>, + ) -> Ty<'tcx> { + Ty::new(tcx, GeneratorWitnessMIR(id, args)) + } + + // misc + + #[inline] + pub fn new_unit(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + tcx.types.unit + } + + #[inline] + pub fn new_static_str(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_) + } + + #[inline] + pub fn new_diverging_default(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + if tcx.features().never_type_fallback { tcx.types.never } else { tcx.types.unit } + } + + // lang and diagnostic tys + + fn new_generic_adt(tcx: TyCtxt<'tcx>, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> { + let adt_def = tcx.adt_def(wrapper_def_id); + let args = GenericArgs::for_item(tcx, wrapper_def_id, |param, args| match param.kind { + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(), + GenericParamDefKind::Type { has_default, .. } => { + if param.index == 0 { + ty_param.into() + } else { + assert!(has_default); + tcx.type_of(param.def_id).instantiate(tcx, args).into() + } + } + }); + Ty::new(tcx, Adt(adt_def, args)) + } + + #[inline] + pub fn new_lang_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> { + let def_id = tcx.lang_items().get(item)?; + Some(Ty::new_generic_adt(tcx, def_id, ty)) + } + + #[inline] + pub fn new_diagnostic_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> { + let def_id = tcx.get_diagnostic_item(name)?; + Some(Ty::new_generic_adt(tcx, def_id, ty)) + } + + #[inline] + pub fn new_box(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + let def_id = tcx.require_lang_item(LangItem::OwnedBox, None); + Ty::new_generic_adt(tcx, def_id, ty) + } + + #[inline] + pub fn new_maybe_uninit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + let def_id = tcx.require_lang_item(LangItem::MaybeUninit, None); + Ty::new_generic_adt(tcx, def_id, ty) + } + + /// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes. + pub fn new_task_context(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + let context_did = tcx.require_lang_item(LangItem::Context, None); + let context_adt_ref = tcx.adt_def(context_did); + let context_args = tcx.mk_args(&[tcx.lifetimes.re_erased.into()]); + let context_ty = Ty::new_adt(tcx, context_adt_ref, context_args); + Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, context_ty) + } +} + /// Type utilities impl<'tcx> Ty<'tcx> { #[inline(always)] @@ -1987,10 +2371,10 @@ impl<'tcx> Ty<'tcx> { pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) { match self.kind() { - Adt(def, substs) => { + Adt(def, args) => { assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type"); let variant = def.non_enum_variant(); - let f0_ty = variant.fields[FieldIdx::from_u32(0)].ty(tcx, substs); + let f0_ty = variant.fields[FieldIdx::from_u32(0)].ty(tcx, args); match f0_ty.kind() { // If the first field is an array, we assume it is the only field and its @@ -2051,7 +2435,7 @@ impl<'tcx> Ty<'tcx> { /// Panics if called on any type other than `Box<T>`. pub fn boxed_ty(self) -> Ty<'tcx> { match self.kind() { - Adt(def, substs) if def.is_box() => substs.type_at(0), + Adt(def, args) if def.is_box() => args.type_at(0), _ => bug!("`boxed_ty` is called on non-box type {:?}", self), } } @@ -2215,14 +2599,14 @@ impl<'tcx> Ty<'tcx> { pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> { match self.kind() { - FnDef(def_id, substs) => tcx.fn_sig(*def_id).subst(tcx, substs), + FnDef(def_id, args) => tcx.fn_sig(*def_id).instantiate(tcx, args), FnPtr(f) => *f, Error(_) => { // ignore errors (#54954) ty::Binder::dummy(FnSig::fake()) } Closure(..) => bug!( - "to get the signature of a closure, use `substs.as_closure().sig()` not `fn_sig()`", + "to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`", ), _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self), } @@ -2256,7 +2640,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn tuple_fields(self) -> &'tcx List<Ty<'tcx>> { match self.kind() { - Tuple(substs) => substs, + Tuple(args) => args, _ => bug!("tuple_fields called on non-tuple"), } } @@ -2268,8 +2652,8 @@ impl<'tcx> Ty<'tcx> { pub fn variant_range(self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> { match self.kind() { TyKind::Adt(adt, _) => Some(adt.variant_range()), - TyKind::Generator(def_id, substs, _) => { - Some(substs.as_generator().variant_range(*def_id, tcx)) + TyKind::Generator(def_id, args, _) => { + Some(args.as_generator().variant_range(*def_id, tcx)) } _ => None, } @@ -2294,8 +2678,8 @@ impl<'tcx> Ty<'tcx> { TyKind::Adt(adt, _) if adt.is_enum() => { Some(adt.discriminant_for_variant(tcx, variant_index)) } - TyKind::Generator(def_id, substs, _) => { - Some(substs.as_generator().discriminant_for_variant(*def_id, tcx, variant_index)) + TyKind::Generator(def_id, args, _) => { + Some(args.as_generator().discriminant_for_variant(*def_id, tcx, variant_index)) } _ => None, } @@ -2305,13 +2689,13 @@ impl<'tcx> Ty<'tcx> { pub fn discriminant_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match self.kind() { ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx), - ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx), + ty::Generator(_, args, _) => args.as_generator().discr_ty(tcx), ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => { let assoc_items = tcx.associated_item_def_ids( tcx.require_lang_item(hir::LangItem::DiscriminantKind, None), ); - tcx.mk_projection(assoc_items[0], tcx.mk_substs(&[self.into()])) + Ty::new_projection(tcx, assoc_items[0], tcx.mk_args(&[self.into()])) } ty::Bool @@ -2384,7 +2768,7 @@ impl<'tcx> Ty<'tcx> { ty::Str | ty::Slice(_) => (tcx.types.usize, false), ty::Dynamic(..) => { let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None); - (tcx.type_of(dyn_metadata).subst(tcx, &[tail.into()]), false) + (tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()]), false) }, // type parameters only have unit metadata if they're sized, so return true @@ -2401,7 +2785,7 @@ impl<'tcx> Ty<'tcx> { } /// When we create a closure, we record its kind (i.e., what trait - /// it implements) into its `ClosureSubsts` using a type + /// it implements) into its `ClosureArgs` using a type /// parameter. This is kind of a phantom type, except that the /// most convenient thing for us to are the integral types. This /// function converts such a special type into the closure @@ -2464,7 +2848,7 @@ impl<'tcx> Ty<'tcx> { ty::Tuple(tys) => tys.iter().all(|ty| ty.is_trivially_sized(tcx)), - ty::Adt(def, _substs) => def.sized_constraint(tcx).skip_binder().is_empty(), + ty::Adt(def, _args) => def.sized_constraint(tcx).skip_binder().is_empty(), ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => false, diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index e61037e5ea8..6e55e7915c9 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -52,6 +52,16 @@ pub struct TraitDef { /// List of functions from `#[rustc_must_implement_one_of]` attribute one of which /// must be implemented. pub must_implement_one_of: Option<Box<[Ident]>>, + + /// Whether to add a builtin `dyn Trait: Trait` implementation. + /// This is enabled for all traits except ones marked with + /// `#[rustc_deny_explicit_impl(implement_via_object = false)]`. + pub implement_via_object: bool, + + /// Whether a trait is fully built-in, and any implementation is disallowed. + /// This only applies to built-in traits, and is marked via + /// `#[rustc_deny_explicit_impl(implement_via_object = ...)]`. + pub deny_explicit_impl: bool, } /// Whether this trait is treated specially by the standard library @@ -226,7 +236,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait for &impl_def_id in tcx.hir().trait_impls(trait_id) { let impl_def_id = impl_def_id.to_def_id(); - let impl_self_ty = tcx.type_of(impl_def_id).subst_identity(); + let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity(); if impl_self_ty.references_error() { continue; } diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 8cbffa14850..327cd0a5d7b 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -4,13 +4,12 @@ use crate::{ traits::ObligationCause, ty::{ self, tls, BindingMode, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData, - GenericArgKind, InternalSubsts, SubstsRef, Ty, UserSubsts, + GenericArgKind, GenericArgs, GenericArgsRef, Ty, UserArgs, }, }; use rustc_data_structures::{ - fx::{FxHashMap, FxIndexMap}, - sync::Lrc, - unord::{UnordItems, UnordSet}, + fx::FxIndexMap, + unord::{ExtendUnord, UnordItems, UnordSet}, }; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; @@ -54,7 +53,7 @@ pub struct TypeckResults<'tcx> { /// of this node. This only applies to nodes that refer to entities /// parameterized by type parameters, such as generic fns, types, or /// other items. - node_substs: ItemLocalMap<SubstsRef<'tcx>>, + node_args: ItemLocalMap<GenericArgsRef<'tcx>>, /// This will either store the canonicalized types provided by the user /// or the substitutions that the user explicitly gave (if any) attached @@ -145,7 +144,7 @@ pub struct TypeckResults<'tcx> { /// This is used for warning unused imports. During type /// checking, this `Lrc` should not be cloned: it must have a ref-count /// of 1 so that we can insert things into the set mutably. - pub used_trait_imports: Lrc<UnordSet<LocalDefId>>, + pub used_trait_imports: UnordSet<LocalDefId>, /// If any errors occurred while type-checking this body, /// this field will be set to `Some(ErrorGuaranteed)`. @@ -183,7 +182,7 @@ pub struct TypeckResults<'tcx> { /// we never capture `t`. This becomes an issue when we build MIR as we require /// information on `t` in order to create place `t.0` and `t.1`. We can solve this /// issue by fake reading `t`. - pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>, + pub closure_fake_reads: LocalDefIdMap<Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>, /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions /// by applying extended parameter rules. @@ -197,7 +196,7 @@ pub struct TypeckResults<'tcx> { /// Stores the predicates that apply on generator witness types. /// formatting modified file tests/ui/generator/retain-resume-ref.rs pub generator_interior_predicates: - FxHashMap<LocalDefId, Vec<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>>, + LocalDefIdMap<Vec<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>>, /// We sometimes treat byte string literals (which are of type `&[u8; N]`) /// as `&[u8]`, depending on the pattern in which they are used. @@ -207,7 +206,7 @@ pub struct TypeckResults<'tcx> { /// Contains the data for evaluating the effect of feature `capture_disjoint_fields` /// on closure size. - pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>, + pub closure_size_eval: LocalDefIdMap<ClosureSizeProfileData<'tcx>>, /// Container types and field indices of `offset_of!` expressions offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<FieldIdx>)>, @@ -265,7 +264,7 @@ impl<'tcx> TypeckResults<'tcx> { user_provided_types: Default::default(), user_provided_sigs: Default::default(), node_types: Default::default(), - node_substs: Default::default(), + node_args: Default::default(), adjustments: Default::default(), pat_binding_modes: Default::default(), pat_adjustments: Default::default(), @@ -273,7 +272,7 @@ impl<'tcx> TypeckResults<'tcx> { liberated_fn_sigs: Default::default(), fru_field_types: Default::default(), coercion_casts: Default::default(), - used_trait_imports: Lrc::new(Default::default()), + used_trait_imports: Default::default(), tainted_by_errors: None, concrete_opaque_types: Default::default(), closure_min_captures: Default::default(), @@ -385,18 +384,18 @@ impl<'tcx> TypeckResults<'tcx> { self.node_types.get(&id.local_id).cloned() } - pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> { - LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs } + pub fn node_args_mut(&mut self) -> LocalTableInContextMut<'_, GenericArgsRef<'tcx>> { + LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_args } } - pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> { + pub fn node_args(&self, id: hir::HirId) -> GenericArgsRef<'tcx> { validate_hir_id_for_typeck_results(self.hir_owner, id); - self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty()) + self.node_args.get(&id.local_id).cloned().unwrap_or_else(|| GenericArgs::empty()) } - pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> { + pub fn node_args_opt(&self, id: hir::HirId) -> Option<GenericArgsRef<'tcx>> { validate_hir_id_for_typeck_results(self.hir_owner, id); - self.node_substs.get(&id.local_id).cloned() + self.node_args.get(&id.local_id).cloned() } /// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function @@ -636,7 +635,7 @@ impl<'a, V> LocalTableInContextMut<'a, V> { &mut self, items: UnordItems<(hir::HirId, V), impl Iterator<Item = (hir::HirId, V)>>, ) { - self.data.extend(items.map(|(id, value)| { + self.data.extend_unord(items.map(|(id, value)| { validate_hir_id_for_typeck_results(self.hir_owner, id); (id.local_id, value) })) @@ -671,12 +670,12 @@ impl<'tcx> CanonicalUserType<'tcx> { pub fn is_identity(&self) -> bool { match self.value { UserType::Ty(_) => false, - UserType::TypeOf(_, user_substs) => { - if user_substs.user_self_ty.is_some() { + UserType::TypeOf(_, user_args) => { + if user_args.user_self_ty.is_some() { return false; } - iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| { + iter::zip(user_args.args, BoundVar::new(0)..).all(|(kind, cvar)| { match kind.unpack() { GenericArgKind::Type(ty) => match ty.kind() { ty::Bound(debruijn, b) => { @@ -721,5 +720,5 @@ pub enum UserType<'tcx> { /// The canonical type is the result of `type_of(def_id)` with the /// given substitutions applied. - TypeOf(DefId, UserSubsts<'tcx>), + TypeOf(DefId, UserArgs<'tcx>), } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index c9f69c37782..553b76cad4e 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1,14 +1,13 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use crate::mir; use crate::query::Providers; use crate::ty::layout::IntegerExt; use crate::ty::{ self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; -use crate::ty::{GenericArgKind, SubstsRef}; +use crate::ty::{GenericArgKind, GenericArgsRef}; use rustc_apfloat::Float as _; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher}; @@ -17,11 +16,10 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_index::bit_set::GrowableBitSet; -use rustc_index::{Idx, IndexVec}; use rustc_macros::HashStable; use rustc_session::Limit; use rustc_span::sym; -use rustc_target::abi::{Integer, IntegerType, Size, TargetDataLayout}; +use rustc_target::abi::{Integer, IntegerType, Size}; use rustc_target::spec::abi::Abi; use smallvec::SmallVec; use std::{fmt, iter}; @@ -225,17 +223,17 @@ impl<'tcx> TyCtxt<'tcx> { }; let reported = self.sess.emit_err(crate::error::RecursionLimitReached { ty, suggested_limit }); - return self.ty_error(reported); + return Ty::new_error(self, reported); } match *ty.kind() { - ty::Adt(def, substs) => { + ty::Adt(def, args) => { if !def.is_struct() { break; } - match def.non_enum_variant().fields.raw.last() { + match def.non_enum_variant().tail_opt() { Some(field) => { f(); - ty = field.ty(self, substs); + ty = field.ty(self, args); } None => break, } @@ -303,12 +301,12 @@ impl<'tcx> TyCtxt<'tcx> { let (mut a, mut b) = (source, target); loop { match (&a.kind(), &b.kind()) { - (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs)) + (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args)) if a_def == b_def && a_def.is_struct() => { - if let Some(f) = a_def.non_enum_variant().fields.raw.last() { - a = f.ty(self, a_substs); - b = f.ty(self, b_substs); + if let Some(f) = a_def.non_enum_variant().tail_opt() { + a = f.ty(self, a_args); + b = f.ty(self, b_args); } else { break; } @@ -351,7 +349,7 @@ impl<'tcx> TyCtxt<'tcx> { let drop_trait = self.lang_items().drop_trait()?; self.ensure().coherent_trait(drop_trait); - let ty = self.type_of(adt_did).subst_identity(); + let ty = self.type_of(adt_did).instantiate_identity(); let mut dtor_candidate = None; self.for_each_relevant_impl(drop_trait, ty, |impl_did| { if validate(self, impl_did).is_err() { @@ -360,7 +358,8 @@ impl<'tcx> TyCtxt<'tcx> { } let Some(item_id) = self.associated_item_def_ids(impl_did).first() else { - self.sess.delay_span_bug(self.def_span(impl_did), "Drop impl without drop function"); + self.sess + .delay_span_bug(self.def_span(impl_did), "Drop impl without drop function"); return; }; @@ -385,7 +384,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Note that this returns only the constraints for the /// destructor of `def` itself. For the destructors of the /// contents, you need `adt_dtorck_constraint`. - pub fn destructor_constraints(self, def: ty::AdtDef<'tcx>) -> Vec<ty::subst::GenericArg<'tcx>> { + pub fn destructor_constraints(self, def: ty::AdtDef<'tcx>) -> Vec<ty::GenericArg<'tcx>> { let dtor = match def.destructor(self) { None => { debug!("destructor_constraints({:?}) - no dtor", def.did()); @@ -402,7 +401,7 @@ impl<'tcx> TyCtxt<'tcx> { // must be live. // We need to return the list of parameters from the ADTs - // generics/substs that correspond to impure parameters on the + // generics/args that correspond to impure parameters on the // impl's generics. This is a bit ugly, but conceptually simple: // // Suppose our ADT looks like the following @@ -414,21 +413,21 @@ impl<'tcx> TyCtxt<'tcx> { // impl<#[may_dangle] P0, P1, P2> Drop for S<P1, P2, P0> // // We want to return the parameters (X, Y). For that, we match - // up the item-substs <X, Y, Z> with the substs on the impl ADT, - // <P1, P2, P0>, and then look up which of the impl substs refer to + // up the item-args <X, Y, Z> with the args on the impl ADT, + // <P1, P2, P0>, and then look up which of the impl args refer to // parameters marked as pure. - let impl_substs = match *self.type_of(impl_def_id).subst_identity().kind() { - ty::Adt(def_, substs) if def_ == def => substs, + let impl_args = match *self.type_of(impl_def_id).instantiate_identity().kind() { + ty::Adt(def_, args) if def_ == def => args, _ => bug!(), }; - let item_substs = match *self.type_of(def.did()).subst_identity().kind() { - ty::Adt(def_, substs) if def_ == def => substs, + let item_args = match *self.type_of(def.did()).instantiate_identity().kind() { + ty::Adt(def_, args) if def_ == def => args, _ => bug!(), }; - let result = iter::zip(item_substs, impl_substs) + let result = iter::zip(item_args, impl_args) .filter(|&(_, k)| { match k.unpack() { GenericArgKind::Lifetime(region) => match region.kind() { @@ -461,12 +460,12 @@ impl<'tcx> TyCtxt<'tcx> { /// Checks whether each generic argument is simply a unique generic parameter. pub fn uses_unique_generic_params( self, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, ignore_regions: CheckRegions, ) -> Result<(), NotUniqueParam<'tcx>> { let mut seen = GrowableBitSet::default(); let mut seen_late = FxHashSet::default(); - for arg in substs { + for arg in args { match arg.unpack() { GenericArgKind::Lifetime(lt) => match (ignore_regions, lt.kind()) { (CheckRegions::Bound, ty::ReLateBound(di, reg)) => { @@ -512,10 +511,10 @@ impl<'tcx> TyCtxt<'tcx> { /// for better caching. pub fn uses_unique_placeholders_ignoring_regions( self, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, ) -> Result<(), NotUniqueParam<'tcx>> { let mut seen = GrowableBitSet::default(); - for arg in substs { + for arg in args { match arg.unpack() { // Ignore regions, since we can't resolve those in a canonicalized // query in the trait solver. @@ -596,7 +595,7 @@ impl<'tcx> TyCtxt<'tcx> { def_id } - /// Given the `DefId` and substs a closure, creates the type of + /// Given the `DefId` and args a closure, creates the type of /// `self` argument that the closure expects. For example, for a /// `Fn` closure, this would return a reference type `&T` where /// `T = closure_ty`. @@ -609,15 +608,15 @@ impl<'tcx> TyCtxt<'tcx> { pub fn closure_env_ty( self, closure_def_id: DefId, - closure_substs: SubstsRef<'tcx>, + closure_args: GenericArgsRef<'tcx>, env_region: ty::Region<'tcx>, ) -> Option<Ty<'tcx>> { - let closure_ty = self.mk_closure(closure_def_id, closure_substs); - let closure_kind_ty = closure_substs.as_closure().kind_ty(); + let closure_ty = Ty::new_closure(self, closure_def_id, closure_args); + let closure_kind_ty = closure_args.as_closure().kind_ty(); let closure_kind = closure_kind_ty.to_opt_closure_kind()?; let env_ty = match closure_kind { - ty::ClosureKind::Fn => self.mk_imm_ref(env_region, closure_ty), - ty::ClosureKind::FnMut => self.mk_mut_ref(env_region, closure_ty), + ty::ClosureKind::Fn => Ty::new_imm_ref(self, env_region, closure_ty), + ty::ClosureKind::FnMut => Ty::new_mut_ref(self, env_region, closure_ty), ty::ClosureKind::FnOnce => closure_ty, }; Some(env_ty) @@ -656,14 +655,14 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns the type a reference to the thread local takes in MIR. pub fn thread_local_ptr_ty(self, def_id: DefId) -> Ty<'tcx> { - let static_ty = self.type_of(def_id).subst_identity(); + let static_ty = self.type_of(def_id).instantiate_identity(); if self.is_mutable_static(def_id) { - self.mk_mut_ptr(static_ty) + Ty::new_mut_ptr(self, static_ty) } else if self.is_foreign_item(def_id) { - self.mk_imm_ptr(static_ty) + Ty::new_imm_ptr(self, static_ty) } else { // FIXME: These things don't *really* have 'static lifetime. - self.mk_imm_ref(self.lifetimes.re_static, static_ty) + Ty::new_imm_ref(self, self.lifetimes.re_static, static_ty) } } @@ -672,17 +671,17 @@ impl<'tcx> TyCtxt<'tcx> { // Make sure that any constants in the static's type are evaluated. let static_ty = self.normalize_erasing_regions( ty::ParamEnv::empty(), - self.type_of(def_id).subst_identity(), + self.type_of(def_id).instantiate_identity(), ); // Make sure that accesses to unsafe statics end up using raw pointers. // For thread-locals, this needs to be kept in sync with `Rvalue::ty`. if self.is_mutable_static(def_id) { - self.mk_mut_ptr(static_ty) + Ty::new_mut_ptr(self, static_ty) } else if self.is_foreign_item(def_id) { - self.mk_imm_ptr(static_ty) + Ty::new_imm_ptr(self, static_ty) } else { - self.mk_imm_ref(self.lifetimes.re_erased, static_ty) + Ty::new_imm_ref(self, self.lifetimes.re_erased, static_ty) } } @@ -721,7 +720,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn try_expand_impl_trait_type( self, def_id: DefId, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, ) -> Result<Ty<'tcx>, Ty<'tcx>> { let mut visitor = OpaqueTypeExpander { seen_opaque_tys: FxHashSet::default(), @@ -734,84 +733,10 @@ impl<'tcx> TyCtxt<'tcx> { tcx: self, }; - let expanded_type = visitor.expand_opaque_ty(def_id, substs).unwrap(); + let expanded_type = visitor.expand_opaque_ty(def_id, args).unwrap(); if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) } } - /// Returns names of captured upvars for closures and generators. - /// - /// Here are some examples: - /// - `name__field1__field2` when the upvar is captured by value. - /// - `_ref__name__field` when the upvar is captured by reference. - /// - /// For generators this only contains upvars that are shared by all states. - pub fn closure_saved_names_of_captured_variables( - self, - def_id: DefId, - ) -> SmallVec<[String; 16]> { - let body = self.optimized_mir(def_id); - - body.var_debug_info - .iter() - .filter_map(|var| { - let is_ref = match var.value { - mir::VarDebugInfoContents::Place(place) - if place.local == mir::Local::new(1) => - { - // The projection is either `[.., Field, Deref]` or `[.., Field]`. It - // implies whether the variable is captured by value or by reference. - matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref) - } - _ => return None, - }; - let prefix = if is_ref { "_ref__" } else { "" }; - Some(prefix.to_owned() + var.name.as_str()) - }) - .collect() - } - - // FIXME(eddyb) maybe precompute this? Right now it's computed once - // per generator monomorphization, but it doesn't depend on substs. - pub fn generator_layout_and_saved_local_names( - self, - def_id: DefId, - ) -> ( - &'tcx ty::GeneratorLayout<'tcx>, - IndexVec<mir::GeneratorSavedLocal, Option<rustc_span::Symbol>>, - ) { - let tcx = self; - let body = tcx.optimized_mir(def_id); - let generator_layout = body.generator_layout().unwrap(); - let mut generator_saved_local_names = - IndexVec::from_elem(None, &generator_layout.field_tys); - - let state_arg = mir::Local::new(1); - for var in &body.var_debug_info { - let mir::VarDebugInfoContents::Place(place) = &var.value else { continue }; - if place.local != state_arg { - continue; - } - match place.projection[..] { - [ - // Deref of the `Pin<&mut Self>` state argument. - mir::ProjectionElem::Field(..), - mir::ProjectionElem::Deref, - // Field of a variant of the state. - mir::ProjectionElem::Downcast(_, variant), - mir::ProjectionElem::Field(field, _), - ] => { - let name = &mut generator_saved_local_names - [generator_layout.variant_fields[variant][field]]; - if name.is_none() { - name.replace(var.name); - } - } - _ => {} - } - } - (generator_layout, generator_saved_local_names) - } - /// Query and get an English description for the item's kind. pub fn def_descr(self, def_id: DefId) -> &'static str { self.def_kind_descr(self.def_kind(def_id), def_id) @@ -875,7 +800,7 @@ struct OpaqueTypeExpander<'tcx> { seen_opaque_tys: FxHashSet<DefId>, // Cache of all expansions we've seen so far. This is a critical // optimization for some large types produced by async fn trees. - expanded_cache: FxHashMap<(DefId, SubstsRef<'tcx>), Ty<'tcx>>, + expanded_cache: FxHashMap<(DefId, GenericArgsRef<'tcx>), Ty<'tcx>>, primary_def_id: Option<DefId>, found_recursion: bool, found_any_recursion: bool, @@ -888,19 +813,19 @@ struct OpaqueTypeExpander<'tcx> { } impl<'tcx> OpaqueTypeExpander<'tcx> { - fn expand_opaque_ty(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> Option<Ty<'tcx>> { + fn expand_opaque_ty(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> Option<Ty<'tcx>> { if self.found_any_recursion { return None; } - let substs = substs.fold_with(self); + let args = args.fold_with(self); if !self.check_recursion || self.seen_opaque_tys.insert(def_id) { - let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) { + let expanded_ty = match self.expanded_cache.get(&(def_id, args)) { Some(expanded_ty) => *expanded_ty, None => { let generic_ty = self.tcx.type_of(def_id); - let concrete_ty = generic_ty.subst(self.tcx, substs); + let concrete_ty = generic_ty.instantiate(self.tcx, args); let expanded_ty = self.fold_ty(concrete_ty); - self.expanded_cache.insert((def_id, substs), expanded_ty); + self.expanded_cache.insert((def_id, args), expanded_ty); expanded_ty } }; @@ -917,21 +842,21 @@ impl<'tcx> OpaqueTypeExpander<'tcx> { } } - fn expand_generator(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> Option<Ty<'tcx>> { + fn expand_generator(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> Option<Ty<'tcx>> { if self.found_any_recursion { return None; } - let substs = substs.fold_with(self); + let args = args.fold_with(self); if !self.check_recursion || self.seen_opaque_tys.insert(def_id) { - let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) { + let expanded_ty = match self.expanded_cache.get(&(def_id, args)) { Some(expanded_ty) => *expanded_ty, None => { for bty in self.tcx.generator_hidden_types(def_id) { - let hidden_ty = bty.subst(self.tcx, substs); + let hidden_ty = bty.instantiate(self.tcx, args); self.fold_ty(hidden_ty); } - let expanded_ty = self.tcx.mk_generator_witness_mir(def_id, substs); - self.expanded_cache.insert((def_id, substs), expanded_ty); + let expanded_ty = Ty::new_generator_witness_mir(self.tcx, def_id, args); + self.expanded_cache.insert((def_id, args), expanded_ty); expanded_ty } }; @@ -955,16 +880,16 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> { } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - let mut t = if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *t.kind() { - self.expand_opaque_ty(def_id, substs).unwrap_or(t) + let mut t = if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) = *t.kind() { + self.expand_opaque_ty(def_id, args).unwrap_or(t) } else if t.has_opaque_types() || t.has_generators() { t.super_fold_with(self) } else { t }; if self.expand_generators { - if let ty::GeneratorWitnessMIR(def_id, substs) = *t.kind() { - t = self.expand_generator(def_id, substs).unwrap_or(t); + if let ty::GeneratorWitnessMIR(def_id, args) = *t.kind() { + t = self.expand_generator(def_id, args).unwrap_or(t); } } t @@ -972,7 +897,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> { fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { if let ty::PredicateKind::Clause(clause) = p.kind().skip_binder() - && let ty::Clause::Projection(projection_pred) = clause + && let ty::ClauseKind::Projection(projection_pred) = clause { p.kind() .rebind(ty::ProjectionPredicate { @@ -1160,7 +1085,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn needs_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { // Avoid querying in simple cases. - match needs_drop_components(self, &tcx.data_layout) { + match needs_drop_components(tcx, self) { Err(AlwaysRequiresDrop) => true, Ok(components) => { let query_ty = match *components { @@ -1193,7 +1118,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { // Avoid querying in simple cases. - match needs_drop_components(self, &tcx.data_layout) { + match needs_drop_components(tcx, self) { Err(AlwaysRequiresDrop) => true, Ok(components) => { let query_ty = match *components { @@ -1353,10 +1278,10 @@ impl<'tcx> ExplicitSelf<'tcx> { /// *any* of the returned types need drop. Returns `Err(AlwaysRequiresDrop)` if /// this type always needs drop. pub fn needs_drop_components<'tcx>( + tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, - target_layout: &TargetDataLayout, ) -> Result<SmallVec<[Ty<'tcx>; 2]>, AlwaysRequiresDrop> { - match ty.kind() { + match *ty.kind() { ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) | ty::Bool @@ -1378,11 +1303,11 @@ pub fn needs_drop_components<'tcx>( ty::Dynamic(..) | ty::Error(_) => Err(AlwaysRequiresDrop), - ty::Slice(ty) => needs_drop_components(*ty, target_layout), + ty::Slice(ty) => needs_drop_components(tcx, ty), ty::Array(elem_ty, size) => { - match needs_drop_components(*elem_ty, target_layout) { + match needs_drop_components(tcx, elem_ty) { Ok(v) if v.is_empty() => Ok(v), - res => match size.kind().try_to_bits(target_layout.pointer_size) { + res => match size.try_to_target_usize(tcx) { // Arrays of size zero don't need drop, even if their element // type does. Some(0) => Ok(SmallVec::new()), @@ -1396,7 +1321,7 @@ pub fn needs_drop_components<'tcx>( } // If any field needs drop, then the whole tuple does. ty::Tuple(fields) => fields.iter().try_fold(SmallVec::new(), move |mut acc, elem| { - acc.extend(needs_drop_components(elem, target_layout)?); + acc.extend(needs_drop_components(tcx, elem)?); Ok(acc) }), @@ -1495,8 +1420,8 @@ pub struct AlwaysRequiresDrop; /// with their underlying types. pub fn reveal_opaque_types_in_bounds<'tcx>( tcx: TyCtxt<'tcx>, - val: &'tcx ty::List<ty::Predicate<'tcx>>, -) -> &'tcx ty::List<ty::Predicate<'tcx>> { + val: &'tcx ty::List<ty::Clause<'tcx>>, +) -> &'tcx ty::List<ty::Clause<'tcx>> { let mut visitor = OpaqueTypeExpander { seen_opaque_tys: FxHashSet::default(), expanded_cache: FxHashMap::default(), diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 04a635a6803..7c3d9ed390a 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -1,8 +1,8 @@ //! An iterator over the type substructure. //! WARNING: this does not keep track of the region depth. -use crate::ty::subst::{GenericArg, GenericArgKind}; use crate::ty::{self, Ty}; +use crate::ty::{GenericArg, GenericArgKind}; use rustc_data_structures::sso::SsoHashSet; use smallvec::SmallVec; @@ -166,33 +166,33 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) stack.push(lt.into()); } ty::Alias(_, data) => { - stack.extend(data.substs.iter().rev()); + stack.extend(data.args.iter().rev()); } ty::Dynamic(obj, lt, _) => { stack.push(lt.into()); stack.extend(obj.iter().rev().flat_map(|predicate| { - let (substs, opt_ty) = match predicate.skip_binder() { - ty::ExistentialPredicate::Trait(tr) => (tr.substs, None), - ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.term)), + let (args, opt_ty) = match predicate.skip_binder() { + ty::ExistentialPredicate::Trait(tr) => (tr.args, None), + ty::ExistentialPredicate::Projection(p) => (p.args, Some(p.term)), ty::ExistentialPredicate::AutoTrait(_) => // Empty iterator { - (ty::InternalSubsts::empty(), None) + (ty::GenericArgs::empty(), None) } }; - substs.iter().rev().chain(opt_ty.map(|term| match term.unpack() { + args.iter().rev().chain(opt_ty.map(|term| match term.unpack() { ty::TermKind::Ty(ty) => ty.into(), ty::TermKind::Const(ct) => ct.into(), })) })); } - ty::Adt(_, substs) - | ty::Closure(_, substs) - | ty::Generator(_, substs, _) - | ty::GeneratorWitnessMIR(_, substs) - | ty::FnDef(_, substs) => { - stack.extend(substs.iter().rev()); + ty::Adt(_, args) + | ty::Closure(_, args) + | ty::Generator(_, args, _) + | ty::GeneratorWitnessMIR(_, args) + | ty::FnDef(_, args) => { + stack.extend(args.iter().rev()); } ty::Tuple(ts) => stack.extend(ts.iter().rev().map(GenericArg::from)), ty::GeneratorWitness(ts) => { @@ -233,7 +233,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) }, ty::ConstKind::Unevaluated(ct) => { - stack.extend(ct.substs.iter().rev()); + stack.extend(ct.args.iter().rev()); } } } diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs index 98d55ea6d40..4e2a2c6ae0a 100644 --- a/compiler/rustc_middle/src/util/call_kind.rs +++ b/compiler/rustc_middle/src/util/call_kind.rs @@ -2,7 +2,7 @@ //! as well as errors when attempting to call a non-const function in a const //! context. -use crate::ty::subst::SubstsRef; +use crate::ty::GenericArgsRef; use crate::ty::{AssocItemContainer, Instance, ParamEnv, Ty, TyCtxt}; use rustc_hir::def_id::DefId; use rustc_hir::{lang_items, LangItem}; @@ -43,7 +43,7 @@ pub enum CallKind<'tcx> { self_arg: Option<Ident>, desugaring: Option<(CallDesugaringKind, Ty<'tcx>)>, method_did: DefId, - method_substs: SubstsRef<'tcx>, + method_args: GenericArgsRef<'tcx>, }, /// A call to `Fn(..)::call(..)`, desugared from `my_closure(a, b, c)` FnCall { fn_trait_id: DefId, self_ty: Ty<'tcx> }, @@ -63,7 +63,7 @@ pub fn call_kind<'tcx>( tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, method_did: DefId, - method_substs: SubstsRef<'tcx>, + method_args: GenericArgsRef<'tcx>, fn_call_span: Span, from_hir_call: bool, self_arg: Option<Ident>, @@ -92,19 +92,19 @@ pub fn call_kind<'tcx>( // an FnOnce call, an operator (e.g. `<<`), or a // deref coercion. let kind = if let Some(trait_id) = fn_call { - Some(CallKind::FnCall { fn_trait_id: trait_id, self_ty: method_substs.type_at(0) }) + Some(CallKind::FnCall { fn_trait_id: trait_id, self_ty: method_args.type_at(0) }) } else if let Some(trait_id) = operator { - Some(CallKind::Operator { self_arg, trait_id, self_ty: method_substs.type_at(0) }) + Some(CallKind::Operator { self_arg, trait_id, self_ty: method_args.type_at(0) }) } else if is_deref { let deref_target = tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| { - Instance::resolve(tcx, param_env, deref_target, method_substs).transpose() + Instance::resolve(tcx, param_env, deref_target, method_args).transpose() }); if let Some(Ok(instance)) = deref_target { let deref_target_ty = instance.ty(tcx, param_env); Some(CallKind::DerefCoercion { deref_target: tcx.def_span(instance.def_id()), deref_target_ty, - self_ty: method_substs.type_at(0), + self_ty: method_args.type_at(0), }) } else { None @@ -119,24 +119,24 @@ pub fn call_kind<'tcx>( let desugaring = if Some(method_did) == tcx.lang_items().into_iter_fn() && fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop) { - Some((CallDesugaringKind::ForLoopIntoIter, method_substs.type_at(0))) + Some((CallDesugaringKind::ForLoopIntoIter, method_args.type_at(0))) } else if fn_call_span.desugaring_kind() == Some(DesugaringKind::QuestionMark) { if Some(method_did) == tcx.lang_items().branch_fn() { - Some((CallDesugaringKind::QuestionBranch, method_substs.type_at(0))) + Some((CallDesugaringKind::QuestionBranch, method_args.type_at(0))) } else if Some(method_did) == tcx.lang_items().from_residual_fn() { - Some((CallDesugaringKind::QuestionFromResidual, method_substs.type_at(0))) + Some((CallDesugaringKind::QuestionFromResidual, method_args.type_at(0))) } else { None } } else if Some(method_did) == tcx.lang_items().from_output_fn() && fn_call_span.desugaring_kind() == Some(DesugaringKind::TryBlock) { - Some((CallDesugaringKind::TryBlockFromOutput, method_substs.type_at(0))) + Some((CallDesugaringKind::TryBlockFromOutput, method_args.type_at(0))) } else if fn_call_span.is_desugaring(DesugaringKind::Await) { - Some((CallDesugaringKind::Await, method_substs.type_at(0))) + Some((CallDesugaringKind::Await, method_args.type_at(0))) } else { None }; - CallKind::Normal { self_arg, desugaring, method_did, method_substs } + CallKind::Normal { self_arg, desugaring, method_did, method_args } }) } diff --git a/compiler/rustc_middle/src/util/find_self_call.rs b/compiler/rustc_middle/src/util/find_self_call.rs index 0eab0adf07e..1b845334c49 100644 --- a/compiler/rustc_middle/src/util/find_self_call.rs +++ b/compiler/rustc_middle/src/util/find_self_call.rs @@ -1,5 +1,5 @@ use crate::mir::*; -use crate::ty::subst::SubstsRef; +use crate::ty::GenericArgsRef; use crate::ty::{self, TyCtxt}; use rustc_span::def_id::DefId; @@ -11,21 +11,21 @@ pub fn find_self_call<'tcx>( body: &Body<'tcx>, local: Local, block: BasicBlock, -) -> Option<(DefId, SubstsRef<'tcx>)> { +) -> Option<(DefId, GenericArgsRef<'tcx>)> { debug!("find_self_call(local={:?}): terminator={:?}", local, &body[block].terminator); if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) = &body[block].terminator { debug!("find_self_call: func={:?}", func); if let Operand::Constant(box Constant { literal, .. }) = func { - if let ty::FnDef(def_id, substs) = *literal.ty().kind() { + if let ty::FnDef(def_id, fn_args) = *literal.ty().kind() { if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) = tcx.opt_associated_item(def_id) { - debug!("find_self_call: args={:?}", args); + debug!("find_self_call: args={:?}", fn_args); if let [Operand::Move(self_place) | Operand::Copy(self_place), ..] = **args { if self_place.as_local() == Some(local) { - return Some((def_id, substs)); + return Some((def_id, fn_args)); } } } diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index a00c77ccbcd..b0961d91787 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -16,7 +16,7 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for Ty<'_> { fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo<DepKind>]) -> Self { // SAFETY: This is never called when `Self` is not `Ty<'tcx>`. // FIXME: Represent the above fact in the trait system somehow. - unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(tcx.ty_error_misc()) } + unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(Ty::new_misc_error(tcx)) } } } @@ -34,7 +34,7 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::SymbolName<'_> { impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::Binder<'_, ty::FnSig<'_>> { fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo<DepKind>]) -> Self { - let err = tcx.ty_error_misc(); + let err = Ty::new_misc_error(tcx); let arity = if let Some(frame) = stack.get(0) && frame.query.dep_kind == DepKind::fn_sig @@ -106,9 +106,12 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::EarlyBinder<ty::Binder<'_, ty::F } } -impl<'tcx, T> Value<TyCtxt<'tcx>, DepKind> for Result<T, ty::layout::LayoutError<'_>> { +impl<'tcx, T> Value<TyCtxt<'tcx>, DepKind> for Result<T, &'_ ty::layout::LayoutError<'_>> { fn from_cycle_error(_tcx: TyCtxt<'tcx>, _cycle: &[QueryInfo<DepKind>]) -> Self { - Err(ty::layout::LayoutError::Cycle) + // tcx.arena.alloc cannot be used because we are not allowed to use &'tcx LayoutError under + // min_specialization. Since this is an error path anyways, leaking doesn't matter (and really, + // tcx.arena.alloc is pretty much equal to leaking). + Err(Box::leak(Box::new(ty::layout::LayoutError::Cycle))) } } |
