diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index eab067a02b7bf..356d2323aca1f 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -538,7 +538,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( match *in_elem.kind() { ty::RawPtr(p_ty, _) => { - let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { + let metadata = p_ty.ptr_metadata_ty(bx.tcx, &ObligationCause::dummy(), |ty| { bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty) }); require!( @@ -552,7 +552,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } match *out_elem.kind() { ty::RawPtr(p_ty, _) => { - let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { + let metadata = p_ty.ptr_metadata_ty(bx.tcx, &ObligationCause::dummy(), |ty| { bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty) }); require!( diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index cf088ed509092..aa4f35e054438 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -16,6 +16,7 @@ use rustc_hir as hir; use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::find_attr; use rustc_middle::mir::BinOp; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf}; use rustc_middle::ty::offload_meta::OffloadMetadata; use rustc_middle::ty::{self, GenericArgsRef, Instance, SimdAlign, Ty, TyCtxt, TypingEnv}; @@ -2561,7 +2562,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( match in_elem.kind() { ty::RawPtr(p_ty, _) => { - let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { + let metadata = p_ty.ptr_metadata_ty(bx.tcx, &ObligationCause::dummy(), |ty| { bx.tcx.normalize_erasing_regions(bx.typing_env(), ty) }); require!( @@ -2575,7 +2576,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } match out_elem.kind() { ty::RawPtr(p_ty, _) => { - let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { + let metadata = p_ty.ptr_metadata_ty(bx.tcx, &ObligationCause::dummy(), |ty| { bx.tcx.normalize_erasing_regions(bx.typing_env(), ty) }); require!( diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 25458a7cbd116..eea090e4cb715 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -9,6 +9,7 @@ use rustc_data_structures::assert_matches; use rustc_errors::msg; use rustc_hir::def_id::DefId; use rustc_hir::find_attr; +use rustc_infer::traits::ObligationCause; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{self, AdtDef, Instance, Ty, VariantDef}; use rustc_middle::{bug, mir, span_bug}; @@ -221,7 +222,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // to fields, which can yield non-normalized types. So we need to provide a // normalization function. let normalize = |ty| self.tcx.normalize_erasing_regions(self.typing_env, ty); - ty.ptr_metadata_ty(*self.tcx, normalize) + ty.ptr_metadata_ty(*self.tcx, &ObligationCause::dummy(), normalize) }; return interp_ok(meta_ty(caller) == meta_ty(callee)); } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 28671cc36ee9a..3ad7637326acd 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -777,11 +777,9 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( if !remapped_types.contains_key(assoc_item) { remapped_types.insert( *assoc_item, - ty::EarlyBinder::bind(Ty::new_error_with_message( - tcx, - return_span, - "missing synthetic item for RPITIT", - )), + ty::EarlyBinder::bind( + tcx.new_error_with_message(return_span, "missing synthetic item for RPITIT"), + ), ); } } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index a1c8c0150a66e..7d664bf72cd9a 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -257,7 +257,7 @@ pub(crate) fn check_intrinsic_type( { Ty::new_param(tcx, n, name) } else { - Ty::new_error_with_message(tcx, span, "expected param") + tcx.new_error_with_message(span, "expected param") } }; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index f4c7234cd8f83..40b2e2e772eb5 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -342,7 +342,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { if !self.tcx.dcx().has_stashed_diagnostic(span, StashKey::ItemNoType) { self.report_placeholder_type_error(vec![span], vec![]); } - Ty::new_error_with_message(self.tcx(), span, "bad placeholder type") + self.tcx().new_error_with_message(span, "bad placeholder type") } fn ct_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> { @@ -539,7 +539,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i)) { infer_replacements.push((a.span, suggested_ty.to_string())); - return Ty::new_error_with_message(tcx, a.span, suggested_ty.to_string()); + return tcx.new_error_with_message(a.span, suggested_ty.to_string()); } self.lowerer().lower_ty(a) @@ -553,7 +553,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None) { infer_replacements.push((output.span, suggested_ty.to_string())); - Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string()) + tcx.new_error_with_message(output.span, suggested_ty.to_string()) } else { self.lower_ty(output) } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 23df419d06a70..71d7bbff80536 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -34,8 +34,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ return map[&trait_item_def_id]; } Err(_) => { - return ty::EarlyBinder::bind(Ty::new_error_with_message( - tcx, + return ty::EarlyBinder::bind(tcx.new_error_with_message( DUMMY_SP, "Could not collect return position impl trait in trait tys", )); @@ -366,8 +365,7 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx tcx.type_of(field_def_id).instantiate_identity() } - _ => Ty::new_error_with_message( - tcx, + _ => tcx.new_error_with_message( span, format!("unexpected anon const parent in type_of(): {parent_node:?}"), ), @@ -402,8 +400,7 @@ fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: S // This is not a `bug!` as const arguments in path segments that did not resolve to anything // will result in `type_of` never being fed. - _ => Ty::new_error_with_message( - tcx, + _ => tcx.new_error_with_message( span, "`type_of` called on const argument's anon const before the const argument was lowered", ), @@ -427,8 +424,7 @@ fn infer_placeholder_type<'tcx>( if let Some(trait_item_def_id) = tcx.trait_item_of(def_id.to_def_id()) { tcx.type_of(trait_item_def_id).instantiate_identity() } else { - Ty::new_error_with_message( - tcx, + tcx.new_error_with_message( ty_span, "constant with `type const` requires an explicit type", ) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index ca399964fdd93..b18cddec18af3 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -684,11 +684,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let item_def_id = match path.res { Res::Def(DefKind::AssocFn, item_def_id) => item_def_id, Res::Err => { - return Ty::new_error_with_message( - tcx, - hir_ty.span, - "failed to resolve RTN", - ); + return tcx.new_error_with_message(hir_ty.span, "failed to resolve RTN"); } _ => bug!("only expected method resolution for fully qualified RTN"), }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 25911d3e9e462..58c0004cb0ea6 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -765,7 +765,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lowerer.ty_infer(Some(param), self.span).into() } else { // We've already errored above about the mismatch. - Ty::new_misc_error(tcx).into() + tcx.new_misc_error().into() } } GenericParamDefKind::Const { has_default, .. } => { diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 82b7c578a1f25..f73b2ff0ed08d 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -1018,8 +1018,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { })? } ty::Alias(ty::Projection, _) => { - return Some(Ty::new_error_with_message( - self.tcx, + return Some(self.tcx.new_error_with_message( closure_span, "this projection should have been projected to an opaque type", )); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 9f2134e050bc0..12b9e012d474c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -724,8 +724,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(ctxt) => ctxt.coerce.as_ref().map(|coerce| coerce.expected_ty()), None => { // Avoid ICE when `break` is inside a closure (#65383). - return Ty::new_error_with_message( - tcx, + return tcx.new_error_with_message( expr.span, "break was outside loop, but no error was emitted", ); @@ -762,8 +761,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); let Some(ctxt) = enclosing_breakables.opt_find_breakable(target_id) else { // Avoid ICE when `break` is inside a closure (#65383). - return Ty::new_error_with_message( - tcx, + return tcx.new_error_with_message( expr.span, "break was outside loop, but no error was emitted", ); @@ -823,8 +821,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // this can only happen if the `break` was not // inside a loop at all, which is caught by the // loop-checking pass. - let err = Ty::new_error_with_message( - self.tcx, + let err = self.tcx.new_error_with_message( expr.span, "break was outside loop, but no error was emitted", ); @@ -871,7 +868,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } else { // There was an error; make type-check fail. - Ty::new_misc_error(self.tcx) + self.tcx.new_misc_error() } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 967f255361b59..81df31befc4b0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2959,7 +2959,7 @@ impl<'a, 'b, 'tcx> ArgsCtxt<'a, 'b, 'tcx> { .typeck_results .borrow() .expr_ty_adjusted_opt(expr) - .unwrap_or_else(|| Ty::new_misc_error(self.call_ctxt.fn_ctxt.tcx)); + .unwrap_or_else(|| self.call_ctxt.fn_ctxt.tcx.new_misc_error()); ( self.call_ctxt.fn_ctxt.resolve_vars_if_possible(ty), self.normalize_span(expr.span), diff --git a/compiler/rustc_hir_typeck/src/inline_asm.rs b/compiler/rustc_hir_typeck/src/inline_asm.rs index 7c1655f8201d7..30ea6354635fc 100644 --- a/compiler/rustc_hir_typeck/src/inline_asm.rs +++ b/compiler/rustc_hir_typeck/src/inline_asm.rs @@ -43,7 +43,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { let ty = self.fcx.typeck_results.borrow().expr_ty_adjusted(expr); let ty = self.fcx.try_structurally_resolve_type(expr.span, ty); if ty.has_non_region_infer() { - Ty::new_misc_error(self.tcx()) + self.tcx().new_misc_error() } else { self.tcx().erase_and_anonymize_regions(ty) } diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index 7567f8ba34883..b01ed23fe6c1e 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -81,8 +81,7 @@ fn check_transmute<'tcx>( if let Ok(ty) = tcx.try_normalize_erasing_regions(typing_env, ty) { ty } else { - Ty::new_error_with_message( - tcx, + tcx.new_error_with_message( span(), format!("tried to normalize non-wf type {ty:#?} in check_transmute"), ) diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 608bc7dffd9c0..a773786832b0d 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -179,11 +179,9 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // time writing the results into the various typeck results. let mut autoderef = self.autoderef(self.call_expr.span, unadjusted_self_ty); let Some((mut target, n)) = autoderef.nth(pick.autoderefs) else { - return Ty::new_error_with_message( - self.tcx, - DUMMY_SP, - format!("failed autoderef {}", pick.autoderefs), - ); + return self + .tcx + .new_error_with_message(DUMMY_SP, format!("failed autoderef {}", pick.autoderefs)); }; assert_eq!(n, pick.autoderefs); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 77f7053689d27..c9dd4b85c6e7a 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2131,7 +2131,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results .borrow() .expr_ty_adjusted_opt(rcvr_expr) - .unwrap_or(Ty::new_misc_error(self.tcx)), + .unwrap_or(self.new_misc_error()), ); let Ok(candidates) = self.probe_for_name_many( diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index e9d79a2ece2ec..86e376a3532d9 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -299,7 +299,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // error types are considered "builtin" Err(_) if lhs_ty.references_error() || rhs_ty.references_error() => { - Ty::new_misc_error(self.tcx) + self.tcx.new_misc_error() } Err(errors) => { let (_, trait_def_id) = lang_item_for_binop(self.tcx, op); diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index ea4edb3ccf3cd..7a5d02db931c1 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1065,7 +1065,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { demand_eqtype(&mut rhs, lhs); if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) { - return Ty::new_misc_error(self.tcx); + return self.tcx.new_misc_error(); } // Find the unified type and check if it's of numeric or char type again. @@ -2053,7 +2053,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .unwrap_or_else(|| { inexistent_fields.push(field); - Ty::new_misc_error(tcx) + tcx.new_misc_error() }) } }; diff --git a/compiler/rustc_lint/src/gpukernel_abi.rs b/compiler/rustc_lint/src/gpukernel_abi.rs index 4fb26739cd28a..30508ea7077ec 100644 --- a/compiler/rustc_lint/src/gpukernel_abi.rs +++ b/compiler/rustc_lint/src/gpukernel_abi.rs @@ -2,6 +2,7 @@ use std::iter; use rustc_abi::ExternAbi; use rustc_hir::{self as hir, find_attr}; +use rustc_infer::traits::ObligationCause; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::Span; @@ -109,7 +110,10 @@ impl<'tcx> TypeFolder> for CheckGpuKernelTypes<'tcx> { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => {} // Thin pointers are allowed but fat pointers with metadata are not ty::RawPtr(_, _) => { - if !ty.pointee_metadata_ty_or_projection(self.tcx).is_unit() { + if !ty + .pointee_metadata_ty_or_projection(&ObligationCause::dummy(), self.tcx) + .is_unit() + { self.has_invalid = true; } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 2fa8e19984b4c..da22a9f1d1e1a 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -387,6 +387,8 @@ impl<'a> BlobDecodeContext<'a> { } impl<'a, 'tcx> TyDecoder<'tcx> for MetadataDecodeContext<'a, 'tcx> { + type Interner = TyCtxt<'tcx>; + const CLEAR_CROSS_CRATE: bool = true; #[inline] diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 885fa891892e6..a69df197ed7ca 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -369,6 +369,8 @@ impl<'a, 'tcx> Encodable> for [u8] { } impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> { + type Interner = TyCtxt<'tcx>; + const CLEAR_CROSS_CRATE: bool = true; fn position(&self) -> usize { diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs index a0e4c288c4a85..c934bfbe806d8 100644 --- a/compiler/rustc_middle/src/middle/lang_items.rs +++ b/compiler/rustc_middle/src/middle/lang_items.rs @@ -12,7 +12,7 @@ use rustc_hir::def_id::DefId; use rustc_span::Span; use rustc_target::spec::PanicStrategy; -use crate::ty::{self, TyCtxt}; +use crate::ty::{self, AdtDef, TyCtxt}; impl<'tcx> TyCtxt<'tcx> { /// Returns the `DefId` for a given `LangItem`. @@ -27,6 +27,10 @@ impl<'tcx> TyCtxt<'tcx> { self.lang_items().get(lang_item) == Some(def_id) } + pub fn is_c_void(self, adt: ty::AdtDef<'tcx>) -> bool { + self.is_lang_item(adt.did(), LangItem::CVoid) + } + pub fn as_lang_item(self, def_id: DefId) -> Option { self.lang_items().from_def_id(def_id) } diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index de3ef6deca1fc..4598027f87fd4 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -94,10 +94,6 @@ impl ConstValue { self.try_to_scalar_int()?.try_into().ok() } - pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Option { - Some(self.try_to_scalar_int()?.to_target_usize(tcx)) - } - pub fn try_to_bits_for_ty<'tcx>( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 48dcef298d66a..9beca36256f14 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -6,6 +6,7 @@ use tracing::{debug, instrument}; use super::interpret::GlobalAlloc; use super::*; +use crate::traits::ObligationCause; use crate::ty::CoroutineArgsExt; /////////////////////////////////////////////////////////////////////////// @@ -870,7 +871,9 @@ impl<'tcx> UnOp { pub fn ty(&self, tcx: TyCtxt<'tcx>, arg_ty: Ty<'tcx>) -> Ty<'tcx> { match self { UnOp::Not | UnOp::Neg => arg_ty, - UnOp::PtrMetadata => arg_ty.pointee_metadata_ty_or_projection(tcx), + UnOp::PtrMetadata => { + arg_ty.pointee_metadata_ty_or_projection(&ObligationCause::dummy(), tcx) + } } } } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 54b72c5b6714b..0ef9046fa26f3 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -9,6 +9,7 @@ use rustc_data_structures::stable_hasher::HashStable; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId}; use rustc_hir::hir_id::OwnerId; use rustc_span::{DUMMY_SP, Ident, LocalExpnId, Span, Symbol}; +use rustc_type_ir::inherent::IntoKind; use crate::dep_graph::DepNodeIndex; use crate::ich::StableHashingContext; @@ -267,7 +268,7 @@ impl<'tcx> QueryKey for Ty<'tcx> { } fn def_id_for_ty_in_cycle(&self) -> Option { - match *self.kind() { + match self.kind() { ty::Adt(adt, _) => Some(adt.did()), ty::Coroutine(def_id, ..) => Some(def_id), _ => None, diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 8db48fc2f9956..a3961fea4e45e 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -27,7 +27,7 @@ use crate::dep_graph::{DepNodeIndex, QuerySideEffect, SerializedDepNodeIndex}; use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use crate::mir::mono::MonoItem; use crate::mir::{self, interpret}; -use crate::ty::codec::{RefDecodable, TyDecoder, TyEncoder}; +use crate::ty::codec::{RefDecodable, TyEncoder}; use crate::ty::{self, Ty, TyCtxt}; const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE; @@ -525,7 +525,7 @@ where value } -impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> { +impl<'a, 'tcx> rustc_middle::ty::codec::TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> { const CLEAR_CROSS_CRATE: bool = false; #[inline] @@ -969,7 +969,7 @@ impl<'a, 'tcx> SpanEncoder for CacheEncoder<'a, 'tcx> { } } -impl<'a, 'tcx> TyEncoder<'tcx> for CacheEncoder<'a, 'tcx> { +impl<'a, 'tcx> rustc_middle::ty::codec::TyEncoder<'tcx> for CacheEncoder<'a, 'tcx> { const CLEAR_CROSS_CRATE: bool = false; #[inline] diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 6a51ea4deffee..a682d37d7506a 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -264,6 +264,22 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef> for AdtDef<'tcx> { self.repr().packed() } + fn is_box(self) -> bool { + self.is_box() + } + + fn is_pin(self) -> bool { + self.is_pin() + } + + fn is_enum(self) -> bool { + self.is_enum() + } + + fn is_union(self) -> bool { + self.is_union() + } + fn struct_tail_ty(self, interner: TyCtxt<'tcx>) -> Option>> { Some(interner.type_of(self.non_enum_variant().tail_opt()?.did)) } @@ -284,6 +300,10 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef> for AdtDef<'tcx> { self.field_representing_type_info(tcx, args) } + fn has_unsafe_fields(self) -> bool { + self.all_fields().any(|field| field.safety.is_unsafe()) + } + fn all_field_tys( self, tcx: TyCtxt<'tcx>, @@ -311,6 +331,36 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef> for AdtDef<'tcx> { hir::Constness::NotConst => AdtDestructorKind::NotConst, }) } + + /// Asserts this is a struct or union and returns its unique variant. + fn non_enum_variant(self) -> &'tcx VariantDef { + assert!(self.is_struct() || self.is_union()); + self.variant(FIRST_VARIANT) + } + + fn repr_is_simd(self) -> bool { + self.0.0.repr.simd() + } + + fn scalable_element_cnt(self) -> Option { + if let Some(ty::ScalableElt::ElementCount(element_count)) = self.repr().scalable { + Some(element_count) + } else { + None + } + } + + fn discriminant_for_variant(self, tcx: TyCtxt<'tcx>, variant_index: VariantIdx) -> Discr<'tcx> { + self.discriminant_for_variant(tcx, variant_index) + } + + fn variant_range(self) -> Range { + self.variant_range() + } + + fn repr_discr_type_to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + self.repr().discr_type().to_ty(tcx) + } } #[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)] @@ -522,12 +572,6 @@ impl<'tcx> AdtDef<'tcx> { self.destructor(tcx).is_some() } - /// Asserts this is a struct or union and returns its unique variant. - pub fn non_enum_variant(self) -> &'tcx VariantDef { - assert!(self.is_struct() || self.is_union()); - self.variant(FIRST_VARIANT) - } - #[inline] pub fn predicates(self, tcx: TyCtxt<'tcx>) -> GenericPredicates<'tcx> { tcx.predicates_of(self.did()) diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index aade274bfc98c..7ad08b537f1c0 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -148,7 +148,7 @@ impl<'tcx> Const<'tcx> { ) } - /// Like [Ty::new_error_with_message] but for constants. + /// Like [Interner.new_error_with_message] but for constants. #[track_caller] pub fn new_error_with_message>( tcx: TyCtxt<'tcx>, @@ -213,6 +213,16 @@ impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { fn new_error(interner: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self { Const::new_error(interner, guar) } + + fn try_to_target_usize(&self, tcx: TyCtxt<'tcx>) -> Option { + Some(self.try_to_scalar_int()?.to_target_usize(tcx)) + } + + #[inline] + /// Creates an interned usize constant. + fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self { + Self::from_bits(tcx, n as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.usize) + } } impl<'tcx> Const<'tcx> { @@ -247,12 +257,6 @@ impl<'tcx> Const<'tcx> { Self::from_bits(tcx, v as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.bool) } - #[inline] - /// Creates an interned usize constant. - pub fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self { - Self::from_bits(tcx, n as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.usize) - } - /// Panics if `self.kind != ty::ConstKind::Value`. pub fn to_value(self) -> ty::Value<'tcx> { match self.kind() { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 68819445a06c4..050cb3bb6b000 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -209,7 +209,7 @@ impl<'tcx> CtxtInterners<'tcx> { #[allow(rustc::usage_of_ty_tykind)] #[inline(never)] fn intern_ty(&self, kind: TyKind<'tcx>, sess: &Session, untracked: &Untracked) -> Ty<'tcx> { - Ty(Interned::new_unchecked( + Ty::from_interned(Interned::new_unchecked( self.type_ .intern(kind, |kind| { let flags = ty::FlagComputation::>::for_kind(&kind); @@ -1100,10 +1100,6 @@ impl<'tcx> TyCtxt<'tcx> { self.coroutine_kind(def_id).is_some() } - pub fn is_async_drop_in_place_coroutine(self, def_id: DefId) -> bool { - self.is_lang_item(self.parent(def_id), LangItem::AsyncDropInPlace) - } - pub fn type_const_span(self, def_id: DefId) -> Option { if !self.is_type_const(def_id) { return None; diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index a6b3f29d7ec23..02e57bb6215a2 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -1,9 +1,11 @@ //! Implementation of [`rustc_type_ir::Interner`] for [`TyCtxt`]. use std::fmt; +use std::ops::Range; -use rustc_abi::ExternAbi; +use rustc_abi::{ExternAbi, FieldIdx, VariantIdx}; use rustc_data_structures::debug_assert_matches; +use rustc_data_structures::intern::Interned; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind}; @@ -11,18 +13,20 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_span::{DUMMY_SP, Span, Symbol}; use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem}; -use rustc_type_ir::{CollectAndApply, Interner, TypeFoldable, search_graph}; +use rustc_type_ir::{CollectAndApply, Interner, TypeFoldable, elaborate, search_graph}; use crate::dep_graph::{DepKind, DepNodeIndex}; use crate::infer::canonical::CanonicalVarKinds; use crate::query::IntoQueryParam; +use crate::traits::ObligationCause; use crate::traits::cache::WithDepNode; use crate::traits::solve::{ self, CanonicalInput, ExternalConstraints, ExternalConstraintsData, QueryResult, inspect, }; +use crate::ty::util::Discr; use crate::ty::{ - self, Clause, Const, List, ParamTy, Pattern, PolyExistentialPredicate, Predicate, Region, Ty, - TyCtxt, + self, Clause, Const, GenericArgs, List, ParamTy, Pattern, PolyExistentialPredicate, Predicate, + Region, Ty, TyCtxt, VariantDef, }; #[allow(rustc::usage_of_ty_tykind)] @@ -40,12 +44,19 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type CoroutineClosureId = DefId; type CoroutineId = DefId; type AdtId = DefId; + type VariantDef = VariantDef; type ImplId = DefId; type UnevaluatedConstId = DefId; type Span = Span; - - type GenericArgs = ty::GenericArgsRef<'tcx>; - + type Interned = + Interned<'tcx, T>; + type VariantIdx = VariantIdx; + type Discr = Discr<'tcx>; + type ObligationCause = ObligationCause<'tcx>; + type LangItem = LangItem; + + type GenericArgs = ty::GenericArgs<'tcx>; + type GenericArgsRef: ty::GenericArgsRef; type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>]; type GenericArg = ty::GenericArg<'tcx>; type Term = ty::Term<'tcx>; @@ -79,7 +90,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { fn with_cached_task(self, task: impl FnOnce() -> T) -> (T, DepNodeIndex) { self.dep_graph.with_anon_task(self, DepKind::TraitSelect, task) } - type Ty = Ty<'tcx>; type Tys = &'tcx List>; type FnInputTys = &'tcx [Ty<'tcx>]; @@ -264,6 +274,94 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.debug_assert_args_compatible(def_id, args); } + fn debug_assert_adt_def_compatible(self, def: ty::AdtDef<'tcx>) { + if cfg!(debug_assertions) { + match self.def_kind(def.did()) { + DefKind::Struct | DefKind::Union | DefKind::Enum => {} + DefKind::Mod + | DefKind::Variant + | DefKind::Trait + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::TyParam + | DefKind::Fn + | DefKind::Const { .. } + | DefKind::ConstParam + | DefKind::Static { .. } + | DefKind::Ctor(..) + | DefKind::AssocFn + | DefKind::AssocConst { .. } + | DefKind::Macro(..) + | DefKind::ExternCrate + | DefKind::Use + | DefKind::ForeignMod + | DefKind::AnonConst + | DefKind::InlineConst + | DefKind::OpaqueTy + | DefKind::Field + | DefKind::LifetimeParam + | DefKind::GlobalAsm + | DefKind::Impl { .. } + | DefKind::Closure + | DefKind::SyntheticCoroutineBody => { + bug!("not an adt: {def:?} ({:?})", self.def_kind(def.did())) + } + } + } + } + + /// Given the `DefId`, returns the `DefId` of the innermost item that + /// has its own type-checking context or "inference environment". + /// + /// For example, a closure has its own `DefId`, but it is type-checked + /// with the containing item. Therefore, when we fetch the `typeck` of the closure, + /// for example, we really wind up fetching the `typeck` of the enclosing fn item. + fn typeck_root_def_id(self, def_id: DefId) -> DefId { + let mut def_id = def_id; + while self.is_typeck_child(def_id) { + def_id = self.parent(def_id); + } + def_id + } + + fn debug_assert_new_dynamic_compatible( + self, + obj: &'tcx List>, + ) { + if cfg!(debug_assertions) { + let projection_count = obj + .projection_bounds() + .filter(|item| !self.generics_require_sized_self(item.item_def_id())) + .count(); + let expected_count: usize = obj + .principal_def_id() + .into_iter() + .flat_map(|principal_def_id| { + // IMPORTANT: This has to agree with HIR ty lowering of dyn trait! + elaborate::supertraits( + self, + ty::Binder::dummy(ty::TraitRef::identity(self, principal_def_id)), + ) + .map(|principal| { + self.associated_items(principal.def_id()) + .in_definition_order() + .filter(|item| item.is_type() || item.is_const()) + .filter(|item| !item.is_impl_trait_in_trait()) + .filter(|item| !self.generics_require_sized_self(item.def_id)) + .count() + }) + }) + .sum(); + assert_eq!( + projection_count, expected_count, + "expected {obj:?} to have {expected_count} projections, \ + but it has {projection_count}" + ); + } + } + /// Assert that the args from an `ExistentialTraitRef` or `ExistentialProjection` /// are compatible with the `DefId`. Since we're missing a `Self` type, stick on /// a dummy self type and forward to `debug_assert_args_compatible`. @@ -292,6 +390,22 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.mk_type_list_from_iter(args) } + fn mk_ty_from_kind(self, kind: ty::TyKind<'tcx>) -> Ty<'tcx> { + self.mk_ty_from_kind(kind) + } + + fn mk_coroutine_witness_for_coroutine( + self, + def_id: DefId, + args: Self::GenericArgs, + ) -> Ty<'tcx> { + Ty::new_coroutine_witness_for_coroutine(self, def_id, args) + } + + fn ty_discriminant_ty(self, ty: Ty<'tcx>) -> Ty<'tcx> { + ty.discriminant_ty(self) + } + fn parent(self, def_id: DefId) -> DefId { self.parent(def_id) } @@ -449,6 +563,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.is_lang_item(def_id, solver_lang_item_to_lang_item(lang_item)) } + fn is_c_void(self, adt: ty::AdtDef<'tcx>) -> bool { + self.is_c_void(adt) + } + fn is_trait_lang_item(self, def_id: DefId, lang_item: SolverTraitLangItem) -> bool { self.is_lang_item(def_id, solver_trait_lang_item_to_lang_item(lang_item)) } @@ -720,6 +838,211 @@ impl<'tcx> Interner for TyCtxt<'tcx> { bug!("item_name: no name for {:?}", self.def_path(id)); }) } + + #[inline] + fn i8_type(self) -> Ty<'tcx> { + self.types.i8 + } + + #[inline] + fn i16_type(self) -> Ty<'tcx> { + self.types.i16 + } + + #[inline] + fn i32_type(self) -> Ty<'tcx> { + self.types.i32 + } + + #[inline] + fn u8_type(self) -> Ty<'tcx> { + self.types.u8 + } + + #[inline] + fn usize_type(self) -> Ty<'tcx> { + self.types.usize + } + + #[inline] + fn unit_type(self) -> Ty<'tcx> { + self.types.unit + } + + fn is_async_drop_in_place_coroutine(self, def_id: DefId) -> bool { + self.is_lang_item(self.parent(def_id), LangItem::AsyncDropInPlace) + } + + #[inline] + fn coroutine_variant_range( + self, + def_id: DefId, + coroutine_args: ty::CoroutineArgs, + ) -> Range { + self.coroutine_variant_range(def_id, coroutine_args) + } + + fn struct_tail_raw( + self, + mut ty: Ty<'tcx>, + cause: &ObligationCause<'tcx>, + mut normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, + mut f: impl FnMut() -> (), + ) -> Ty<'tcx> { + self.struct_tail_raw(ty, cause, normalize, f) + } + + fn get_ty_var(self, id: usize) -> Option> { + self.types.ty_vars.get(id).copied() + } + + fn get_fresh_ty(self, id: usize) -> Option> { + self.types.fresh_tys.get(id).copied() + } + + fn get_fresh_ty_int(self, id: usize) -> Option> { + self.types.fresh_int_tys.get(id).copied() + } + + fn get_fresh_ty_float(self, id: usize) -> Option> { + self.types.fresh_float_tys.get(id).copied() + } + + fn get_anon_bound_ty(self, id: usize) -> Option>> { + self.types.anon_bound_tys.get(id).copied() + } + + fn get_anon_canonical_bound_ty(self, id: usize) -> Option> { + self.types.anon_canonical_bound_tys.get(id.as_usize()).copied() + } + + fn get_generic_args_for_item(self, def_id: DefId) -> ty::GenericArgsRef<'tcx> { + // HACK: Coroutine witness types are lifetime erased, so they + // never reference any lifetime args from the coroutine. We erase + // the regions here since we may get into situations where a + // coroutine is recursively contained within itself, leading to + // witness types that differ by region args. This means that + // cycle detection in fulfillment will not kick in, which leads + // to unnecessary overflows in async code. See the issue: + // . + ty::GenericArgs::for_item(self, self.typeck_root_def_id(def_id), |def, _| match def.kind { + ty::GenericParamDefKind::Lifetime => self.lifetimes.re_erased.into(), + ty::GenericParamDefKind::Type { .. } | ty::GenericParamDefKind::Const { .. } => { + coroutine_args[def.index as usize] + } + }) + } + + fn get_generic_adt_args( + self, + wrapper_def_id: DefId, + ty_param: Ty<'tcx>, + ) -> ty::GenericArgsRef<'tcx> { + 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() + } + } + }) + } + + fn new_static_str(self) -> Ty<'tcx> { + Ty::new_imm_ref(self, self.lifetimes.re_static, self.types.str_) + } + + fn get_lang_item(self, item: LangItem) -> Option { + self.lang_items().get(item) + } + + fn get_diagnostic_item(self, name: Symbol) -> Option { + self.get_diagnostic_item(name) + } + + fn require_lang_item_owned_box(self) -> DefId { + self.require_lang_item(LangItem::OwnedBox, DUMMY_SP) + } + + fn require_lang_item_option(self) -> DefId { + self.require_lang_item(LangItem::Option, DUMMY_SP) + } + + fn require_lang_item_maybe_uninit(self) -> DefId { + self.require_lang_item(LangItem::MaybeUninit, DUMMY_SP) + } + + fn require_lang_item_pin(self) -> DefId { + self.require_lang_item(LangItem::Pin, DUMMY_SP) + } + + fn require_lang_item_context(self) -> DefId { + self.require_lang_item(LangItem::Context, DUMMY_SP) + } + + fn new_field_representing_type( + self, + base: Ty<'tcx>, + variant: VariantIdx, + field: FieldIdx, + ) -> Ty<'tcx> { + let Some(did) = self.lang_items().field_representing_type() else { + bug!("could not locate the `FieldRepresentingType` lang item") + }; + let def = self.adt_def(did); + let args = self.mk_args(&[ + base.into(), + Const::new_value( + self, + ty::ValTree::from_scalar_int(self, variant.as_u32().into()), + self.types.u32, + ) + .into(), + Const::new_value( + self, + ty::ValTree::from_scalar_int(self, field.as_u32().into()), + self.types.u32, + ) + .into(), + ]); + Ty::new_adt(self, def, args) + } + + fn get_re_erased_region(self) -> Region { + self.lifetimes.re_erased + } + + fn new_generic_adt(self, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> { + let adt_def = self.adt_def(wrapper_def_id); + let args = GenericArgs::for_item(self, 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); + self.type_of(param.def_id).instantiate(tcx, args).into() + } + } + }); + Ty::new_adt(self, adt_def, args) + } + + fn new_pinned_ref(self, r: Region<'tcx>, ty: Ty<'tcx>, mutbl: ty::Mutability) -> Ty<'tcx> { + let pin = self.adt_def(self.require_lang_item(LangItem::Pin, DUMMY_SP)); + Ty::new_adt(tcx, pin, self.mk_args(&[Ty::new_ref(tcx, r, ty, mutbl).into()])) + } + + fn new_task_context(self) -> Ty<'tcx> { + let context_did = self.require_lang_item(LangItem::Context, DUMMY_SP); + let context_adt_ref = self.adt_def(context_did); + let context_args = self.mk_args(&[self.lifetimes.re_erased.into()]); + let context_ty = Ty::new_adt(tcx, context_adt_ref, context_args); + Ty::new_mut_ref(tcx, self.lifetimes.re_erased, context_ty) + } } /// Defines trivial conversion functions between the main [`LangItem`] enum, @@ -758,6 +1081,7 @@ bidirectional_lang_item_map! { FieldBase, FieldType, FutureOutput, + GlobalAlloc, Metadata, // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 329a7b99e15b7..1efd2206c30fd 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -19,15 +19,6 @@ use crate::ty::{ TypeSuperVisitable, TypeVisitable, TypeVisitor, }; -impl IntoDiagArg for Ty<'_> { - fn into_diag_arg(self, path: &mut Option) -> rustc_errors::DiagArgValue { - ty::tls::with(|tcx| { - let ty = tcx.short_string(self, path); - DiagArgValue::Str(std::borrow::Cow::Owned(ty)) - }) - } -} - impl IntoDiagArg for Instance<'_> { fn into_diag_arg(self, path: &mut Option) -> rustc_errors::DiagArgValue { ty::tls::with(|tcx| { diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 3ade3a3ef51e8..bae1687ea9540 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -5,6 +5,7 @@ use std::marker::PhantomData; use std::num::NonZero; use std::ptr::NonNull; +use rustc_abi::VariantIdx; use rustc_data_structures::intern::Interned; use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_hir::def_id::DefId; @@ -15,6 +16,7 @@ use rustc_type_ir::walk::TypeWalker; use smallvec::SmallVec; use crate::ty::codec::{TyDecoder, TyEncoder}; +use crate::ty::util::Discr; use crate::ty::{ self, ClosureArgs, CoroutineArgs, CoroutineClosureArgs, FallibleTypeFolder, InlineConstArgs, Lift, List, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, VisitorResult, @@ -122,6 +124,19 @@ impl<'tcx> rustc_type_ir::inherent::GenericArgs> for ty::GenericArg _ => bug!("coroutine args missing synthetics"), } } + + fn coroutine_discriminant_for_variant( + self, + def_id: DefId, + tcx: TyCtxt<'tcx>, + variant_index: VariantIdx, + ) -> Discr<'tcx> { + self.as_coroutine().discriminant_for_variant(def_id, tcx, variant_index) + } + + fn as_coroutine_discr_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + self.as_coroutine().discr_ty(tcx) + } } impl<'tcx> rustc_type_ir::inherent::IntoKind for GenericArg<'tcx> { @@ -229,7 +244,7 @@ impl<'tcx> GenericArg<'tcx> { REGION_TAG => GenericArgKind::Lifetime(ty::Region(Interned::new_unchecked( ptr.cast::>().as_ref(), ))), - TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked( + TYPE_TAG => GenericArgKind::Type(Ty::from_interned(Interned::new_unchecked( ptr.cast::>>().as_ref(), ))), CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index ed587cbc3c285..4dc437f44856c 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -5,7 +5,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::{Span, Symbol, kw}; use tracing::instrument; -use super::{Clause, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt}; +use super::{Clause, InstantiatedPredicates, ParamConst, ParamTy, TyCtxt}; use crate::ty; use crate::ty::{EarlyBinder, GenericArgsRef}; @@ -96,7 +96,7 @@ impl GenericParamDef { pub fn to_error<'tcx>(&self, tcx: TyCtxt<'tcx>) -> ty::GenericArg<'tcx> { match &self.kind { ty::GenericParamDefKind::Lifetime => ty::Region::new_error_misc(tcx).into(), - ty::GenericParamDefKind::Type { .. } => Ty::new_misc_error(tcx).into(), + ty::GenericParamDefKind::Type { .. } => tcx.new_misc_error().into(), ty::GenericParamDefKind::Const { .. } => ty::Const::new_misc_error(tcx).into(), } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index de0b26ede0e06..04c78fc190adc 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -423,8 +423,7 @@ impl<'tcx> SizeSkeleton<'tcx> { &ObligationCause::dummy(), |ty| match tcx.try_normalize_erasing_regions(typing_env, ty) { Ok(ty) => ty, - Err(e) => Ty::new_error_with_message( - tcx, + Err(e) => tcx.new_error_with_message( DUMMY_SP, format!( "normalization failed for {} but no errors reported", diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9a78b35488503..b3ba7b67aed93 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -11,10 +11,12 @@ #![allow(rustc::usage_of_ty_tykind)] +use std::borrow::Cow; use std::fmt::Debug; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::num::NonZero; +use std::ops::Range; use std::ptr::NonNull; use std::{fmt, iter, str}; @@ -36,7 +38,7 @@ use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; use rustc_data_structures::unord::{UnordMap, UnordSet}; -use rustc_errors::{Diag, ErrorGuaranteed, LintBuffer}; +use rustc_errors::{Diag, ErrorGuaranteed, LintBuffer, MultiSpan}; use rustc_hir::attrs::StrippedCfgItem; use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; @@ -61,6 +63,7 @@ pub use rustc_type_ir::fast_reject::DeepRejectCtxt; rustc::non_glob_import_of_type_ir_inherent )] use rustc_type_ir::inherent; +use rustc_type_ir::inherent::IntoKind; pub use rustc_type_ir::relate::VarianceDiagInfo; pub use rustc_type_ir::solve::{CandidatePreferenceMode, SizedTraitKind}; pub use rustc_type_ir::*; @@ -105,7 +108,7 @@ pub use self::sty::{ AliasTy, Article, Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PlaceholderConst, PlaceholderRegion, - PlaceholderType, PolyFnSig, TyKind, TypeAndMut, TypingMode, UpvarArgs, + PlaceholderType, PolyFnSig, Ty, TyKind, TypeAndMut, TypingMode, UpvarArgs, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ @@ -453,29 +456,11 @@ pub struct CReaderCacheKey { pub pos: usize, } -/// Use this rather than `TyKind`, whenever possible. -#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)] -#[rustc_diagnostic_item = "Ty"] -#[rustc_pass_by_value] -pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); - -impl<'tcx> rustc_type_ir::inherent::IntoKind for Ty<'tcx> { - type Kind = TyKind<'tcx>; - - fn kind(self) -> TyKind<'tcx> { - *self.kind() - } -} - -impl<'tcx> rustc_type_ir::Flags for Ty<'tcx> { - fn flags(&self) -> TypeFlags { - self.0.flags - } - - fn outer_exclusive_binder(&self) -> DebruijnIndex { - self.0.outer_exclusive_binder - } -} +///// Use this rather than `TyKind`, whenever possible. +//#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)] +//#[rustc_diagnostic_item = "Ty"] +//#[rustc_pass_by_value] +//pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); /// The crate outlives map is computed during typeck and contains the /// outlives of every item in the local crate. You should not use it @@ -596,7 +581,7 @@ impl<'tcx> Term<'tcx> { // and this is just going in the other direction. unsafe { match self.ptr.addr().get() & TAG_MASK { - TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked( + TYPE_TAG => TermKind::Ty(Ty::from_interned(Interned::new_unchecked( ptr.cast::>>().as_ref(), ))), CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( @@ -632,7 +617,7 @@ impl<'tcx> Term<'tcx> { pub fn to_alias_term(self) -> Option> { match self.kind() { - TermKind::Ty(ty) => match *ty.kind() { + TermKind::Ty(ty) => match ty.kind() { ty::Alias(_kind, alias_ty) => Some(alias_ty.into()), _ => None, }, @@ -1257,6 +1242,16 @@ impl VariantDef { } } +impl<'tcx> rustc_type_ir::inherent::VariantDef for VariantDef { + fn field_zero_ty(self, tcx: TyCtxt<'tcx>, args: ty::GenericArgs<'tcx>) -> Ty<'tcx> { + self.fields[FieldIdx::ZERO].ty(tcx, args) + } + + fn fields_len(self) -> usize { + self.fields.len() + } +} + impl PartialEq for VariantDef { #[inline] fn eq(&self, other: &Self) -> bool { @@ -2197,6 +2192,32 @@ impl<'tcx> TyCtxt<'tcx> { self.fn_abi_of_instance_no_deduced_attrs(query) } } + + /// The valid variant indices of this coroutine. + #[inline] + pub fn coroutine_variant_range( + self, + def_id: DefId, + coroutine_args: ty::CoroutineArgs, + ) -> Range { + // FIXME requires optimized MIR + rustc_abi::FIRST_VARIANT + ..self.coroutine_layout(def_id, coroutine_args).unwrap().variant_fields.next_index() + } + + pub fn new_error_with_message>( + self, + span: S, + msg: impl Into>, + ) -> Ty<'tcx> { + let reported = self.dcx().span_delayed_bug(span, msg); + Ty::new(self, ty::Error(reported)) + } + + /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` to ensure it gets used. + pub fn new_misc_error(self) -> Ty<'tcx> { + self.new_error_with_message(DUMMY_SP, "TyKind::Error constructed but no error reported") + } } pub fn provide(providers: &mut Providers) { @@ -2401,7 +2422,7 @@ fn typetree_from_ty_impl_inner<'tcx>( if ty.is_slice() { if let ty::Slice(element_ty) = ty.kind() { let element_tree = - typetree_from_ty_impl_inner(tcx, *element_ty, depth + 1, visited, false); + typetree_from_ty_impl_inner(tcx, element_ty, depth + 1, visited, false); return element_tree; } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index a34244096d20c..04381a94210ce 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -17,6 +17,7 @@ use rustc_hir::limit::Limit; use rustc_macros::{Lift, extension}; use rustc_session::cstore::{ExternCrate, ExternCrateSource}; use rustc_span::{Ident, RemapPathScopeComponents, Symbol, kw, sym}; +use rustc_type_ir::inherent::{GenericArgs as _, IntoKind as _}; use rustc_type_ir::{FieldInfo, Upcast as _, elaborate}; use smallvec::SmallVec; @@ -1185,7 +1186,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { trait_ref: ty::TraitRef::new( tcx, trait_def_id, - [self_ty, Ty::new_tup(tcx, args)], + [self_ty, ty::Ty::new_tup(tcx, args)], ), }), FxIndexMap::default(), @@ -3103,7 +3104,6 @@ macro_rules! define_print_and_forward_display { forward_display_to_print! { ty::Region<'tcx>, - Ty<'tcx>, &'tcx ty::List>, ty::Const<'tcx> } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 9f2a1187a9ddc..17d7f87eca712 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -3,21 +3,10 @@ use std::iter; pub use rustc_type_ir::relate::*; use crate::ty::error::{ExpectedFound, TypeError}; -use crate::ty::{self as ty, Ty, TyCtxt}; +use crate::ty::{self as ty, TyCtxt}; pub type RelateResult<'tcx, T> = rustc_type_ir::relate::RelateResult, T>; -impl<'tcx> Relate> for Ty<'tcx> { - #[inline] - fn relate>>( - relation: &mut R, - a: Ty<'tcx>, - b: Ty<'tcx>, - ) -> RelateResult<'tcx, Ty<'tcx>> { - relation.tys(a, b) - } -} - impl<'tcx> Relate> for ty::Pattern<'tcx> { #[inline] fn relate>>( diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 8707b03e4b8f2..7477ad3b75ef6 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -86,12 +86,6 @@ impl fmt::Debug for ty::LateParamRegionKind { } } -impl<'tcx> fmt::Debug for Ty<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - with_no_trimmed_paths!(fmt::Debug::fmt(self.kind(), f)) - } -} - impl fmt::Debug for ty::ParamTy { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}/#{}", self.name, self.index) @@ -327,165 +321,6 @@ impl<'tcx> TypeVisitable> for Pattern<'tcx> { } } -impl<'tcx> TypeFoldable> for Ty<'tcx> { - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - folder.try_fold_ty(self) - } - - fn fold_with>>(self, folder: &mut F) -> Self { - folder.fold_ty(self) - } -} - -impl<'tcx> TypeVisitable> for Ty<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> V::Result { - visitor.visit_ty(*self) - } -} - -impl<'tcx> TypeSuperFoldable> for Ty<'tcx> { - fn try_super_fold_with>>( - self, - folder: &mut F, - ) -> Result { - let kind = match *self.kind() { - ty::RawPtr(ty, mutbl) => ty::RawPtr(ty.try_fold_with(folder)?, mutbl), - 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, args) => ty::Adt(tid, args.try_fold_with(folder)?), - ty::Dynamic(trait_ty, region) => { - ty::Dynamic(trait_ty.try_fold_with(folder)?, region.try_fold_with(folder)?) - } - ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?), - ty::FnDef(def_id, args) => ty::FnDef(def_id, args.try_fold_with(folder)?), - ty::FnPtr(sig_tys, hdr) => ty::FnPtr(sig_tys.try_fold_with(folder)?, hdr), - ty::UnsafeBinder(f) => ty::UnsafeBinder(f.try_fold_with(folder)?), - ty::Ref(r, ty, mutbl) => { - ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl) - } - ty::Coroutine(did, args) => ty::Coroutine(did, args.try_fold_with(folder)?), - ty::CoroutineWitness(did, args) => { - ty::CoroutineWitness(did, args.try_fold_with(folder)?) - } - ty::Closure(did, args) => ty::Closure(did, args.try_fold_with(folder)?), - ty::CoroutineClosure(did, args) => { - ty::CoroutineClosure(did, args.try_fold_with(folder)?) - } - ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?), - ty::Pat(ty, pat) => ty::Pat(ty.try_fold_with(folder)?, pat.try_fold_with(folder)?), - - ty::Bool - | ty::Char - | ty::Str - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Error(_) - | ty::Infer(_) - | ty::Param(..) - | ty::Bound(..) - | ty::Placeholder(..) - | ty::Never - | ty::Foreign(..) => return Ok(self), - }; - - Ok(if *self.kind() == kind { self } else { folder.cx().mk_ty_from_kind(kind) }) - } - - fn super_fold_with>>(self, folder: &mut F) -> Self { - let kind = match *self.kind() { - ty::RawPtr(ty, mutbl) => ty::RawPtr(ty.fold_with(folder), mutbl), - ty::Array(typ, sz) => ty::Array(typ.fold_with(folder), sz.fold_with(folder)), - ty::Slice(typ) => ty::Slice(typ.fold_with(folder)), - ty::Adt(tid, args) => ty::Adt(tid, args.fold_with(folder)), - ty::Dynamic(trait_ty, region) => { - ty::Dynamic(trait_ty.fold_with(folder), region.fold_with(folder)) - } - ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)), - ty::FnDef(def_id, args) => ty::FnDef(def_id, args.fold_with(folder)), - ty::FnPtr(sig_tys, hdr) => ty::FnPtr(sig_tys.fold_with(folder), hdr), - ty::UnsafeBinder(f) => ty::UnsafeBinder(f.fold_with(folder)), - ty::Ref(r, ty, mutbl) => ty::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl), - ty::Coroutine(did, args) => ty::Coroutine(did, args.fold_with(folder)), - ty::CoroutineWitness(did, args) => ty::CoroutineWitness(did, args.fold_with(folder)), - ty::Closure(did, args) => ty::Closure(did, args.fold_with(folder)), - ty::CoroutineClosure(did, args) => ty::CoroutineClosure(did, args.fold_with(folder)), - ty::Alias(kind, data) => ty::Alias(kind, data.fold_with(folder)), - ty::Pat(ty, pat) => ty::Pat(ty.fold_with(folder), pat.fold_with(folder)), - - ty::Bool - | ty::Char - | ty::Str - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Error(_) - | ty::Infer(_) - | ty::Param(..) - | ty::Bound(..) - | ty::Placeholder(..) - | ty::Never - | ty::Foreign(..) => return self, - }; - - if *self.kind() == kind { self } else { folder.cx().mk_ty_from_kind(kind) } - } -} - -impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { - fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { - match self.kind() { - ty::RawPtr(ty, _mutbl) => ty.visit_with(visitor), - ty::Array(typ, sz) => { - try_visit!(typ.visit_with(visitor)); - sz.visit_with(visitor) - } - ty::Slice(typ) => typ.visit_with(visitor), - ty::Adt(_, args) => args.visit_with(visitor), - ty::Dynamic(trait_ty, reg) => { - try_visit!(trait_ty.visit_with(visitor)); - reg.visit_with(visitor) - } - ty::Tuple(ts) => ts.visit_with(visitor), - ty::FnDef(_, args) => args.visit_with(visitor), - ty::FnPtr(sig_tys, _) => sig_tys.visit_with(visitor), - ty::UnsafeBinder(f) => f.visit_with(visitor), - ty::Ref(r, ty, _) => { - try_visit!(r.visit_with(visitor)); - ty.visit_with(visitor) - } - ty::Coroutine(_did, args) => args.visit_with(visitor), - ty::CoroutineWitness(_did, args) => args.visit_with(visitor), - ty::Closure(_did, args) => args.visit_with(visitor), - ty::CoroutineClosure(_did, args) => args.visit_with(visitor), - ty::Alias(_, data) => data.visit_with(visitor), - - ty::Pat(ty, pat) => { - try_visit!(ty.visit_with(visitor)); - pat.visit_with(visitor) - } - - ty::Error(guar) => guar.visit_with(visitor), - - ty::Bool - | ty::Char - | ty::Str - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Infer(_) - | ty::Bound(..) - | ty::Placeholder(..) - | ty::Param(..) - | ty::Never - | ty::Foreign(..) => V::Result::output(), - } - } -} - impl<'tcx> TypeFoldable> for ty::Region<'tcx> { fn try_fold_with>>( self, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index b449b8f1a406c..7de53f9e22ebc 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -3,31 +3,27 @@ #![allow(rustc::usage_of_ty_tykind)] use std::borrow::Cow; -use std::ops::{ControlFlow, Range}; +use std::ops::Range; use hir::def::{CtorKind, DefKind}; -use rustc_abi::{FIRST_VARIANT, FieldIdx, ScalableElt, VariantIdx}; +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::debug_assert_matches; -use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::LangItem; use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, extension}; -use rustc_span::{DUMMY_SP, Span, Symbol, kw, sym}; +use rustc_span::{DUMMY_SP, Span, Symbol, kw}; use rustc_type_ir::TyKind::*; -use rustc_type_ir::solve::SizedTraitKind; -use rustc_type_ir::walk::TypeWalker; -use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, TypeVisitableExt, elaborate}; +use rustc_type_ir::inherent::IntoKind; +use rustc_type_ir::{self as ir, CollectAndApply, TypeVisitableExt, elaborate}; use tracing::instrument; use ty::util::IntTypeExt; use super::GenericParamDefKind; use crate::infer::canonical::Canonical; -use crate::traits::ObligationCause; -use crate::ty::InferTy::*; use crate::ty::{ self, AdtDef, Const, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv, Region, - Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy, ValTree, + TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, ValTree, }; // Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here @@ -49,6 +45,7 @@ pub type BoundRegion<'tcx> = ir::BoundRegion>; pub type BoundVariableKind<'tcx> = ir::BoundVariableKind>; pub type BoundRegionKind<'tcx> = ir::BoundRegionKind>; pub type BoundTyKind<'tcx> = ir::BoundTyKind>; +pub type Ty<'tcx> = ir::Ty>; pub trait Article { fn article(&self) -> &'static str; @@ -89,7 +86,7 @@ impl<'tcx> ty::CoroutineArgs> { #[inline] fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range { // FIXME requires optimized MIR - FIRST_VARIANT..tcx.coroutine_layout(def_id, self.args).unwrap().variant_fields.next_index() + tcx.coroutine_variant_range(def_id, self) } /// The discriminant for the given variant. Panics if the `variant_index` is @@ -359,1751 +356,6 @@ impl ParamConst { } } -/// Constructors for `Ty` -impl<'tcx> Ty<'tcx> { - /// Avoid using this in favour of more specific `new_*` methods, where possible. - /// The more specific methods will often optimize their creation. - #[allow(rustc::usage_of_ty_tykind)] - #[inline] - 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> { - Ty::new(tcx, Param(ParamTy { index, name })) - } - - #[inline] - pub fn new_bound( - tcx: TyCtxt<'tcx>, - index: ty::DebruijnIndex, - bound_ty: ty::BoundTy<'tcx>, - ) -> Ty<'tcx> { - // Use a pre-interned one when possible. - if let ty::BoundTy { var, kind: ty::BoundTyKind::Anon } = bound_ty - && let Some(inner) = tcx.types.anon_bound_tys.get(index.as_usize()) - && let Some(ty) = inner.get(var.as_usize()).copied() - { - ty - } else { - Ty::new(tcx, Bound(ty::BoundVarIndexKind::Bound(index), bound_ty)) - } - } - - #[inline] - pub fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: BoundVar) -> Ty<'tcx> { - // Use a pre-interned one when possible. - if let Some(ty) = tcx.types.anon_canonical_bound_tys.get(var.as_usize()).copied() { - ty - } else { - Ty::new( - tcx, - Bound( - ty::BoundVarIndexKind::Canonical, - ty::BoundTy { var, kind: ty::BoundTyKind::Anon }, - ), - ) - } - } - - #[inline] - pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderType<'tcx>) -> Ty<'tcx> { - Ty::new(tcx, Placeholder(placeholder)) - } - - #[inline] - pub fn new_alias( - tcx: TyCtxt<'tcx>, - kind: ty::AliasTyKind, - 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::Free, DefKind::TyAlias) - ); - Ty::new(tcx, Alias(kind, alias_ty)) - } - - #[inline] - pub fn new_pat(tcx: TyCtxt<'tcx>, base: Ty<'tcx>, pat: ty::Pattern<'tcx>) -> Ty<'tcx> { - Ty::new(tcx, Pat(base, pat)) - } - - #[inline] - pub fn new_field_representing_type( - tcx: TyCtxt<'tcx>, - base: Ty<'tcx>, - variant: VariantIdx, - field: FieldIdx, - ) -> Ty<'tcx> { - let Some(did) = tcx.lang_items().field_representing_type() else { - bug!("could not locate the `FieldRepresentingType` lang item") - }; - let def = tcx.adt_def(did); - let args = tcx.mk_args(&[ - base.into(), - Const::new_value( - tcx, - ValTree::from_scalar_int(tcx, variant.as_u32().into()), - tcx.types.u32, - ) - .into(), - Const::new_value( - tcx, - ValTree::from_scalar_int(tcx, field.as_u32().into()), - tcx.types.u32, - ) - .into(), - ]); - Ty::new_adt(tcx, def, args) - } - - #[inline] - #[instrument(level = "debug", skip(tcx))] - pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>) -> Ty<'tcx> { - Ty::new_alias(tcx, ty::Opaque, AliasTy::new_from_args(tcx, def_id, args)) - } - - /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed` - pub fn new_error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Ty<'tcx> { - Ty::new(tcx, Error(guar)) - } - - /// Constructs a `TyKind::Error` type and registers a `span_delayed_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 `span_delayed_bug` with the given `msg` to - /// ensure it gets used. - #[track_caller] - pub fn new_error_with_message>( - tcx: TyCtxt<'tcx>, - span: S, - msg: impl Into>, - ) -> Ty<'tcx> { - let reported = tcx.dcx().span_delayed_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 { - F16 => tcx.types.f16, - F32 => tcx.types.f32, - F64 => tcx.types.f64, - F128 => tcx.types.f128, - } - } - - #[inline] - pub fn new_ref( - tcx: TyCtxt<'tcx>, - r: Region<'tcx>, - ty: Ty<'tcx>, - mutbl: ty::Mutability, - ) -> Ty<'tcx> { - Ty::new(tcx, Ref(r, ty, mutbl)) - } - - #[inline] - pub fn new_mut_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - Ty::new_ref(tcx, r, ty, 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, ty, hir::Mutability::Not) - } - - pub fn new_pinned_ref( - tcx: TyCtxt<'tcx>, - r: Region<'tcx>, - ty: Ty<'tcx>, - mutbl: ty::Mutability, - ) -> Ty<'tcx> { - let pin = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, DUMMY_SP)); - Ty::new_adt(tcx, pin, tcx.mk_args(&[Ty::new_ref(tcx, r, ty, mutbl).into()])) - } - - #[inline] - pub fn new_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, mutbl: ty::Mutability) -> Ty<'tcx> { - Ty::new(tcx, ty::RawPtr(ty, mutbl)) - } - - #[inline] - pub fn new_mut_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - Ty::new_ptr(tcx, ty, hir::Mutability::Mut) - } - - #[inline] - pub fn new_imm_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - Ty::new_ptr(tcx, ty, hir::Mutability::Not) - } - - #[inline] - pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> { - tcx.debug_assert_args_compatible(def.did(), args); - if cfg!(debug_assertions) { - match tcx.def_kind(def.did()) { - DefKind::Struct | DefKind::Union | DefKind::Enum => {} - DefKind::Mod - | DefKind::Variant - | DefKind::Trait - | DefKind::TyAlias - | DefKind::ForeignTy - | DefKind::TraitAlias - | DefKind::AssocTy - | DefKind::TyParam - | DefKind::Fn - | DefKind::Const { .. } - | DefKind::ConstParam - | DefKind::Static { .. } - | DefKind::Ctor(..) - | DefKind::AssocFn - | DefKind::AssocConst { .. } - | DefKind::Macro(..) - | DefKind::ExternCrate - | DefKind::Use - | DefKind::ForeignMod - | DefKind::AnonConst - | DefKind::InlineConst - | DefKind::OpaqueTy - | DefKind::Field - | DefKind::LifetimeParam - | DefKind::GlobalAsm - | DefKind::Impl { .. } - | DefKind::Closure - | DefKind::SyntheticCoroutineBody => { - bug!("not an adt: {def:?} ({:?})", tcx.def_kind(def.did())) - } - } - } - 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(tcx: TyCtxt<'tcx>, iter: I) -> T::Output - where - I: Iterator, - T: CollectAndApply, 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>>, - ) -> Ty<'tcx> { - debug_assert_matches!( - tcx.def_kind(def_id), - DefKind::AssocFn | DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) - ); - 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> { - let (sig_tys, hdr) = fty.split(); - Ty::new(tcx, FnPtr(sig_tys, hdr)) - } - - #[inline] - pub fn new_unsafe_binder(tcx: TyCtxt<'tcx>, b: Binder<'tcx, Ty<'tcx>>) -> Ty<'tcx> { - Ty::new(tcx, UnsafeBinder(b.into())) - } - - #[inline] - pub fn new_dynamic( - tcx: TyCtxt<'tcx>, - obj: &'tcx List>, - reg: ty::Region<'tcx>, - ) -> Ty<'tcx> { - if cfg!(debug_assertions) { - let projection_count = obj - .projection_bounds() - .filter(|item| !tcx.generics_require_sized_self(item.item_def_id())) - .count(); - let expected_count: usize = obj - .principal_def_id() - .into_iter() - .flat_map(|principal_def_id| { - // IMPORTANT: This has to agree with HIR ty lowering of dyn trait! - elaborate::supertraits( - tcx, - ty::Binder::dummy(ty::TraitRef::identity(tcx, principal_def_id)), - ) - .map(|principal| { - tcx.associated_items(principal.def_id()) - .in_definition_order() - .filter(|item| item.is_type() || item.is_const()) - .filter(|item| !item.is_impl_trait_in_trait()) - .filter(|item| !tcx.generics_require_sized_self(item.def_id)) - .count() - }) - }) - .sum(); - assert_eq!( - projection_count, expected_count, - "expected {obj:?} to have {expected_count} projections, \ - but it has {projection_count}" - ); - } - Ty::new(tcx, Dynamic(obj, reg)) - } - - #[inline] - pub fn new_projection_from_args( - tcx: TyCtxt<'tcx>, - item_def_id: DefId, - args: ty::GenericArgsRef<'tcx>, - ) -> Ty<'tcx> { - Ty::new_alias(tcx, ty::Projection, AliasTy::new_from_args(tcx, item_def_id, args)) - } - - #[inline] - pub fn new_projection( - tcx: TyCtxt<'tcx>, - item_def_id: DefId, - args: impl IntoIterator>>, - ) -> Ty<'tcx> { - Ty::new_alias(tcx, ty::Projection, AliasTy::new(tcx, item_def_id, args)) - } - - #[inline] - pub fn new_closure( - tcx: TyCtxt<'tcx>, - def_id: DefId, - closure_args: GenericArgsRef<'tcx>, - ) -> Ty<'tcx> { - tcx.debug_assert_args_compatible(def_id, closure_args); - Ty::new(tcx, Closure(def_id, closure_args)) - } - - #[inline] - pub fn new_coroutine_closure( - tcx: TyCtxt<'tcx>, - def_id: DefId, - closure_args: GenericArgsRef<'tcx>, - ) -> Ty<'tcx> { - tcx.debug_assert_args_compatible(def_id, closure_args); - Ty::new(tcx, CoroutineClosure(def_id, closure_args)) - } - - #[inline] - pub fn new_coroutine( - tcx: TyCtxt<'tcx>, - def_id: DefId, - coroutine_args: GenericArgsRef<'tcx>, - ) -> Ty<'tcx> { - tcx.debug_assert_args_compatible(def_id, coroutine_args); - Ty::new(tcx, Coroutine(def_id, coroutine_args)) - } - - #[inline] - pub fn new_coroutine_witness( - tcx: TyCtxt<'tcx>, - def_id: DefId, - args: GenericArgsRef<'tcx>, - ) -> Ty<'tcx> { - if cfg!(debug_assertions) { - tcx.debug_assert_args_compatible(tcx.typeck_root_def_id(def_id), args); - } - Ty::new(tcx, CoroutineWitness(def_id, args)) - } - - pub fn new_coroutine_witness_for_coroutine( - tcx: TyCtxt<'tcx>, - def_id: DefId, - coroutine_args: GenericArgsRef<'tcx>, - ) -> Ty<'tcx> { - tcx.debug_assert_args_compatible(def_id, coroutine_args); - // HACK: Coroutine witness types are lifetime erased, so they - // never reference any lifetime args from the coroutine. We erase - // the regions here since we may get into situations where a - // coroutine is recursively contained within itself, leading to - // witness types that differ by region args. This means that - // cycle detection in fulfillment will not kick in, which leads - // to unnecessary overflows in async code. See the issue: - // . - let args = - ty::GenericArgs::for_item(tcx, tcx.typeck_root_def_id(def_id), |def, _| { - match def.kind { - ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), - ty::GenericParamDefKind::Type { .. } - | ty::GenericParamDefKind::Const { .. } => coroutine_args[def.index as usize], - } - }); - Ty::new_coroutine_witness(tcx, def_id, args) - } - - // misc - - #[inline] - pub fn new_static_str(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_) - } - - // 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_adt(tcx, adt_def, args) - } - - #[inline] - pub fn new_lang_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, item: LangItem) -> Option> { - 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> { - 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, DUMMY_SP); - Ty::new_generic_adt(tcx, def_id, ty) - } - - #[inline] - pub fn new_option(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - let def_id = tcx.require_lang_item(LangItem::Option, DUMMY_SP); - 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, DUMMY_SP); - 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, DUMMY_SP); - 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) - } -} - -impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { - fn new_bool(tcx: TyCtxt<'tcx>) -> Self { - tcx.types.bool - } - - fn new_u8(tcx: TyCtxt<'tcx>) -> Self { - tcx.types.u8 - } - - fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferTy) -> Self { - Ty::new_infer(tcx, infer) - } - - fn new_var(tcx: TyCtxt<'tcx>, vid: ty::TyVid) -> Self { - Ty::new_var(tcx, vid) - } - - fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamTy) -> Self { - Ty::new_param(tcx, param.index, param.name) - } - - fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderType<'tcx>) -> Self { - Ty::new_placeholder(tcx, placeholder) - } - - fn new_bound( - interner: TyCtxt<'tcx>, - debruijn: ty::DebruijnIndex, - var: ty::BoundTy<'tcx>, - ) -> Self { - Ty::new_bound(interner, debruijn, var) - } - - fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { - Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon }) - } - - fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: ty::BoundVar) -> Self { - Ty::new_canonical_bound(tcx, var) - } - - fn new_alias( - interner: TyCtxt<'tcx>, - kind: ty::AliasTyKind, - alias_ty: ty::AliasTy<'tcx>, - ) -> Self { - Ty::new_alias(interner, kind, alias_ty) - } - - fn new_error(interner: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self { - Ty::new_error(interner, guar) - } - - fn new_adt( - interner: TyCtxt<'tcx>, - adt_def: ty::AdtDef<'tcx>, - args: ty::GenericArgsRef<'tcx>, - ) -> Self { - Ty::new_adt(interner, adt_def, args) - } - - fn new_foreign(interner: TyCtxt<'tcx>, def_id: DefId) -> Self { - Ty::new_foreign(interner, def_id) - } - - fn new_dynamic( - interner: TyCtxt<'tcx>, - preds: &'tcx List>, - region: ty::Region<'tcx>, - ) -> Self { - Ty::new_dynamic(interner, preds, region) - } - - fn new_coroutine( - interner: TyCtxt<'tcx>, - def_id: DefId, - args: ty::GenericArgsRef<'tcx>, - ) -> Self { - Ty::new_coroutine(interner, def_id, args) - } - - fn new_coroutine_closure( - interner: TyCtxt<'tcx>, - def_id: DefId, - args: ty::GenericArgsRef<'tcx>, - ) -> Self { - Ty::new_coroutine_closure(interner, def_id, args) - } - - fn new_closure(interner: TyCtxt<'tcx>, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Self { - Ty::new_closure(interner, def_id, args) - } - - fn new_coroutine_witness( - interner: TyCtxt<'tcx>, - def_id: DefId, - args: ty::GenericArgsRef<'tcx>, - ) -> Self { - Ty::new_coroutine_witness(interner, def_id, args) - } - - fn new_coroutine_witness_for_coroutine( - interner: TyCtxt<'tcx>, - def_id: DefId, - coroutine_args: ty::GenericArgsRef<'tcx>, - ) -> Self { - Ty::new_coroutine_witness_for_coroutine(interner, def_id, coroutine_args) - } - - fn new_ptr(interner: TyCtxt<'tcx>, ty: Self, mutbl: hir::Mutability) -> Self { - Ty::new_ptr(interner, ty, mutbl) - } - - fn new_ref( - interner: TyCtxt<'tcx>, - region: ty::Region<'tcx>, - ty: Self, - mutbl: hir::Mutability, - ) -> Self { - Ty::new_ref(interner, region, ty, mutbl) - } - - fn new_array_with_const_len(interner: TyCtxt<'tcx>, ty: Self, len: ty::Const<'tcx>) -> Self { - Ty::new_array_with_const_len(interner, ty, len) - } - - fn new_slice(interner: TyCtxt<'tcx>, ty: Self) -> Self { - Ty::new_slice(interner, ty) - } - - fn new_tup(interner: TyCtxt<'tcx>, tys: &[Ty<'tcx>]) -> Self { - Ty::new_tup(interner, tys) - } - - fn new_tup_from_iter(interner: TyCtxt<'tcx>, iter: It) -> T::Output - where - It: Iterator, - T: CollectAndApply, - { - Ty::new_tup_from_iter(interner, iter) - } - - fn tuple_fields(self) -> &'tcx ty::List> { - self.tuple_fields() - } - - fn to_opt_closure_kind(self) -> Option { - self.to_opt_closure_kind() - } - - fn from_closure_kind(interner: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Self { - Ty::from_closure_kind(interner, kind) - } - - fn from_coroutine_closure_kind( - interner: TyCtxt<'tcx>, - kind: rustc_type_ir::ClosureKind, - ) -> Self { - Ty::from_coroutine_closure_kind(interner, kind) - } - - fn new_fn_def(interner: TyCtxt<'tcx>, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Self { - Ty::new_fn_def(interner, def_id, args) - } - - fn new_fn_ptr(interner: TyCtxt<'tcx>, sig: ty::Binder<'tcx, ty::FnSig<'tcx>>) -> Self { - Ty::new_fn_ptr(interner, sig) - } - - fn new_pat(interner: TyCtxt<'tcx>, ty: Self, pat: ty::Pattern<'tcx>) -> Self { - Ty::new_pat(interner, ty, pat) - } - - fn new_unsafe_binder(interner: TyCtxt<'tcx>, ty: ty::Binder<'tcx, Ty<'tcx>>) -> Self { - Ty::new_unsafe_binder(interner, ty) - } - - fn new_unit(interner: TyCtxt<'tcx>) -> Self { - interner.types.unit - } - - fn new_usize(interner: TyCtxt<'tcx>) -> Self { - interner.types.usize - } - - fn discriminant_ty(self, interner: TyCtxt<'tcx>) -> Ty<'tcx> { - self.discriminant_ty(interner) - } - - fn has_unsafe_fields(self) -> bool { - Ty::has_unsafe_fields(self) - } -} - -/// Type utilities -impl<'tcx> Ty<'tcx> { - // It would be nicer if this returned the value instead of a reference, - // like how `Predicate::kind` and `Region::kind` do. (It would result in - // many fewer subsequent dereferences.) But that gives a small but - // noticeable performance hit. See #126069 for details. - #[inline(always)] - pub fn kind(self) -> &'tcx TyKind<'tcx> { - self.0.0 - } - - // FIXME(compiler-errors): Think about removing this. - #[inline(always)] - pub fn flags(self) -> TypeFlags { - self.0.0.flags - } - - #[inline] - pub fn is_unit(self) -> bool { - match self.kind() { - Tuple(tys) => tys.is_empty(), - _ => false, - } - } - - /// Check if type is an `usize`. - #[inline] - pub fn is_usize(self) -> bool { - matches!(self.kind(), Uint(UintTy::Usize)) - } - - /// Check if type is an `usize` or an integral type variable. - #[inline] - pub fn is_usize_like(self) -> bool { - matches!(self.kind(), Uint(UintTy::Usize) | Infer(IntVar(_))) - } - - #[inline] - pub fn is_never(self) -> bool { - matches!(self.kind(), Never) - } - - #[inline] - pub fn is_primitive(self) -> bool { - matches!(self.kind(), Bool | Char | Int(_) | Uint(_) | Float(_)) - } - - #[inline] - pub fn is_adt(self) -> bool { - matches!(self.kind(), Adt(..)) - } - - #[inline] - pub fn is_ref(self) -> bool { - matches!(self.kind(), Ref(..)) - } - - #[inline] - pub fn is_ty_var(self) -> bool { - matches!(self.kind(), Infer(TyVar(_))) - } - - #[inline] - pub fn ty_vid(self) -> Option { - match self.kind() { - &Infer(TyVar(vid)) => Some(vid), - _ => None, - } - } - - #[inline] - pub fn is_ty_or_numeric_infer(self) -> bool { - matches!(self.kind(), Infer(_)) - } - - #[inline] - pub fn is_phantom_data(self) -> bool { - if let Adt(def, _) = self.kind() { def.is_phantom_data() } else { false } - } - - #[inline] - pub fn is_bool(self) -> bool { - *self.kind() == Bool - } - - /// Returns `true` if this type is a `str`. - #[inline] - pub fn is_str(self) -> bool { - *self.kind() == Str - } - - /// Returns true if this type is `&str`. The reference's lifetime is ignored. - #[inline] - pub fn is_imm_ref_str(self) -> bool { - matches!(self.kind(), ty::Ref(_, inner, hir::Mutability::Not) if inner.is_str()) - } - - #[inline] - pub fn is_param(self, index: u32) -> bool { - match self.kind() { - ty::Param(data) => data.index == index, - _ => false, - } - } - - #[inline] - pub fn is_slice(self) -> bool { - matches!(self.kind(), Slice(_)) - } - - #[inline] - pub fn is_array_slice(self) -> bool { - match self.kind() { - Slice(_) => true, - ty::RawPtr(ty, _) | Ref(_, ty, _) => matches!(ty.kind(), Slice(_)), - _ => false, - } - } - - #[inline] - pub fn is_array(self) -> bool { - matches!(self.kind(), Array(..)) - } - - #[inline] - pub fn is_simd(self) -> bool { - match self.kind() { - Adt(def, _) => def.repr().simd(), - _ => false, - } - } - - #[inline] - pub fn is_scalable_vector(self) -> bool { - match self.kind() { - Adt(def, _) => def.repr().scalable(), - _ => false, - } - } - - pub fn sequence_element_type(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - match self.kind() { - Array(ty, _) | Slice(ty) => *ty, - Str => tcx.types.u8, - _ => bug!("`sequence_element_type` called on non-sequence value: {}", self), - } - } - - pub fn scalable_vector_element_count_and_type(self, tcx: TyCtxt<'tcx>) -> (u16, Ty<'tcx>) { - let Adt(def, args) = self.kind() else { - bug!("`scalable_vector_size_and_type` called on invalid type") - }; - let Some(ScalableElt::ElementCount(element_count)) = def.repr().scalable else { - bug!("`scalable_vector_size_and_type` called on non-scalable vector type"); - }; - let variant = def.non_enum_variant(); - assert_eq!(variant.fields.len(), 1); - let field_ty = variant.fields[FieldIdx::ZERO].ty(tcx, args); - (element_count, field_ty) - } - - pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) { - let Adt(def, args) = self.kind() else { - bug!("`simd_size_and_type` called on invalid type") - }; - assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type"); - let variant = def.non_enum_variant(); - assert_eq!(variant.fields.len(), 1); - let field_ty = variant.fields[FieldIdx::ZERO].ty(tcx, args); - let Array(f0_elem_ty, f0_len) = field_ty.kind() else { - bug!("Simd type has non-array field type {field_ty:?}") - }; - // FIXME(repr_simd): https://github.com/rust-lang/rust/pull/78863#discussion_r522784112 - // The way we evaluate the `N` in `[T; N]` here only works since we use - // `simd_size_and_type` post-monomorphization. It will probably start to ICE - // if we use it in generic code. See the `simd-array-trait` ui test. - ( - f0_len - .try_to_target_usize(tcx) - .expect("expected SIMD field to have definite array size"), - *f0_elem_ty, - ) - } - - #[inline] - pub fn is_mutable_ptr(self) -> bool { - matches!(self.kind(), RawPtr(_, hir::Mutability::Mut) | Ref(_, _, hir::Mutability::Mut)) - } - - /// Get the mutability of the reference or `None` when not a reference - #[inline] - pub fn ref_mutability(self) -> Option { - match self.kind() { - Ref(_, _, mutability) => Some(*mutability), - _ => None, - } - } - - #[inline] - pub fn is_raw_ptr(self) -> bool { - matches!(self.kind(), RawPtr(_, _)) - } - - /// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer). - /// `Box` is *not* considered a pointer here! - #[inline] - pub fn is_any_ptr(self) -> bool { - self.is_ref() || self.is_raw_ptr() || self.is_fn_ptr() - } - - #[inline] - pub fn is_box(self) -> bool { - match self.kind() { - Adt(def, _) => def.is_box(), - _ => false, - } - } - - /// Tests whether this is a Box definitely using the global allocator. - /// - /// If the allocator is still generic, the answer is `false`, but it may - /// later turn out that it does use the global allocator. - #[inline] - pub fn is_box_global(self, tcx: TyCtxt<'tcx>) -> bool { - match self.kind() { - Adt(def, args) if def.is_box() => { - let Some(alloc) = args.get(1) else { - // Single-argument Box is always global. (for "minicore" tests) - return true; - }; - alloc.expect_ty().ty_adt_def().is_some_and(|alloc_adt| { - tcx.is_lang_item(alloc_adt.did(), LangItem::GlobalAlloc) - }) - } - _ => false, - } - } - - pub fn boxed_ty(self) -> Option> { - match self.kind() { - Adt(def, args) if def.is_box() => Some(args.type_at(0)), - _ => None, - } - } - - pub fn pinned_ty(self) -> Option> { - match self.kind() { - Adt(def, args) if def.is_pin() => Some(args.type_at(0)), - _ => None, - } - } - - pub fn maybe_pinned_ref( - self, - ) -> Option<(Ty<'tcx>, ty::Pinnedness, ty::Mutability, Region<'tcx>)> { - match self.kind() { - Adt(def, args) - if def.is_pin() - && let &ty::Ref(region, ty, mutbl) = args.type_at(0).kind() => - { - Some((ty, ty::Pinnedness::Pinned, mutbl, region)) - } - &Ref(region, ty, mutbl) => Some((ty, ty::Pinnedness::Not, mutbl, region)), - _ => None, - } - } - - /// Panics if called on any type other than `Box`. - pub fn expect_boxed_ty(self) -> Ty<'tcx> { - self.boxed_ty() - .unwrap_or_else(|| bug!("`expect_boxed_ty` is called on non-box type {:?}", self)) - } - - /// A scalar type is one that denotes an atomic datum, with no sub-components. - /// (A RawPtr is scalar because it represents a non-managed pointer, so its - /// contents are abstract to rustc.) - #[inline] - pub fn is_scalar(self) -> bool { - matches!( - self.kind(), - Bool | Char - | Int(_) - | Float(_) - | Uint(_) - | FnDef(..) - | FnPtr(..) - | RawPtr(_, _) - | Infer(IntVar(_) | FloatVar(_)) - ) - } - - /// Returns `true` if this type is a floating point type. - #[inline] - pub fn is_floating_point(self) -> bool { - matches!(self.kind(), Float(_) | Infer(FloatVar(_))) - } - - #[inline] - pub fn is_trait(self) -> bool { - matches!(self.kind(), Dynamic(_, _)) - } - - #[inline] - pub fn is_enum(self) -> bool { - matches!(self.kind(), Adt(adt_def, _) if adt_def.is_enum()) - } - - #[inline] - pub fn is_union(self) -> bool { - matches!(self.kind(), Adt(adt_def, _) if adt_def.is_union()) - } - - #[inline] - pub fn is_closure(self) -> bool { - matches!(self.kind(), Closure(..)) - } - - #[inline] - pub fn is_coroutine(self) -> bool { - matches!(self.kind(), Coroutine(..)) - } - - #[inline] - pub fn is_coroutine_closure(self) -> bool { - matches!(self.kind(), CoroutineClosure(..)) - } - - #[inline] - pub fn is_integral(self) -> bool { - matches!(self.kind(), Infer(IntVar(_)) | Int(_) | Uint(_)) - } - - #[inline] - pub fn is_fresh_ty(self) -> bool { - matches!(self.kind(), Infer(FreshTy(_))) - } - - #[inline] - pub fn is_fresh(self) -> bool { - matches!(self.kind(), Infer(FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_))) - } - - #[inline] - pub fn is_char(self) -> bool { - matches!(self.kind(), Char) - } - - #[inline] - pub fn is_numeric(self) -> bool { - self.is_integral() || self.is_floating_point() - } - - #[inline] - pub fn is_signed(self) -> bool { - matches!(self.kind(), Int(_)) - } - - #[inline] - pub fn is_ptr_sized_integral(self) -> bool { - matches!(self.kind(), Int(ty::IntTy::Isize) | Uint(ty::UintTy::Usize)) - } - - #[inline] - pub fn has_concrete_skeleton(self) -> bool { - !matches!(self.kind(), Param(_) | Infer(_) | Error(_)) - } - - /// Checks whether a type recursively contains another type - /// - /// Example: `Option<()>` contains `()` - pub fn contains(self, other: Ty<'tcx>) -> bool { - struct ContainsTyVisitor<'tcx>(Ty<'tcx>); - - impl<'tcx> TypeVisitor> for ContainsTyVisitor<'tcx> { - type Result = ControlFlow<()>; - - fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { - if self.0 == t { ControlFlow::Break(()) } else { t.super_visit_with(self) } - } - } - - let cf = self.visit_with(&mut ContainsTyVisitor(other)); - cf.is_break() - } - - /// Checks whether a type recursively contains any closure - /// - /// Example: `Option<{closure@file.rs:4:20}>` returns true - pub fn contains_closure(self) -> bool { - struct ContainsClosureVisitor; - - impl<'tcx> TypeVisitor> for ContainsClosureVisitor { - type Result = ControlFlow<()>; - - fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { - if let ty::Closure(..) = t.kind() { - ControlFlow::Break(()) - } else { - t.super_visit_with(self) - } - } - } - - let cf = self.visit_with(&mut ContainsClosureVisitor); - cf.is_break() - } - - /// Returns the deepest `async_drop_in_place::{closure}` implementation. - /// - /// `async_drop_in_place::{closure}`, when T is a coroutine, is a proxy-impl - /// to call async drop poll from impl coroutine. - pub fn find_async_drop_impl_coroutine)>( - self, - tcx: TyCtxt<'tcx>, - mut f: F, - ) -> Ty<'tcx> { - assert!(self.is_coroutine()); - let mut cor_ty = self; - let mut ty = cor_ty; - loop { - let ty::Coroutine(def_id, args) = ty.kind() else { return cor_ty }; - cor_ty = ty; - f(ty); - if !tcx.is_async_drop_in_place_coroutine(*def_id) { - return cor_ty; - } - ty = args.first().unwrap().expect_ty(); - } - } - - /// Returns the type of `*ty`. - /// - /// The parameter `explicit` indicates if this is an *explicit* dereference. - /// Some types -- notably raw ptrs -- can only be dereferenced explicitly. - pub fn builtin_deref(self, explicit: bool) -> Option> { - match *self.kind() { - _ if let Some(boxed) = self.boxed_ty() => Some(boxed), - Ref(_, ty, _) => Some(ty), - RawPtr(ty, _) if explicit => Some(ty), - _ => None, - } - } - - /// Returns the type of `ty[i]`. - pub fn builtin_index(self) -> Option> { - match self.kind() { - Array(ty, _) | Slice(ty) => Some(*ty), - _ => None, - } - } - - #[tracing::instrument(level = "trace", skip(tcx))] - pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> { - self.kind().fn_sig(tcx) - } - - #[inline] - pub fn is_fn(self) -> bool { - matches!(self.kind(), FnDef(..) | FnPtr(..)) - } - - #[inline] - pub fn is_fn_ptr(self) -> bool { - matches!(self.kind(), FnPtr(..)) - } - - #[inline] - pub fn is_impl_trait(self) -> bool { - matches!(self.kind(), Alias(ty::Opaque, ..)) - } - - #[inline] - pub fn ty_adt_def(self) -> Option> { - match self.kind() { - Adt(adt, _) => Some(*adt), - _ => None, - } - } - - /// Iterates over tuple fields. - /// Panics when called on anything but a tuple. - #[inline] - pub fn tuple_fields(self) -> &'tcx List> { - match self.kind() { - Tuple(args) => args, - _ => bug!("tuple_fields called on non-tuple: {self:?}"), - } - } - - /// If the type contains variants, returns the valid range of variant indices. - // - // FIXME: This requires the optimized MIR in the case of coroutines. - #[inline] - pub fn variant_range(self, tcx: TyCtxt<'tcx>) -> Option> { - match self.kind() { - TyKind::Adt(adt, _) => Some(adt.variant_range()), - TyKind::Coroutine(def_id, args) => { - Some(args.as_coroutine().variant_range(*def_id, tcx)) - } - _ => None, - } - } - - /// If the type contains variants, returns the variant for `variant_index`. - /// Panics if `variant_index` is out of range. - // - // FIXME: This requires the optimized MIR in the case of coroutines. - #[inline] - pub fn discriminant_for_variant( - self, - tcx: TyCtxt<'tcx>, - variant_index: VariantIdx, - ) -> Option> { - match self.kind() { - TyKind::Adt(adt, _) if adt.is_enum() => { - Some(adt.discriminant_for_variant(tcx, variant_index)) - } - TyKind::Coroutine(def_id, args) => { - Some(args.as_coroutine().discriminant_for_variant(*def_id, tcx, variant_index)) - } - _ => None, - } - } - - /// Returns the type of the discriminant of this type. - 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::Coroutine(_, args) => args.as_coroutine().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, DUMMY_SP), - ); - Ty::new_projection_from_args(tcx, assoc_items[0], tcx.mk_args(&[self.into()])) - } - - ty::Pat(ty, _) => ty.discriminant_ty(tcx), - - ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Adt(..) - | ty::Foreign(_) - | ty::Str - | ty::Array(..) - | ty::Slice(_) - | ty::RawPtr(_, _) - | ty::Ref(..) - | ty::FnDef(..) - | ty::FnPtr(..) - | ty::Dynamic(..) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::CoroutineWitness(..) - | ty::Never - | ty::Tuple(_) - | ty::UnsafeBinder(_) - | ty::Error(_) - | ty::Infer(IntVar(_) | FloatVar(_)) => tcx.types.u8, - - ty::Bound(..) - | ty::Placeholder(_) - | ty::Infer(FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { - bug!("`discriminant_ty` applied to unexpected type: {:?}", self) - } - } - } - - /// Returns the type of metadata for (potentially wide) pointers to this type, - /// or the struct tail if the metadata type cannot be determined. - pub fn ptr_metadata_ty_or_tail( - self, - tcx: TyCtxt<'tcx>, - normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, - ) -> Result, Ty<'tcx>> { - let tail = tcx.struct_tail_raw(self, &ObligationCause::dummy(), normalize, || {}); - match tail.kind() { - // Sized types - ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) - | ty::Uint(_) - | ty::Int(_) - | ty::Bool - | ty::Float(_) - | ty::FnDef(..) - | ty::FnPtr(..) - | ty::RawPtr(..) - | ty::Char - | ty::Ref(..) - | ty::Coroutine(..) - | ty::CoroutineWitness(..) - | ty::Array(..) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Never - | ty::Error(_) - // Extern types have metadata = (). - | ty::Foreign(..) - // If returned by `struct_tail_raw` this is a unit struct - // without any fields, or not a struct, and therefore is Sized. - | ty::Adt(..) - // If returned by `struct_tail_raw` this is the empty tuple, - // a.k.a. unit type, which is Sized - | ty::Tuple(..) => Ok(tcx.types.unit), - - ty::Str | ty::Slice(_) => Ok(tcx.types.usize), - - ty::Dynamic(_, _) => { - let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, DUMMY_SP); - Ok(tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()])) - } - - // We don't know the metadata of `self`, but it must be equal to the - // metadata of `tail`. - ty::Param(_) | ty::Alias(..) => Err(tail), - - | ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"), - - ty::Infer(ty::TyVar(_)) - | ty::Pat(..) - | ty::Bound(..) - | ty::Placeholder(..) - | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => bug!( - "`ptr_metadata_ty_or_tail` applied to unexpected type: {self:?} (tail = {tail:?})" - ), - } - } - - /// Returns the type of metadata for (potentially wide) pointers to this type. - /// Causes an ICE if the metadata type cannot be determined. - pub fn ptr_metadata_ty( - self, - tcx: TyCtxt<'tcx>, - normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, - ) -> Ty<'tcx> { - match self.ptr_metadata_ty_or_tail(tcx, normalize) { - Ok(metadata) => metadata, - Err(tail) => bug!( - "`ptr_metadata_ty` failed to get metadata for type: {self:?} (tail = {tail:?})" - ), - } - } - - /// Given a pointer or reference type, returns the type of the *pointee*'s - /// metadata. If it can't be determined exactly (perhaps due to still - /// being generic) then a projection through `ptr::Pointee` will be returned. - /// - /// This is particularly useful for getting the type of the result of - /// [`UnOp::PtrMetadata`](crate::mir::UnOp::PtrMetadata). - /// - /// Panics if `self` is not dereferenceable. - #[track_caller] - pub fn pointee_metadata_ty_or_projection(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - let Some(pointee_ty) = self.builtin_deref(true) else { - bug!("Type {self:?} is not a pointer or reference type") - }; - if pointee_ty.has_trivial_sizedness(tcx, SizedTraitKind::Sized) { - tcx.types.unit - } else { - match pointee_ty.ptr_metadata_ty_or_tail(tcx, |x| x) { - Ok(metadata_ty) => metadata_ty, - Err(tail_ty) => { - let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, DUMMY_SP); - Ty::new_projection(tcx, metadata_def_id, [tail_ty]) - } - } - } - } - - /// When we create a closure, we record its kind (i.e., what trait - /// it implements, constrained by how it uses its borrows) into its - /// [`ty::ClosureArgs`] or [`ty::CoroutineClosureArgs`] 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 - /// kind. To go the other way, use [`Ty::from_closure_kind`]. - /// - /// Note that during type checking, we use an inference variable - /// to represent the closure kind, because it has not yet been - /// inferred. Once upvar inference (in `rustc_hir_analysis/src/check/upvar.rs`) - /// is complete, that type variable will be unified with one of - /// the integral types. - /// - /// ```rust,ignore (snippet of compiler code) - /// if let TyKind::Closure(def_id, args) = closure_ty.kind() - /// && let Some(closure_kind) = args.as_closure().kind_ty().to_opt_closure_kind() - /// { - /// println!("{closure_kind:?}"); - /// } else if let TyKind::CoroutineClosure(def_id, args) = closure_ty.kind() - /// && let Some(closure_kind) = args.as_coroutine_closure().kind_ty().to_opt_closure_kind() - /// { - /// println!("{closure_kind:?}"); - /// } - /// ``` - /// - /// After upvar analysis, you should instead use [`ty::ClosureArgs::kind()`] - /// or [`ty::CoroutineClosureArgs::kind()`] to assert that the `ClosureKind` - /// has been constrained instead of manually calling this method. - /// - /// ```rust,ignore (snippet of compiler code) - /// if let TyKind::Closure(def_id, args) = closure_ty.kind() - /// { - /// println!("{:?}", args.as_closure().kind()); - /// } else if let TyKind::CoroutineClosure(def_id, args) = closure_ty.kind() - /// { - /// println!("{:?}", args.as_coroutine_closure().kind()); - /// } - /// ``` - pub fn to_opt_closure_kind(self) -> Option { - match self.kind() { - Int(int_ty) => match int_ty { - ty::IntTy::I8 => Some(ty::ClosureKind::Fn), - ty::IntTy::I16 => Some(ty::ClosureKind::FnMut), - ty::IntTy::I32 => Some(ty::ClosureKind::FnOnce), - _ => bug!("cannot convert type `{:?}` to a closure kind", self), - }, - - // "Bound" types appear in canonical queries when the - // closure type is not yet known, and `Placeholder` and `Param` - // may be encountered in generic `AsyncFnKindHelper` goals. - Bound(..) | Placeholder(_) | Param(_) | Infer(_) => None, - - Error(_) => Some(ty::ClosureKind::Fn), - - _ => bug!("cannot convert type `{:?}` to a closure kind", self), - } - } - - /// Inverse of [`Ty::to_opt_closure_kind`]. See docs on that method - /// for explanation of the relationship between `Ty` and [`ty::ClosureKind`]. - pub fn from_closure_kind(tcx: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Ty<'tcx> { - match kind { - ty::ClosureKind::Fn => tcx.types.i8, - ty::ClosureKind::FnMut => tcx.types.i16, - ty::ClosureKind::FnOnce => tcx.types.i32, - } - } - - /// Like [`Ty::to_opt_closure_kind`], but it caps the "maximum" closure kind - /// to `FnMut`. This is because although we have three capability states, - /// `AsyncFn`/`AsyncFnMut`/`AsyncFnOnce`, we only need to distinguish two coroutine - /// bodies: by-ref and by-value. - /// - /// See the definition of `AsyncFn` and `AsyncFnMut` and the `CallRefFuture` - /// associated type for why we don't distinguish [`ty::ClosureKind::Fn`] and - /// [`ty::ClosureKind::FnMut`] for the purpose of the generated MIR bodies. - /// - /// This method should be used when constructing a `Coroutine` out of a - /// `CoroutineClosure`, when the `Coroutine`'s `kind` field is being populated - /// directly from the `CoroutineClosure`'s `kind`. - pub fn from_coroutine_closure_kind(tcx: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Ty<'tcx> { - match kind { - ty::ClosureKind::Fn | ty::ClosureKind::FnMut => tcx.types.i16, - ty::ClosureKind::FnOnce => tcx.types.i32, - } - } - - /// Fast path helper for testing if a type is `Sized` or `MetaSized`. - /// - /// Returning true means the type is known to implement the sizedness trait. Returning `false` - /// means nothing -- could be sized, might not be. - /// - /// Note that we could never rely on the fact that a type such as `[_]` is trivially `!Sized` - /// because we could be in a type environment with a bound such as `[_]: Copy`. A function with - /// such a bound obviously never can be called, but that doesn't mean it shouldn't typecheck. - /// This is why this method doesn't return `Option`. - #[instrument(skip(tcx), level = "debug")] - pub fn has_trivial_sizedness(self, tcx: TyCtxt<'tcx>, sizedness: SizedTraitKind) -> bool { - match self.kind() { - ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) - | ty::Uint(_) - | ty::Int(_) - | ty::Bool - | ty::Float(_) - | ty::FnDef(..) - | ty::FnPtr(..) - | ty::UnsafeBinder(_) - | ty::RawPtr(..) - | ty::Char - | ty::Ref(..) - | ty::Coroutine(..) - | ty::CoroutineWitness(..) - | ty::Array(..) - | ty::Pat(..) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Never - | ty::Error(_) => true, - - ty::Str | ty::Slice(_) | ty::Dynamic(_, _) => match sizedness { - SizedTraitKind::Sized => false, - SizedTraitKind::MetaSized => true, - }, - - ty::Foreign(..) => match sizedness { - SizedTraitKind::Sized | SizedTraitKind::MetaSized => false, - }, - - ty::Tuple(tys) => tys.last().is_none_or(|ty| ty.has_trivial_sizedness(tcx, sizedness)), - - ty::Adt(def, args) => def - .sizedness_constraint(tcx, sizedness) - .is_none_or(|ty| ty.instantiate(tcx, args).has_trivial_sizedness(tcx, sizedness)), - - ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) | ty::Bound(..) => false, - - ty::Infer(ty::TyVar(_)) => false, - - ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { - bug!("`has_trivial_sizedness` applied to unexpected type: {:?}", self) - } - } - } - - /// Fast path helper for primitives which are always `Copy` and which - /// have a side-effect-free `Clone` impl. - /// - /// Returning true means the type is known to be pure and `Copy+Clone`. - /// Returning `false` means nothing -- could be `Copy`, might not be. - /// - /// This is mostly useful for optimizations, as these are the types - /// on which we can replace cloning with dereferencing. - pub fn is_trivially_pure_clone_copy(self) -> bool { - match self.kind() { - ty::Bool | ty::Char | ty::Never => true, - - // These aren't even `Clone` - ty::Str | ty::Slice(..) | ty::Foreign(..) | ty::Dynamic(..) => false, - - ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_)) - | ty::Int(..) - | ty::Uint(..) - | ty::Float(..) => true, - - // ZST which can't be named are fine. - ty::FnDef(..) => true, - - ty::Array(element_ty, _len) => element_ty.is_trivially_pure_clone_copy(), - - // A 100-tuple isn't "trivial", so doing this only for reasonable sizes. - ty::Tuple(field_tys) => { - field_tys.len() <= 3 && field_tys.iter().all(Self::is_trivially_pure_clone_copy) - } - - ty::Pat(ty, _) => ty.is_trivially_pure_clone_copy(), - - // Sometimes traits aren't implemented for every ABI or arity, - // because we can't be generic over everything yet. - ty::FnPtr(..) => false, - - // Definitely absolutely not copy. - ty::Ref(_, _, hir::Mutability::Mut) => false, - - // The standard library has a blanket Copy impl for shared references and raw pointers, - // for all unsized types. - ty::Ref(_, _, hir::Mutability::Not) | ty::RawPtr(..) => true, - - ty::Coroutine(..) | ty::CoroutineWitness(..) => false, - - // Might be, but not "trivial" so just giving the safe answer. - ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) => false, - - ty::UnsafeBinder(_) => false, - - // Needs normalization or revealing to determine, so no is the safe answer. - ty::Alias(..) => false, - - ty::Param(..) | ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(..) => { - false - } - } - } - - pub fn is_trivially_wf(self, tcx: TyCtxt<'tcx>) -> bool { - match *self.kind() { - ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Str - | ty::Never - | ty::Param(_) - | ty::Placeholder(_) - | ty::Bound(..) => true, - - ty::Slice(ty) => { - ty.is_trivially_wf(tcx) && ty.has_trivial_sizedness(tcx, SizedTraitKind::Sized) - } - ty::RawPtr(ty, _) => ty.is_trivially_wf(tcx), - - ty::FnPtr(sig_tys, _) => { - sig_tys.skip_binder().inputs_and_output.iter().all(|ty| ty.is_trivially_wf(tcx)) - } - ty::Ref(_, ty, _) => ty.is_global() && ty.is_trivially_wf(tcx), - - ty::Infer(infer) => match infer { - ty::TyVar(_) => false, - ty::IntVar(_) | ty::FloatVar(_) => true, - ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => true, - }, - - ty::Adt(_, _) - | ty::Tuple(_) - | ty::Array(..) - | ty::Foreign(_) - | ty::Pat(_, _) - | ty::FnDef(..) - | ty::UnsafeBinder(..) - | ty::Dynamic(..) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Coroutine(..) - | ty::CoroutineWitness(..) - | ty::Alias(..) - | ty::Error(_) => false, - } - } - - /// If `self` is a primitive, return its [`Symbol`]. - pub fn primitive_symbol(self) -> Option { - match self.kind() { - ty::Bool => Some(sym::bool), - ty::Char => Some(sym::char), - ty::Float(f) => match f { - ty::FloatTy::F16 => Some(sym::f16), - ty::FloatTy::F32 => Some(sym::f32), - ty::FloatTy::F64 => Some(sym::f64), - ty::FloatTy::F128 => Some(sym::f128), - }, - ty::Int(f) => match f { - ty::IntTy::Isize => Some(sym::isize), - ty::IntTy::I8 => Some(sym::i8), - ty::IntTy::I16 => Some(sym::i16), - ty::IntTy::I32 => Some(sym::i32), - ty::IntTy::I64 => Some(sym::i64), - ty::IntTy::I128 => Some(sym::i128), - }, - ty::Uint(f) => match f { - ty::UintTy::Usize => Some(sym::usize), - ty::UintTy::U8 => Some(sym::u8), - ty::UintTy::U16 => Some(sym::u16), - ty::UintTy::U32 => Some(sym::u32), - ty::UintTy::U64 => Some(sym::u64), - ty::UintTy::U128 => Some(sym::u128), - }, - ty::Str => Some(sym::str), - _ => None, - } - } - - pub fn is_c_void(self, tcx: TyCtxt<'_>) -> bool { - match self.kind() { - ty::Adt(adt, _) => tcx.is_lang_item(adt.did(), LangItem::CVoid), - _ => false, - } - } - - pub fn is_async_drop_in_place_coroutine(self, tcx: TyCtxt<'_>) -> bool { - match self.kind() { - ty::Coroutine(def, ..) => tcx.is_async_drop_in_place_coroutine(*def), - _ => false, - } - } - - /// Returns `true` when the outermost type cannot be further normalized, - /// resolved, or instantiated. This includes all primitive types, but also - /// things like ADTs and trait objects, since even if their arguments or - /// nested types may be further simplified, the outermost [`TyKind`] or - /// type constructor remains the same. - pub fn is_known_rigid(self) -> bool { - self.kind().is_known_rigid() - } - - /// Iterator that walks `self` and any types reachable from - /// `self`, in depth-first order. Note that just walks the types - /// that appear in `self`, it does not descend into the fields of - /// structs or variants. For example: - /// - /// ```text - /// isize => { isize } - /// Foo> => { Foo>, Bar, isize } - /// [isize] => { [isize], isize } - /// ``` - pub fn walk(self) -> TypeWalker> { - TypeWalker::new(self.into()) - } -} - impl<'tcx> rustc_type_ir::inherent::Tys> for &'tcx ty::List> { fn inputs(self) -> &'tcx [Ty<'tcx>] { self.split_last().unwrap().1 diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index c620b67ad26d8..ab9a1ddac2b6b 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -636,20 +636,6 @@ impl<'tcx> TyCtxt<'tcx> { matches!(self.def_kind(def_id), DefKind::Ctor(..)) } - /// Given the `DefId`, returns the `DefId` of the innermost item that - /// has its own type-checking context or "inference environment". - /// - /// For example, a closure has its own `DefId`, but it is type-checked - /// with the containing item. Therefore, when we fetch the `typeck` of the closure, - /// for example, we really wind up fetching the `typeck` of the enclosing fn item. - pub fn typeck_root_def_id(self, def_id: DefId) -> DefId { - let mut def_id = def_id; - while self.is_typeck_child(def_id) { - def_id = self.parent(def_id); - } - def_id - } - /// 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 diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 0960859fb2a4f..3f3eb5e08aa47 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -104,6 +104,7 @@ use rustc_data_structures::hash_table::{Entry, HashTable}; use rustc_hir::def::DefKind; use rustc_index::bit_set::DenseBitSet; use rustc_index::{IndexVec, newtype_index}; +use rustc_infer::traits::ObligationCause; use rustc_middle::bug; use rustc_middle::mir::interpret::{AllocRange, GlobalAlloc}; use rustc_middle::mir::visit::*; @@ -1622,8 +1623,10 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { } fn pointers_have_same_metadata(&self, left_ptr_ty: Ty<'tcx>, right_ptr_ty: Ty<'tcx>) -> bool { - let left_meta_ty = left_ptr_ty.pointee_metadata_ty_or_projection(self.tcx); - let right_meta_ty = right_ptr_ty.pointee_metadata_ty_or_projection(self.tcx); + let left_meta_ty = + left_ptr_ty.pointee_metadata_ty_or_projection(&ObligationCause::dummy(), self.tcx); + let right_meta_ty = + right_ptr_ty.pointee_metadata_ty_or_projection(&ObligationCause::dummy(), self.tcx); if left_meta_ty == right_meta_ty { true } else if let Ok(left) = diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index ce2be24adc586..25bc25814e4a5 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -3,7 +3,7 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::solve::{Goal, QueryInput}; use rustc_type_ir::{ self as ty, Canonical, CanonicalParamEnvCacheEntry, CanonicalVarKind, Flags, InferCtxtLike, - Interner, PlaceholderConst, PlaceholderType, TypeFlags, TypeFoldable, TypeFolder, + Interner, PlaceholderConst, PlaceholderType, Ty, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; @@ -78,7 +78,7 @@ pub(super) struct Canonicalizer<'a, D: SolverDelegate, I: Interner /// We can simply cache based on the ty itself, because we use /// `ty::BoundVarIndexKind::Canonical`. - cache: HashMap, + cache: HashMap, Ty>, } impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { @@ -316,7 +316,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { (max_universe, self.variables, var_kinds) } - fn inner_fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn inner_fold_ty(&mut self, t: Ty) -> Ty { let kind = match t.kind() { ty::Infer(i) => match i { ty::TyVar(vid) => { @@ -475,7 +475,7 @@ impl, I: Interner> TypeFolder for Canonicaliz Region::new_canonical_bound(self.cx(), var) } - fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn fold_ty(&mut self, t: Ty) -> Ty { if !t.flags().intersects(NEEDS_CANONICAL) { t } else if let Some(&ty) = self.cache.get(&t) { diff --git a/compiler/rustc_next_trait_solver/src/canonical/mod.rs b/compiler/rustc_next_trait_solver/src/canonical/mod.rs index 1f64f09fe787f..cd42bf8b57b60 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/mod.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/mod.rs @@ -16,7 +16,7 @@ use rustc_index::IndexVec; use rustc_type_ir::inherent::*; use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::{ - self as ty, Canonical, CanonicalVarKind, CanonicalVarValues, InferCtxtLike, Interner, + self as ty, Canonical, CanonicalVarKind, CanonicalVarValues, InferCtxtLike, Interner, Ty, TypeFoldable, }; use tracing::instrument; @@ -53,7 +53,7 @@ impl ResponseT for inspect::State { pub(super) fn canonicalize_goal( delegate: &D, goal: Goal, - opaque_types: &[(ty::OpaqueTypeKey, I::Ty)], + opaque_types: &[(ty::OpaqueTypeKey, Ty)], ) -> (Vec, CanonicalInput) where D: SolverDelegate, @@ -264,7 +264,7 @@ fn register_region_constraints( fn register_new_opaque_types( delegate: &D, - opaque_types: &[(ty::OpaqueTypeKey, I::Ty)], + opaque_types: &[(ty::OpaqueTypeKey, Ty)], span: I::Span, ) where D: SolverDelegate, diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs index c370fd24a1bb3..8c03d82d02c4b 100644 --- a/compiler/rustc_next_trait_solver/src/coherence.rs +++ b/compiler/rustc_next_trait_solver/src/coherence.rs @@ -4,7 +4,7 @@ use std::ops::ControlFlow; use derive_where::derive_where; use rustc_type_ir::inherent::*; use rustc_type_ir::{ - self as ty, InferCtxtLike, Interner, TrivialTypeTraversalImpls, TypeVisitable, + self as ty, InferCtxtLike, Interner, TrivialTypeTraversalImpls, Ty, TypeVisitable, TypeVisitableExt, TypeVisitor, }; use tracing::instrument; @@ -47,7 +47,7 @@ pub enum Conflict { pub fn trait_ref_is_knowable( infcx: &Infcx, trait_ref: ty::TraitRef, - mut lazily_normalize_ty: impl FnMut(I::Ty) -> Result, + mut lazily_normalize_ty: impl FnMut(Ty) -> Result, E>, ) -> Result, E> where Infcx: InferCtxtLike, @@ -115,14 +115,14 @@ impl From for IsFirstInputType { #[derive_where(Debug; I: Interner, T: Debug)] pub enum OrphanCheckErr { - NonLocalInputType(Vec<(I::Ty, IsFirstInputType)>), + NonLocalInputType(Vec<(Ty, IsFirstInputType)>), UncoveredTyParams(UncoveredTyParams), } #[derive_where(Debug; I: Interner, T: Debug)] pub struct UncoveredTyParams { pub uncovered: T, - pub local_ty: Option, + pub local_ty: Option>, } /// Checks whether a trait-ref is potentially implementable by a crate. @@ -222,8 +222,8 @@ pub fn orphan_check_trait_ref( infcx: &Infcx, trait_ref: ty::TraitRef, in_crate: InCrate, - lazily_normalize_ty: impl FnMut(I::Ty) -> Result, -) -> Result>, E> + lazily_normalize_ty: impl FnMut(Ty) -> Result, E>, +) -> Result>>, E> where Infcx: InferCtxtLike, I: Interner, @@ -262,14 +262,14 @@ struct OrphanChecker<'a, Infcx, I: Interner, F> { lazily_normalize_ty: F, /// Ignore orphan check failures and exclusively search for the first local type. search_first_local_ty: bool, - non_local_tys: Vec<(I::Ty, IsFirstInputType)>, + non_local_tys: Vec<(Ty, IsFirstInputType)>, } impl<'a, Infcx, I, F, E> OrphanChecker<'a, Infcx, I, F> where Infcx: InferCtxtLike, I: Interner, - F: FnOnce(I::Ty) -> Result, + F: FnOnce(Ty) -> Result, E>, { fn new(infcx: &'a Infcx, in_crate: InCrate, lazily_normalize_ty: F) -> Self { OrphanChecker { @@ -282,12 +282,12 @@ where } } - fn found_non_local_ty(&mut self, t: I::Ty) -> ControlFlow> { + fn found_non_local_ty(&mut self, t: Ty) -> ControlFlow> { self.non_local_tys.push((t, self.in_self_ty.into())); ControlFlow::Continue(()) } - fn found_uncovered_ty_param(&mut self, ty: I::Ty) -> ControlFlow> { + fn found_uncovered_ty_param(&mut self, ty: Ty) -> ControlFlow> { if self.search_first_local_ty { return ControlFlow::Continue(()); } @@ -305,15 +305,15 @@ where enum OrphanCheckEarlyExit { NormalizationFailure(E), - UncoveredTyParam(I::Ty), - LocalTy(I::Ty), + UncoveredTyParam(Ty), + LocalTy(Ty), } impl<'a, Infcx, I, F, E> TypeVisitor for OrphanChecker<'a, Infcx, I, F> where Infcx: InferCtxtLike, I: Interner, - F: FnMut(I::Ty) -> Result, + F: FnMut(Ty) -> Result, E>, { type Result = ControlFlow>; @@ -321,7 +321,7 @@ where ControlFlow::Continue(()) } - fn visit_ty(&mut self, ty: I::Ty) -> Self::Result { + fn visit_ty(&mut self, ty: Ty) -> Self::Result { let ty = self.infcx.shallow_resolve(ty); let ty = match (self.lazily_normalize_ty)(ty) { Ok(norm_ty) if norm_ty.is_ty_var() => ty, diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index 9d5aa8bc124b6..1714ae3dd6b2e 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -1,7 +1,7 @@ use std::ops::Deref; use rustc_type_ir::solve::{Certainty, Goal, NoSolution}; -use rustc_type_ir::{self as ty, InferCtxtLike, Interner, TypeFoldable}; +use rustc_type_ir::{self as ty, InferCtxtLike, Interner, Ty, TypeFoldable}; pub trait SolverDelegate: Deref + Sized { type Infcx: InferCtxtLike; @@ -70,7 +70,7 @@ pub trait SolverDelegate: Deref + Sized { def_id: ::DefId, args: ::GenericArgs, param_env: ::ParamEnv, - hidden_ty: ::Ty, + hidden_ty: Ty, goals: &mut Vec::Predicate>>, ); @@ -86,8 +86,8 @@ pub trait SolverDelegate: Deref + Sized { fn is_transmutable( &self, - src: ::Ty, - dst: ::Ty, + src: Ty, + dst: Ty, assume: ::Const, ) -> Result; } diff --git a/compiler/rustc_next_trait_solver/src/placeholder.rs b/compiler/rustc_next_trait_solver/src/placeholder.rs index 83f3bdf01dc83..2ae090ca5768b 100644 --- a/compiler/rustc_next_trait_solver/src/placeholder.rs +++ b/compiler/rustc_next_trait_solver/src/placeholder.rs @@ -3,7 +3,7 @@ use core::panic; use rustc_type_ir::data_structures::IndexMap; use rustc_type_ir::inherent::*; use rustc_type_ir::{ - self as ty, InferCtxtLike, Interner, PlaceholderConst, PlaceholderRegion, PlaceholderType, + self as ty, InferCtxtLike, Interner, PlaceholderConst, PlaceholderRegion, PlaceholderType, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; @@ -113,7 +113,7 @@ where } } - fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn fold_ty(&mut self, t: Ty) -> Ty { match t.kind() { ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), _) if debruijn.as_usize() + 1 diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs index c3c57eccd6eff..86bf05bdb57cc 100644 --- a/compiler/rustc_next_trait_solver/src/resolve.rs +++ b/compiler/rustc_next_trait_solver/src/resolve.rs @@ -1,7 +1,7 @@ use rustc_type_ir::data_structures::DelayedMap; use rustc_type_ir::inherent::*; use rustc_type_ir::{ - self as ty, InferCtxtLike, Interner, TypeFoldable, TypeFolder, TypeSuperFoldable, + self as ty, InferCtxtLike, Interner, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; @@ -19,7 +19,7 @@ where delegate: &'a D, /// We're able to use a cache here as the folder does not have any /// mutable state. - cache: DelayedMap, + cache: DelayedMap, Ty>, } pub fn eager_resolve_vars>( @@ -45,7 +45,7 @@ impl, I: Interner> TypeFolder for EagerResolv self.delegate.cx() } - fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn fold_ty(&mut self, t: Ty) -> Ty { match t.kind() { ty::Infer(ty::TyVar(vid)) => { let resolved = self.delegate.opportunistic_resolve_ty_var(vid); diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 038168ca638b4..5794c5d6aa249 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -11,7 +11,7 @@ use rustc_type_ir::lang_items::SolverTraitLangItem; use rustc_type_ir::search_graph::CandidateHeadUsages; use rustc_type_ir::solve::{AliasBoundKind, SizedTraitKind}; use rustc_type_ir::{ - self as ty, Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, + self as ty, Interner, Ty, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast, elaborate, }; @@ -45,11 +45,11 @@ where D: SolverDelegate, I: Interner, { - fn self_ty(self) -> I::Ty; + fn self_ty(self) -> Ty; fn trait_ref(self, cx: I) -> ty::TraitRef; - fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self; + fn with_replaced_self_ty(self, cx: I, self_ty: Ty) -> Self; fn trait_def_id(self, cx: I) -> I::TraitId; @@ -680,7 +680,7 @@ where // hitting another overflow error something. Add a depth parameter needed later. fn assemble_alias_bound_candidates_recur>( &mut self, - self_ty: I::Ty, + self_ty: Ty, goal: Goal, candidates: &mut Vec>, consider_self_bounds: AliasBoundKind, @@ -1014,13 +1014,13 @@ where struct ReplaceOpaque { cx: I, alias_ty: ty::AliasTy, - self_ty: I::Ty, + self_ty: Ty, } impl TypeFolder for ReplaceOpaque { fn cx(&self) -> I { self.cx } - fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { + fn fold_ty(&mut self, ty: Ty) -> Ty { if let ty::Alias(ty::Opaque, alias_ty) = ty.kind() { if alias_ty == self.alias_ty { return self.self_ty; @@ -1267,7 +1267,7 @@ where ControlFlow::Continue(()) } - fn visit_ty(&mut self, ty: I::Ty) -> Self::Result { + fn visit_ty(&mut self, ty: Ty) -> Self::Result { let ty = self.ecx.replace_bound_vars(ty, &mut self.universes); let Ok(ty) = self.ecx.structurally_normalize_ty(self.param_env, ty) else { return ControlFlow::Break(Err(NoSolution)); diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 05ea217c1de08..4136660528731 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -8,7 +8,7 @@ use rustc_type_ir::lang_items::{SolverLangItem, SolverTraitLangItem}; use rustc_type_ir::solve::SizedTraitKind; use rustc_type_ir::solve::inspect::ProbeKind; use rustc_type_ir::{ - self as ty, FallibleTypeFolder, Interner, Movability, Mutability, TypeFoldable, + self as ty, FallibleTypeFolder, Interner, Movability, Mutability, Ty, TypeFoldable, TypeSuperFoldable, Upcast as _, elaborate, }; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; @@ -21,8 +21,8 @@ use crate::solve::{AdtDestructorKind, EvalCtxt, Goal, NoSolution}; #[instrument(level = "trace", skip(ecx), ret)] pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait( ecx: &EvalCtxt<'_, D>, - ty: I::Ty, -) -> Result>, NoSolution> + ty: Ty, +) -> Result>>, NoSolution> where D: SolverDelegate, I: Interner, @@ -108,8 +108,8 @@ where pub(in crate::solve) fn instantiate_constituent_tys_for_sizedness_trait( ecx: &EvalCtxt<'_, D>, sizedness: SizedTraitKind, - ty: I::Ty, -) -> Result>, NoSolution> + ty: Ty, +) -> Result>>, NoSolution> where D: SolverDelegate, I: Interner, @@ -186,8 +186,8 @@ where #[instrument(level = "trace", skip(ecx), ret)] pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait( ecx: &EvalCtxt<'_, D>, - ty: I::Ty, -) -> Result>, NoSolution> + ty: Ty, +) -> Result>>, NoSolution> where D: SolverDelegate, I: Interner, @@ -268,9 +268,9 @@ where // Returns a binder of the tupled inputs types and output type from a builtin callable type. pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable( cx: I, - self_ty: I::Ty, + self_ty: Ty, goal_kind: ty::ClosureKind, -) -> Result>, NoSolution> { +) -> Result, Ty)>>, NoSolution> { match self_ty.kind() { // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed. ty::FnDef(def_id, args) => { @@ -408,13 +408,13 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable { - pub tupled_inputs_ty: I::Ty, + pub tupled_inputs_ty: Ty, /// Type returned by calling the closure /// i.e. `f()`. - pub output_coroutine_ty: I::Ty, + pub output_coroutine_ty: Ty, /// Type returned by `await`ing the output /// i.e. `f().await`. - pub coroutine_return_ty: I::Ty, + pub coroutine_return_ty: Ty, } // Returns a binder of the tupled inputs types, output type, and coroutine type @@ -424,7 +424,7 @@ pub(in crate::solve) struct AsyncCallableRelevantTypes { // know the kind already, we can short-circuit this check. pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable( cx: I, - self_ty: I::Ty, + self_ty: Ty, goal_kind: ty::ClosureKind, env_region: I::Region, ) -> Result<(ty::Binder>, Vec), NoSolution> { @@ -608,7 +608,7 @@ fn coroutine_closure_to_certain_coroutine( def_id: I::CoroutineClosureId, args: ty::CoroutineClosureArgs, sig: ty::CoroutineClosureSignature, -) -> I::Ty { +) -> Ty { sig.to_coroutine_given_kind_and_upvars( cx, args.parent_args(), @@ -632,7 +632,7 @@ fn coroutine_closure_to_ambiguous_coroutine( def_id: I::CoroutineClosureId, args: ty::CoroutineClosureArgs, sig: ty::CoroutineClosureSignature, -) -> I::Ty { +) -> Ty { let upvars_projection_def_id = cx.require_lang_item(SolverLangItem::AsyncFnKindUpvars); let tupled_upvars_ty = Ty::new_projection( cx, @@ -663,8 +663,8 @@ fn coroutine_closure_to_ambiguous_coroutine( /// would be wasteful. pub(in crate::solve) fn extract_fn_def_from_const_callable( cx: I, - self_ty: I::Ty, -) -> Result<(ty::Binder, I::FunctionId, I::GenericArgs), NoSolution> { + self_ty: Ty, +) -> Result<(ty::Binder, Ty)>, I::FunctionId, I::GenericArgs), NoSolution> { match self_ty.kind() { ty::FnDef(def_id, args) => { let sig = cx.fn_sig(def_id); @@ -731,7 +731,7 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable( // the old solver, for as long as that exists. pub(in crate::solve) fn const_conditions_for_destruct( cx: I, - self_ty: I::Ty, + self_ty: Ty, ) -> Result>, NoSolution> { let destruct_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Destruct); @@ -912,7 +912,7 @@ where struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate> { ecx: &'a mut EvalCtxt<'b, D>, param_env: I::ParamEnv, - self_ty: I::Ty, + self_ty: Ty, mapping: &'a HashMap>>>, nested: Vec>, } @@ -998,7 +998,7 @@ where self.ecx.cx() } - fn try_fold_ty(&mut self, ty: I::Ty) -> Result { + fn try_fold_ty(&mut self, ty: Ty) -> Result, Ambiguous> { if let ty::Alias(ty::Projection, alias_ty) = ty.kind() && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())? { diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 4da76b88b5de0..358f26e696208 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -6,7 +6,7 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::SolverTraitLangItem; use rustc_type_ir::solve::inspect::ProbeKind; use rustc_type_ir::solve::{AliasBoundKind, SizedTraitKind}; -use rustc_type_ir::{self as ty, Interner, TypingMode, elaborate}; +use rustc_type_ir::{self as ty, Interner, Ty, TypingMode, elaborate}; use tracing::instrument; use super::assembly::{Candidate, structural_traits}; @@ -21,7 +21,7 @@ where D: SolverDelegate, I: Interner, { - fn self_ty(self) -> I::Ty { + fn self_ty(self) -> Ty { self.self_ty() } @@ -29,7 +29,7 @@ where self.trait_ref } - fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self { + fn with_replaced_self_ty(self, cx: I, self_ty: Ty) -> Self { self.with_replaced_self_ty(cx, self_ty) } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 6841fe1c5124e..d6ed220909732 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -10,7 +10,7 @@ use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::search_graph::{CandidateHeadUsages, PathKind}; use rustc_type_ir::solve::OpaqueTypesJank; use rustc_type_ir::{ - self as ty, CanonicalVarValues, InferCtxtLike, Interner, TypeFoldable, TypeFolder, + self as ty, CanonicalVarValues, InferCtxtLike, Interner, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, }; @@ -781,7 +781,7 @@ where region } - pub(super) fn next_ty_infer(&mut self) -> I::Ty { + pub(super) fn next_ty_infer(&mut self) -> Ty { let ty = self.delegate.next_ty_infer(); self.inspect.add_var_value(ty); ty @@ -829,7 +829,7 @@ where term: I::Term, universe_of_term: ty::UniverseIndex, delegate: &'a D, - cache: HashSet, + cache: HashSet>, } impl, I: Interner> ContainsTermOrNotNameable<'_, D, I> { @@ -846,7 +846,7 @@ where for ContainsTermOrNotNameable<'_, D, I> { type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: I::Ty) -> Self::Result { + fn visit_ty(&mut self, t: Ty) -> Self::Result { if self.cache.contains(&t) { return ControlFlow::Continue(()); } @@ -1072,7 +1072,7 @@ where self.delegate.resolve_vars_if_possible(value) } - pub(super) fn shallow_resolve(&self, ty: I::Ty) -> I::Ty { + pub(super) fn shallow_resolve(&self, ty: Ty) -> Ty { self.delegate.shallow_resolve(ty) } @@ -1092,7 +1092,7 @@ where args } - pub(super) fn register_ty_outlives(&self, ty: I::Ty, lt: I::Region) { + pub(super) fn register_ty_outlives(&self, ty: Ty, lt: I::Region) { self.delegate.register_ty_outlives(ty, lt, self.origin_span); } @@ -1134,8 +1134,8 @@ where pub(super) fn register_hidden_type_in_storage( &mut self, opaque_type_key: ty::OpaqueTypeKey, - hidden_ty: I::Ty, - ) -> Option { + hidden_ty: Ty, + ) -> Option> { self.delegate.register_hidden_type_in_storage(opaque_type_key, hidden_ty, self.origin_span) } @@ -1144,7 +1144,7 @@ where opaque_def_id: I::DefId, opaque_args: I::GenericArgs, param_env: I::ParamEnv, - hidden_ty: I::Ty, + hidden_ty: Ty, ) { let mut goals = Vec::new(); self.delegate.add_item_bounds_for_hidden_type( @@ -1170,8 +1170,8 @@ where pub(super) fn is_transmutable( &mut self, - src: I::Ty, - dst: I::Ty, + src: Ty, + dst: Ty, assume: I::Const, ) -> Result { self.delegate.is_transmutable(dst, src, assume) @@ -1195,7 +1195,7 @@ where pub(crate) fn opaques_with_sub_unified_hidden_type( &self, - self_ty: I::Ty, + self_ty: Ty, ) -> Vec> { if let ty::Infer(ty::TyVar(vid)) = self_ty.kind() { self.delegate.opaques_with_sub_unified_hidden_type(vid) @@ -1389,7 +1389,7 @@ where ecx: &'me mut EvalCtxt<'a, D>, param_env: I::ParamEnv, normalization_goal_source: GoalSource, - cache: HashMap, + cache: HashMap, Ty>, } impl<'me, 'a, D, I> ReplaceAliasWithInfer<'me, 'a, D, I> @@ -1421,7 +1421,7 @@ where self.ecx.cx() } - fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { + fn fold_ty(&mut self, ty: Ty) -> Ty { match ty.kind() { ty::Alias(..) if !ty.has_escaping_bound_vars() => { let infer_ty = self.ecx.next_ty_infer(); diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 58bd7cf663d98..71b28cf1ad277 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -24,7 +24,7 @@ mod trait_goals; use derive_where::derive_where; use rustc_type_ir::inherent::*; pub use rustc_type_ir::solve::*; -use rustc_type_ir::{self as ty, Interner, TyVid, TypingMode}; +use rustc_type_ir::{self as ty, Interner, Ty, TyVid, TypingMode}; use tracing::instrument; pub use self::eval_ctxt::{ @@ -88,7 +88,7 @@ where #[instrument(level = "trace", skip(self))] fn compute_type_outlives_goal( &mut self, - goal: Goal>, + goal: Goal>>, ) -> QueryResult { let ty::OutlivesPredicate(ty, lt) = goal.predicate; self.register_ty_outlives(ty, lt); @@ -205,7 +205,7 @@ where #[instrument(level = "trace", skip(self), ret)] fn compute_const_arg_has_type_goal( &mut self, - goal: Goal, + goal: Goal)>, ) -> QueryResult { let (ct, ty) = goal.predicate; let ct = self.structurally_normalize_const(goal.param_env, ct)?; @@ -315,8 +315,8 @@ where fn structurally_normalize_ty( &mut self, param_env: I::ParamEnv, - ty: I::Ty, - ) -> Result { + ty: Ty, + ) -> Result, NoSolution> { self.structurally_normalize_term(param_env, ty.into()).map(|term| term.expect_ty()) } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 13f2ad8f82eba..b84ced070aae7 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -7,7 +7,9 @@ use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem}; use rustc_type_ir::solve::SizedTraitKind; -use rustc_type_ir::{self as ty, FieldInfo, Interner, NormalizesTo, PredicateKind, Upcast as _}; +use rustc_type_ir::{ + self as ty, FieldInfo, Interner, NormalizesTo, PredicateKind, Ty, Upcast as _, +}; use tracing::instrument; use crate::delegate::SolverDelegate; @@ -125,7 +127,7 @@ where D: SolverDelegate, I: Interner, { - fn self_ty(self) -> I::Ty { + fn self_ty(self) -> Ty { self.self_ty() } @@ -133,7 +135,7 @@ where self.alias.trait_ref(cx) } - fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self { + fn with_replaced_self_ty(self, cx: I, self_ty: Ty) -> Self { self.with_replaced_self_ty(cx, self_ty) } @@ -805,10 +807,10 @@ where // coroutine yield ty `Poll>`. let wrapped_expected_ty = Ty::new_adt( cx, - cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Poll)), + cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Poll).into()), cx.mk_args(&[Ty::new_adt( cx, - cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Option)), + cx.adt_def(cx.require_adt_lang_item(SolverAdtLangItem::Option).into()), cx.mk_args(&[expected_ty.into()]), ) .into()]), diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 6589a12c4cc2d..1b754253d21f9 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -8,7 +8,7 @@ use rustc_type_ir::solve::{ AliasBoundKind, CandidatePreferenceMode, CanonicalResponse, SizedTraitKind, }; use rustc_type_ir::{ - self as ty, FieldInfo, Interner, Movability, PredicatePolarity, TraitPredicate, TraitRef, + self as ty, FieldInfo, Interner, Movability, PredicatePolarity, TraitPredicate, TraitRef, Ty, TypeVisitableExt as _, TypingMode, Upcast as _, elaborate, }; use tracing::{debug, instrument, trace}; @@ -29,7 +29,7 @@ where D: SolverDelegate, I: Interner, { - fn self_ty(self) -> I::Ty { + fn self_ty(self) -> Ty { self.self_ty() } @@ -37,7 +37,7 @@ where self.trait_ref } - fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self { + fn with_replaced_self_ty(self, cx: I, self_ty: Ty) -> Self { self.with_replaced_self_ty(cx, self_ty) } @@ -929,7 +929,7 @@ where /// ``` fn consider_builtin_dyn_upcast_candidates( &mut self, - goal: Goal, + goal: Goal, Ty)>, a_data: I::BoundExistentialPredicates, a_region: I::Region, b_data: I::BoundExistentialPredicates, @@ -977,7 +977,7 @@ where fn consider_builtin_unsize_to_dyn_candidate( &mut self, - goal: Goal, + goal: Goal, Ty)>, b_data: I::BoundExistentialPredicates, b_region: I::Region, ) -> Result, NoSolution> { @@ -1018,7 +1018,7 @@ where fn consider_builtin_upcast_to_principal( &mut self, - goal: Goal, + goal: Goal, Ty)>, source: CandidateSource, a_data: I::BoundExistentialPredicates, a_region: I::Region, @@ -1132,9 +1132,9 @@ where /// `#[rustc_deny_explicit_impl]` in this case. fn consider_builtin_array_unsize( &mut self, - goal: Goal, - a_elem_ty: I::Ty, - b_elem_ty: I::Ty, + goal: Goal, Ty)>, + a_elem_ty: Ty, + b_elem_ty: Ty, ) -> Result, NoSolution> { self.eq(goal.param_env, a_elem_ty, b_elem_ty)?; self.probe_builtin_trait_candidate(BuiltinImplSource::Misc) @@ -1156,7 +1156,7 @@ where /// ``` fn consider_builtin_struct_unsize( &mut self, - goal: Goal, + goal: Goal, Ty)>, def: I::AdtDef, a_args: I::GenericArgs, b_args: I::GenericArgs, @@ -1319,8 +1319,8 @@ where goal: Goal>, constituent_tys: impl Fn( &EvalCtxt<'_, D>, - I::Ty, - ) -> Result>, NoSolution>, + Ty, + ) -> Result>>, NoSolution>, ) -> Result, NoSolution> { self.probe_trait_candidate(source).enter(|ecx| { let goals = @@ -1542,7 +1542,7 @@ where self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info) } - fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option, NoSolution>> { + fn try_stall_coroutine(&mut self, self_ty: Ty) -> Option, NoSolution>> { if let ty::Coroutine(def_id, _) = self_ty.kind() { match self.typing_mode() { TypingMode::Analysis { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 364152475e94d..2be1a408ea92d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1139,7 +1139,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.note_missing_impl_for_question_mark(err, self_ty, found_ty, trait_pred); let mut prev_ty = self.resolve_vars_if_possible( - typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)), + typeck.expr_ty_adjusted_opt(expr).unwrap_or(self.tcx.new_misc_error()), ); // We always look at the `E` type, because that's the only one affected by `?`. If the @@ -1171,7 +1171,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { chain.push((span, prev_ty)); let next_ty = self.resolve_vars_if_possible( - typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)), + typeck.expr_ty_adjusted_opt(expr).unwrap_or(self.tcx.new_misc_error()), ); let is_diagnostic_item = |symbol: Symbol, ty: Ty<'tcx>| { @@ -1215,7 +1215,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && let hir::StmtKind::Semi(expr) = stmt.kind && let expr_ty = self.resolve_vars_if_possible( typeck.expr_ty_adjusted_opt(expr) - .unwrap_or(Ty::new_misc_error(self.tcx)), + .unwrap_or(self.tcx.new_misc_error()), ) && self .infcx @@ -1259,7 +1259,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // expression kind, like a method call or a path. If this expression is `Result` as // well, then we also point at it. prev_ty = self.resolve_vars_if_possible( - typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)), + typeck.expr_ty_adjusted_opt(expr).unwrap_or(self.tcx.new_misc_error()), ); chain.push((expr.span, prev_ty)); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 814333859488f..87aed578c8820 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4190,9 +4190,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } if let hir::Expr { kind: hir::ExprKind::Block(block, _), .. } = expr { let inner_expr = expr.peel_blocks(); - let ty = typeck_results - .expr_ty_adjusted_opt(inner_expr) - .unwrap_or(Ty::new_misc_error(tcx)); + let ty = + typeck_results.expr_ty_adjusted_opt(inner_expr).unwrap_or(tcx.new_misc_error()); let span = inner_expr.span; if Some(span) != err.span.primary_span() && !span.in_external_macro(tcx.sess.source_map()) @@ -4589,7 +4588,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut assocs = vec![]; let mut expr = expr; let mut prev_ty = self.resolve_vars_if_possible( - typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)), + typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.new_misc_error()), ); while let hir::ExprKind::MethodCall(path_segment, rcvr_expr, args, span) = expr.kind { // Point at every method call in the chain with the resulting type. @@ -4599,7 +4598,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let assocs_in_this_method = self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env); prev_ty = self.resolve_vars_if_possible( - typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)), + typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.new_misc_error()), ); self.look_for_iterator_item_mistakes( &assocs_in_this_method, @@ -4628,9 +4627,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let hir::Node::Param(param) = parent { // ...and it is an fn argument. let prev_ty = self.resolve_vars_if_possible( - typeck_results - .node_type_opt(param.hir_id) - .unwrap_or(Ty::new_misc_error(tcx)), + typeck_results.node_type_opt(param.hir_id).unwrap_or(tcx.new_misc_error()), ); let assocs_in_this_method = self.probe_assoc_types_at_expr( &type_diffs, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 3df5c9e33438a..295ff337b4ae9 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1528,25 +1528,27 @@ fn confirm_builtin_candidate<'cx, 'tcx>( &mut obligations, ) }; - let metadata_ty = self_ty.ptr_metadata_ty_or_tail(tcx, normalize).unwrap_or_else(|tail| { - if tail == self_ty { - // This is the "fallback impl" for type parameters, unnormalizable projections - // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`. - // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't - // exist. Instead, `Pointee` should be a supertrait of `Sized`. - let sized_predicate = ty::TraitRef::new( - tcx, - tcx.require_lang_item(LangItem::Sized, obligation.cause.span), - [self_ty], - ); - obligations.push(obligation.with(tcx, sized_predicate)); - tcx.types.unit - } else { - // We know that `self_ty` has the same metadata as `tail`. This allows us - // to prove predicates like `Wrapper::Metadata == Tail::Metadata`. - Ty::new_projection(tcx, metadata_def_id, [tail]) - } - }); + let metadata_ty = self_ty + .ptr_metadata_ty_or_tail(tcx, &ObligationCause::dummy(), normalize) + .unwrap_or_else(|tail| { + if tail == self_ty { + // This is the "fallback impl" for type parameters, unnormalizable projections + // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`. + // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't + // exist. Instead, `Pointee` should be a supertrait of `Sized`. + let sized_predicate = ty::TraitRef::new( + tcx, + tcx.require_lang_item(LangItem::Sized, obligation.cause.span), + [self_ty], + ); + obligations.push(obligation.with(tcx, sized_predicate)); + tcx.types.unit + } else { + // We know that `self_ty` has the same metadata as `tail`. This allows us + // to prove predicates like `Wrapper::Metadata == Tail::Metadata`. + Ty::new_projection(tcx, metadata_def_id, [tail]) + } + }); (metadata_ty.into(), obligations) } else if tcx.is_lang_item(trait_def_id, LangItem::Field) { let ty::Adt(def, args) = self_ty.kind() else { @@ -1973,7 +1975,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( "Failed to unify obligation `{obligation:?}` with poly_projection `{poly_cache_entry:?}`: {e:?}", ); debug!("confirm_param_env_candidate: {}", msg); - let err = Ty::new_error_with_message(infcx.tcx, obligation.cause.span, msg); + let err = infcx.tcx.new_error_with_message(obligation.cause.span, msg); Progress { term: err.into(), obligations: PredicateObligations::new() } } } @@ -2024,7 +2026,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( } else { return Ok(Projected::Progress(Progress { term: if obligation.predicate.kind(tcx).is_type() { - Ty::new_misc_error(tcx).into() + tcx.new_misc_error().into() } else { ty::Const::new_misc_error(tcx).into() }, @@ -2052,7 +2054,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( let msg = "impl item and trait item have different parameters"; let span = obligation.cause.span; let err = if obligation.predicate.kind(tcx).is_type() { - Ty::new_error_with_message(tcx, span, msg).into() + tcx.new_error_with_message(span, msg).into() } else { ty::Const::new_error_with_message(tcx, span, msg).into() }; diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 2f83ee046498a..ad859b6685a76 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -243,11 +243,8 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { let mut concrete_ty = generic_ty.instantiate(self.cx(), args); self.anon_depth += 1; if concrete_ty == ty { - concrete_ty = Ty::new_error_with_message( - self.cx(), - DUMMY_SP, - "recursive opaque type", - ); + concrete_ty = + self.cx().new_error_with_message(DUMMY_SP, "recursive opaque type"); } let folded_ty = ensure_sufficient_stack(|| self.try_fold_ty(concrete_ty)); self.anon_depth -= 1; diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 78f3a19228870..78a71349f9f6f 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -355,8 +355,7 @@ fn impl_self_is_guaranteed_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_def_id: DefId) &cause, |ty| { ocx.structurally_normalize_ty(&cause, param_env, ty).unwrap_or_else(|_| { - Ty::new_error_with_message( - tcx, + tcx.new_error_with_message( tcx.def_span(impl_def_id), "struct tail should be computable", ) diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index fc8b39f7c01f0..20adc0fc239ed 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -1,11 +1,13 @@ -use std::fmt; +use std::fmt::{self, Debug}; use std::hash::Hash; use std::marker::PhantomData; -use std::ops::{ControlFlow, Deref}; +use std::ops::{ControlFlow, Deref, Range}; use derive_where::derive_where; +use rustc_abi::{FieldIdx, VariantIdx}; #[cfg(feature = "nightly")] use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; +use rustc_span::sym; use rustc_type_ir_macros::{ GenericTypeVisitable, Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic, }; @@ -14,9 +16,17 @@ use tracing::instrument; use crate::data_structures::SsoHashSet; use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; use crate::inherent::*; +use crate::lang_items::{SolverLangItem, SolverTraitLangItem}; use crate::lift::Lift; -use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; -use crate::{self as ty, DebruijnIndex, Interner, UniverseIndex}; +use crate::solve::SizedTraitKind; +use crate::visit::{ + Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, VisitorResult, +}; +use crate::walk::TypeWalker; +use crate::{ + self as ty, AliasTy, CollectAndApply, DebruijnIndex, Interner, Mutability, TyKind, TypeFlags, + UniverseIndex, WithCachedTypeInfo, try_visit, +}; /// `Binder` is a binder for higher-ranked lifetimes or types. It is part of the /// compiler's representation for things like `for<'a> Fn(&'a isize)` @@ -278,7 +288,7 @@ pub struct ValidateBoundVars { // We only cache types because any complex const will have to step through // a type at some point anyways. We may encounter the same variable at // different levels of binding, so this can't just be `Ty`. - visited: SsoHashSet<(ty::DebruijnIndex, I::Ty)>, + visited: SsoHashSet<(ty::DebruijnIndex, Ty)>, } impl ValidateBoundVars { @@ -301,7 +311,7 @@ impl TypeVisitor for ValidateBoundVars { result } - fn visit_ty(&mut self, t: I::Ty) -> Self::Result { + fn visit_ty(&mut self, t: Ty) -> Self::Result { if t.outer_exclusive_binder() < self.binder_index || !self.visited.insert((self.binder_index, t)) { @@ -372,10 +382,7 @@ impl TypeVisitor for ValidateBoundVars { #[derive_where(Copy; I: Interner, T: Copy)] #[derive_where(Clone, PartialOrd, PartialEq, Hash, Debug; I: Interner, T)] #[derive(GenericTypeVisitable)] -#[cfg_attr( - feature = "nightly", - derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) -)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub struct EarlyBinder { value: T, #[derive_where(skip(Debug))] @@ -733,7 +740,7 @@ impl<'a, I: Interner> TypeFolder for ArgFolder<'a, I> { } } - fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn fold_ty(&mut self, t: Ty) -> Ty { if !t.has_param() { return t; } @@ -762,7 +769,7 @@ impl<'a, I: Interner> TypeFolder for ArgFolder<'a, I> { } impl<'a, I: Interner> ArgFolder<'a, I> { - fn ty_for_param(&self, p: I::ParamTy, source_ty: I::Ty) -> I::Ty { + fn ty_for_param(&self, p: I::ParamTy, source_ty: Ty) -> Ty { // Look up the type in the args. It really should be in there. let opt_ty = self.args.get(p.index() as usize).map(|arg| arg.kind()); let ty = match opt_ty { @@ -776,7 +783,7 @@ impl<'a, I: Interner> ArgFolder<'a, I> { #[cold] #[inline(never)] - fn type_param_expected(&self, p: I::ParamTy, ty: I::Ty, kind: ty::GenericArgKind) -> ! { + fn type_param_expected(&self, p: I::ParamTy, ty: Ty, kind: ty::GenericArgKind) -> ! { panic!( "expected type for `{:?}` ({:?}/{}) but found {:?} when instantiating, args={:?}", p, @@ -789,7 +796,7 @@ impl<'a, I: Interner> ArgFolder<'a, I> { #[cold] #[inline(never)] - fn type_param_out_of_range(&self, p: I::ParamTy, ty: I::Ty) -> ! { + fn type_param_out_of_range(&self, p: I::ParamTy, ty: Ty) -> ! { panic!( "type parameter `{:?}` ({:?}/{}) out of range when instantiating, args={:?}", p, @@ -971,10 +978,7 @@ pub enum BoundVarIndexKind { #[derive_where(Copy; I: Interner, T: Copy)] #[derive_where(Clone, PartialOrd, PartialEq, Eq, Hash; I: Interner, T)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] -#[cfg_attr( - feature = "nightly", - derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) -)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub struct Placeholder { pub universe: UniverseIndex, pub bound: T, @@ -1010,10 +1014,7 @@ where #[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)] #[derive(Lift_Generic)] -#[cfg_attr( - feature = "nightly", - derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) -)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub enum BoundRegionKind { /// An anonymous region parameter for a given fn (&T) @@ -1073,10 +1074,7 @@ impl BoundRegionKind { #[derive_where(Clone, Copy, PartialEq, Eq, Debug, Hash; I: Interner)] #[derive(Lift_Generic)] -#[cfg_attr( - feature = "nightly", - derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) -)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub enum BoundTyKind { Anon, Param(I::DefId), @@ -1291,7 +1289,7 @@ impl PlaceholderConst { Self { universe: ui, bound, _tcx: PhantomData } } - pub fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty { + pub fn find_const_ty_from_env(self, env: I::ParamEnv) -> Ty { let mut candidates = env.caller_bounds().iter().filter_map(|clause| { // `ConstArgHasType` are never desugared to be higher ranked. match clause.kind().skip_binder() { @@ -1325,3 +1323,1728 @@ impl PlaceholderConst { ty } } + +/// Use this rather than `TyKind`, whenever possible. +#[derive_where(Copy; I: Interner, I::Interned>>: Copy)] +#[derive_where(Clone, PartialEq, Eq, Hash; I: Interner)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] +#[rustc_diagnostic_item = "Ty"] +#[rustc_pass_by_value] +pub struct Ty(pub I::Interned>>); + +impl Ty { + #[inline] + pub fn from_interned(interned: I::Interned>>) -> Self { + Ty(interned) + } + + #[inline] + pub fn interned(self) -> I::Interned>> { + self.0 + } +} + +impl fmt::Debug for Ty +where + I::Interned>>: Deref>>, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&(*self).kind(), f) + } +} + +impl IntoKind for Ty +where + I::Interned>>: Deref>>, +{ + type Kind = TyKind; + + #[inline] + fn kind(self) -> TyKind { + (*self.0).internee + } +} + +impl Flags for Ty +where + I::Interned>>: Deref>>, +{ + #[inline] + fn flags(&self) -> TypeFlags { + self.0.flags + } + + #[inline] + fn outer_exclusive_binder(&self) -> DebruijnIndex { + self.0.outer_exclusive_binder + } +} + +impl TypeVisitable for Ty { + fn visit_with>(&self, visitor: &mut V) -> V::Result { + visitor.visit_ty(*self) + } +} + +impl TypeSuperVisitable for Ty +where + I::Interned>>: Deref>>, + I::BoundExistentialPredicates: TypeVisitable, + I::Const: TypeVisitable, + I::ErrorGuaranteed: TypeVisitable, + I::GenericArgs: TypeVisitable, + I::Pat: TypeVisitable, + I::Region: TypeVisitable, + I::Tys: TypeVisitable, +{ + fn super_visit_with>(&self, visitor: &mut V) -> V::Result { + match (*self).kind() { + ty::RawPtr(ty, _mutbl) => ty.visit_with(visitor), + ty::Array(typ, sz) => { + try_visit!(typ.visit_with(visitor)); + sz.visit_with(visitor) + } + ty::Slice(typ) => typ.visit_with(visitor), + ty::Adt(_, args) => args.visit_with(visitor), + ty::Dynamic(trait_ty, reg) => { + try_visit!(trait_ty.visit_with(visitor)); + reg.visit_with(visitor) + } + ty::Tuple(ts) => ts.visit_with(visitor), + ty::FnDef(_, args) => args.visit_with(visitor), + ty::FnPtr(sig_tys, _) => sig_tys.visit_with(visitor), + ty::UnsafeBinder(f) => f.visit_with(visitor), + ty::Ref(r, ty, _) => { + try_visit!(r.visit_with(visitor)); + ty.visit_with(visitor) + } + ty::Coroutine(_did, args) => args.visit_with(visitor), + ty::CoroutineWitness(_did, args) => args.visit_with(visitor), + ty::Closure(_did, args) => args.visit_with(visitor), + ty::CoroutineClosure(_did, args) => args.visit_with(visitor), + ty::Alias(_, data) => data.visit_with(visitor), + ty::Pat(ty, pat) => { + try_visit!(ty.visit_with(visitor)); + pat.visit_with(visitor) + } + ty::Error(guar) => guar.visit_with(visitor), + + ty::Bool + | ty::Char + | ty::Str + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Infer(_) + | ty::Param(..) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Never + | ty::Foreign(..) => V::Result::output(), + } + } +} + +impl TypeFoldable for Ty { + fn try_fold_with>(self, folder: &mut F) -> Result { + folder.try_fold_ty(self) + } + + fn fold_with>(self, folder: &mut F) -> Self { + folder.fold_ty(self) + } +} + +impl TypeSuperFoldable for Ty +where + I::Interned>>: Deref>>, + I::BoundExistentialPredicates: TypeFoldable, + I::Const: TypeFoldable, + I::GenericArgs: TypeFoldable, + I::Pat: TypeFoldable, + I::Region: TypeFoldable, + I::Tys: TypeFoldable, +{ + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + let kind = match self.kind() { + ty::RawPtr(ty, mutbl) => ty::RawPtr(ty.try_fold_with(folder)?, mutbl), + 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, args) => ty::Adt(tid, args.try_fold_with(folder)?), + ty::Dynamic(trait_ty, region) => { + ty::Dynamic(trait_ty.try_fold_with(folder)?, region.try_fold_with(folder)?) + } + ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?), + ty::FnDef(def_id, args) => ty::FnDef(def_id, args.try_fold_with(folder)?), + ty::FnPtr(sig_tys, hdr) => ty::FnPtr(sig_tys.try_fold_with(folder)?, hdr), + ty::UnsafeBinder(f) => ty::UnsafeBinder(f.try_fold_with(folder)?), + ty::Ref(r, ty, mutbl) => { + ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl) + } + ty::Coroutine(did, args) => ty::Coroutine(did, args.try_fold_with(folder)?), + ty::CoroutineWitness(did, args) => { + ty::CoroutineWitness(did, args.try_fold_with(folder)?) + } + ty::Closure(did, args) => ty::Closure(did, args.try_fold_with(folder)?), + ty::CoroutineClosure(did, args) => { + ty::CoroutineClosure(did, args.try_fold_with(folder)?) + } + ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?), + ty::Pat(ty, pat) => ty::Pat(ty.try_fold_with(folder)?, pat.try_fold_with(folder)?), + + ty::Bool + | ty::Char + | ty::Str + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Error(_) + | ty::Infer(_) + | ty::Param(..) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Never + | ty::Foreign(..) => return Ok(self), + }; + + Ok(if self.kind() == kind { self } else { folder.cx().mk_ty_from_kind(kind) }) + } + + fn super_fold_with>(self, folder: &mut F) -> Self { + let kind = match self.kind() { + ty::RawPtr(ty, mutbl) => ty::RawPtr(ty.fold_with(folder), mutbl), + ty::Array(typ, sz) => ty::Array(typ.fold_with(folder), sz.fold_with(folder)), + ty::Slice(typ) => ty::Slice(typ.fold_with(folder)), + ty::Adt(tid, args) => ty::Adt(tid, args.fold_with(folder)), + ty::Dynamic(trait_ty, region) => { + ty::Dynamic(trait_ty.fold_with(folder), region.fold_with(folder)) + } + ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)), + ty::FnDef(def_id, args) => ty::FnDef(def_id, args.fold_with(folder)), + ty::FnPtr(sig_tys, hdr) => ty::FnPtr(sig_tys.fold_with(folder), hdr), + ty::UnsafeBinder(f) => ty::UnsafeBinder(f.fold_with(folder)), + ty::Ref(r, ty, mutbl) => ty::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl), + ty::Coroutine(did, args) => ty::Coroutine(did, args.fold_with(folder)), + ty::CoroutineWitness(did, args) => ty::CoroutineWitness(did, args.fold_with(folder)), + ty::Closure(did, args) => ty::Closure(did, args.fold_with(folder)), + ty::CoroutineClosure(did, args) => ty::CoroutineClosure(did, args.fold_with(folder)), + ty::Alias(kind, data) => ty::Alias(kind, data.fold_with(folder)), + ty::Pat(ty, pat) => ty::Pat(ty.fold_with(folder), pat.fold_with(folder)), + + ty::Bool + | ty::Char + | ty::Str + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Error(_) + | ty::Infer(_) + | ty::Param(..) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Never + | ty::Foreign(..) => return self, + }; + + if self.kind() == kind { self } else { folder.cx().mk_ty_from_kind(kind) } + } +} + +// Simple constructors and transformations +impl Ty +where + I::BoundExistentialPredicates: TypeFoldable + TypeVisitable, + I::GenericArg: From>, + I::GenericArgs: TypeFoldable + TypeVisitable, + I::Const: TypeFoldable + TypeVisitable, + I::ErrorGuaranteed: TypeVisitable, + I::Pat: TypeFoldable + TypeVisitable, + I::Region: TypeFoldable + TypeVisitable, + I::Term: From>, + I::Tys: TypeFoldable + TypeVisitable, + I::Interned>>: + Copy + Clone + Debug + Hash + Eq + Deref>>, +{ + /// Avoid using this in favour of more specific `new_*` methods, where possible. + /// The more specific methods will often optimize their creation. + #[allow(rustc::usage_of_ty_tykind)] + #[inline] + pub fn new(interner: I, st: TyKind) -> Self { + interner.mk_ty_from_kind(st) + } + + #[inline] + pub fn new_unit(interner: I) -> Self { + Self::new(interner, ty::Tuple(Default::default())) + } + + #[inline] + pub fn new_bool(interner: I) -> Self { + Self::new(interner, ty::Bool) + } + + #[inline] + pub fn new_u8(interner: I) -> Self { + Self::new(interner, ty::Uint(ty::UintTy::U8)) + } + + #[inline] + pub fn new_usize(interner: I) -> Self { + Self::new(interner, ty::Uint(ty::UintTy::Usize)) + } + + #[inline] + pub fn new_infer(interner: I, var: ty::InferTy) -> Self { + Self::new(interner, ty::Infer(var)) + } + + #[inline] + pub fn new_var(interner: I, var: ty::TyVid) -> Self { + // Use a pre-interned one when possible. + interner + .get_ty_var(var.as_usize()) + .unwrap_or_else(|| Self::new(interner, ty::Infer(ty::InferTy::TyVar(var)))) + } + + #[inline] + pub fn new_int_var(interner: I, v: ty::IntVid) -> Self { + Self::new_infer(interner, ty::IntVar(v)) + } + + #[inline] + pub fn new_float_var(interner: I, v: ty::FloatVid) -> Self { + Self::new_infer(interner, ty::FloatVar(v)) + } + + #[inline] + pub fn new_fresh(interner: I, n: u32) -> Self { + // Use a pre-interned one when possible. + interner + .get_fresh_ty(n as usize) + .unwrap_or_else(|| Self::new_infer(interner, ty::FreshTy(n))) + } + + #[inline] + pub fn new_fresh_int(interner: I, n: u32) -> Self { + // Use a pre-interned one when possible. + interner + .get_fresh_ty_int(n as usize) + .unwrap_or_else(|| Self::new_infer(interner, ty::FreshIntTy(n))) + } + + #[inline] + pub fn new_fresh_float(interner: I, n: u32) -> Self { + // Use a pre-interned one when possible. + interner + .get_fresh_ty_float(n as usize) + .unwrap_or_else(|| Self::new_infer(interner, ty::FreshFloatTy(n))) + } + + #[inline] + pub fn new_param(interner: I, param: I::ParamTy) -> Self { + Self::new(interner, ty::Param(param)) + } + + #[inline] + pub fn new_placeholder(interner: I, param: ty::PlaceholderType) -> Self { + Self::new(interner, ty::Placeholder(param)) + } + + #[inline] + pub fn new_bound(interner: I, index: ty::DebruijnIndex, bound_ty: ty::BoundTy) -> Self { + // Use a pre-interned one when possible. + if let ty::BoundTy { var, kind: ty::BoundTyKind::Anon } = bound_ty + && let Some(inner) = interner.get_anon_bound_ty(index.as_usize()) + && let Some(ty) = inner.get(var.as_usize()).copied() + { + ty + } else { + Self::new(interner, ty::Bound(ty::BoundVarIndexKind::Bound(index), bound_ty)) + } + } + + #[inline] + pub fn new_canonical_bound(interner: I, var: ty::BoundVar) -> Self { + // Use a pre-interned one when possible. + if let Some(ty) = interner.get_anon_canonical_bound_ty(var.as_usize()) { + ty + } else { + Self::new( + interner, + ty::Bound( + ty::BoundVarIndexKind::Canonical, + ty::BoundTy { var, kind: ty::BoundTyKind::Anon }, + ), + ) + } + } + + #[inline] + pub fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { + let bound_ty = ty::BoundTy { var, kind: ty::BoundTyKind::Anon }; + Self::new(interner, ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_ty)) + } + + #[inline] + pub fn new_alias(interner: I, kind: ty::AliasTyKind, alias_ty: ty::AliasTy) -> Self { + // @PROBLEM + // - requires hir for `DefKind` and we need `def_kind()` as a method + // - Is `interner.debug_assert_args_compatible` a suitable drop in for + // `debug_assert_matches!`? + // + // interner.debug_assert_args_compatible( + // (kind, interner.def_kind(alias_ty.def_id)), + // (ty::Opaque, DefKind::OpaqueTy) + // | (ty::Projection | ty::Inherent, DefKind::AssocTy) + // | (ty::Free, DefKind::TyAlias) + // ); + Self::new(interner, ty::Alias(kind, alias_ty)) + } + + #[inline] + pub fn new_projection_from_args(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self { + Ty::new_alias( + interner, + ty::AliasTyKind::Projection, + ty::AliasTy::new_from_args(interner, def_id, args), + ) + } + + #[inline] + pub fn new_projection( + interner: I, + def_id: I::DefId, + args: impl IntoIterator>, + ) -> Self { + Ty::new_alias( + interner, + ty::AliasTyKind::Projection, + ty::AliasTy::new(interner, def_id, args), + ) + } + + /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed` + pub fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self { + Self::new(interner, ty::Error(guar)) + } + + #[inline] + pub fn new_adt(interner: I, adt_def: I::AdtDef, args: I::GenericArgs) -> Self { + interner.debug_assert_args_compatible(adt_def.def_id().into(), args); + interner.debug_assert_adt_def_compatible(adt_def); + Self::new(interner, ty::Adt(adt_def, args)) + } + + #[inline] + pub fn new_foreign(interner: I, def_id: I::ForeignId) -> Self { + Self::new(interner, ty::Foreign(def_id)) + } + + #[inline] + pub fn new_array(interner: I, ty: Ty, n: u64) -> Ty { + Self::new(interner, ty::Array(ty, Const::from_target_usize(interner, n))) + } + + #[inline] + pub fn new_dynamic( + interner: I, + preds: I::BoundExistentialPredicates, + region: I::Region, + ) -> Self { + Self::new(interner, ty::Dynamic(preds, region)) + } + + #[inline] + pub fn new_coroutine(interner: I, def_id: I::CoroutineId, args: I::GenericArgs) -> Self { + interner.debug_assert_args_compatible(def_id.into(), args); + Self::new(interner, ty::Coroutine(def_id, args)) + } + + #[inline] + pub fn new_coroutine_closure( + interner: I, + def_id: I::CoroutineClosureId, + args: I::GenericArgs, + ) -> Self { + Self::new(interner, ty::CoroutineClosure(def_id, args)) + } + + #[inline] + pub fn new_closure(interner: I, def_id: I::ClosureId, args: I::GenericArgs) -> Self { + Self::new(interner, ty::Closure(def_id, args)) + } + + #[inline] + pub fn new_coroutine_witness( + interner: I, + def_id: I::CoroutineId, + args: I::GenericArgs, + ) -> Self { + if cfg!(debug_assertions) { + interner.debug_assert_args_compatible(interner.typeck_root_def_id(def_id.into()), args); + } + Self::new(interner, ty::CoroutineWitness(def_id, args)) + } + + #[inline] + pub fn new_coroutine_witness_for_coroutine( + interner: I, + def_id: I::CoroutineId, + coroutine_args: I::GenericArgs, + ) -> Self { + interner.debug_assert_args_compatible(def_id.into(), coroutine_args); + let args = interner.get_generic_args_for_item(def_id.into()); + Self::new_coroutine_witness(interner, def_id, args) + } + + #[inline] + pub fn new_static_str(interner: I) -> Self { + interner.new_static_str() + } + + fn new_generic_adt(interner: I, wrapper_def_id: I::DefId, ty_param: Ty) -> Ty { + interner.new_generic_adt(wrapper_def_id, ty_param) + } + + #[inline] + pub fn new_lang_item(interner: I, ty: Ty, item: I::LangItem) -> Option> { + let def_id = interner.get_lang_item(item)?; + Some(Self::new_generic_adt(interner, def_id, ty)) + } + + #[inline] + pub fn new_diagnostic_item(interner: I, ty: Ty, name: I::Symbol) -> Option> { + let def_id = interner.get_diagnostic_item(name)?; + Some(Self::new_generic_adt(interner, def_id, ty)) + } + + #[inline] + pub fn new_box(interner: I, ty: Ty) -> Self { + let def_id = interner.require_lang_item_owned_box(); + Self::new_generic_adt(interner, def_id, ty) + } + + #[inline] + pub fn new_option(interner: I, ty: Self) -> Self { + let def_id = interner.require_lang_item_option(); + Self::new_generic_adt(interner, def_id, ty) + } + + #[inline] + pub fn new_maybe_uninit(interner: I, ty: Self) -> Self { + let def_id = interner.require_lang_item_maybe_uninit(); + Self::new_generic_adt(interner, def_id, ty) + } + + /// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes. + pub fn new_task_context(interner: I) -> Self { + interner.new_task_context() + } + + #[inline] + pub fn new_ptr(interner: I, ty: Self, mutbl: Mutability) -> Self { + Self::new(interner, ty::RawPtr(ty, mutbl)) + } + + #[inline] + pub fn new_mut_ptr(interner: I, ty: Ty) -> Ty { + Self::new_ptr(interner, ty, Mutability::Mut) + } + + #[inline] + pub fn new_imm_ptr(interner: I, ty: Ty) -> Ty { + Self::new_ptr(interner, ty, Mutability::Not) + } + + #[inline] + pub fn new_ref(interner: I, region: I::Region, ty: Self, mutbl: Mutability) -> Self { + Self::new(interner, ty::Ref(region, ty, mutbl)) + } + + #[inline] + pub fn new_mut_ref(interner: I, r: I::Region, ty: Ty) -> Ty { + Self::new_ref(interner, r, ty, Mutability::Mut) + } + + #[inline] + pub fn new_imm_ref(interner: I, r: I::Region, ty: Ty) -> Ty { + Self::new_ref(interner, r, ty, Mutability::Not) + } + + #[inline] + pub fn new_array_with_const_len(interner: I, ty: Self, len: I::Const) -> Self { + Self::new(interner, ty::Array(ty, len)) + } + + pub fn new_pinned_ref(interner: I, r: I::Region, ty: Ty, mutbl: Mutability) -> Ty { + interner.new_pinned_ref(r, ty, mutbl) + } + + #[inline] + pub fn new_slice(interner: I, ty: Self) -> Self { + Self::new(interner, ty::Slice(ty)) + } + + #[inline] + pub fn new_tup(interner: I, tys: &[Ty]) -> Self { + if tys.is_empty() { + return Self::new_unit(interner); + } + + let tys = interner.mk_type_list_from_iter(tys.iter().copied()); + Self::new(interner, ty::Tuple(tys)) + } + + #[inline] + pub fn new_tup_from_iter(interner: I, iter: It) -> T::Output + where + It: Iterator, + T: CollectAndApply, + { + T::collect_and_apply(iter, |ts| Self::new_tup(interner, ts)) + } + + #[inline] + pub fn new_fn_def(interner: I, def_id: I::FunctionId, args: I::GenericArgs) -> Self { + Self::new(interner, ty::FnDef(def_id, args)) + } + + #[inline] + pub fn new_fn_ptr(interner: I, sig: ty::Binder>) -> Self { + let (sig_tys, hdr) = sig.split(); + Self::new(interner, ty::FnPtr(sig_tys, hdr)) + } + + #[inline] + pub fn new_pat(interner: I, ty: Self, pat: I::Pat) -> Self { + Self::new(interner, ty::Pat(ty, pat)) + } + + #[inline] + #[instrument(level = "debug", skip(interner))] + pub fn new_opaque(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self { + Self::new_alias(interner, ty::Opaque, AliasTy::new_from_args(interner, def_id, args)) + } + + #[inline] + pub fn new_unsafe_binder(interner: I, ty: ty::Binder>) -> Self { + Self::new(interner, ty::UnsafeBinder(ty::UnsafeBinderInner::from(ty))) + } +} + +// Methods to determine what flavour `Ty` is +impl Ty +where + I::Interned>>: Deref>>, + I::BoundExistentialPredicates: TypeVisitable, + I::Const: TypeVisitable, + I::ErrorGuaranteed: TypeVisitable, + I::GenericArgs: TypeVisitable, + I::Pat: TypeVisitable, + I::Region: TypeVisitable, + I::Tys: TypeVisitable, +{ + // ==== Below here is what used to be `compiler/rustc_middle/src/ty/sty.rs` + // Type utilities L931 + + // FIXME(compiler-errors): Think about removing this. + #[inline(always)] + pub fn flags(self) -> TypeFlags { + self.0.flags + } + + #[inline] + pub fn is_unit(self) -> bool { + match self.kind() { + ty::Tuple(tys) => tys.is_empty(), + _ => false, + } + } + + /// Check if type is an `usize`. + #[inline] + pub fn is_usize(self) -> bool { + matches!(self.kind(), ty::Uint(ty::UintTy::Usize)) + } + + /// Check if type is an `usize` or an integral type variable. + #[inline] + pub fn is_usize_like(self) -> bool { + matches!(self.kind(), ty::Uint(ty::UintTy::Usize) | ty::Infer(ty::IntVar(_))) + } + + #[inline] + pub fn is_never(self) -> bool { + matches!(self.kind(), ty::Never) + } + + #[inline] + pub fn is_primitive(self) -> bool { + matches!(self.kind(), ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_)) + } + + #[inline] + pub fn is_adt(self) -> bool { + matches!(self.kind(), ty::Adt(..)) + } + + #[inline] + pub fn is_ref(self) -> bool { + matches!(self.kind(), ty::Ref(..)) + } + + #[inline] + pub fn is_ty_var(self) -> bool { + matches!(self.kind(), ty::Infer(ty::TyVar(_))) + } + + #[inline] + pub fn ty_vid(self) -> Option { + match self.kind() { + ty::Infer(ty::TyVar(vid)) => Some(vid), + _ => None, + } + } + + #[inline] + pub fn is_ty_or_numeric_infer(self) -> bool { + matches!(self.kind(), ty::Infer(_)) + } + + #[inline] + pub fn is_phantom_data(self) -> bool { + if let ty::Adt(def, _) = self.kind() { def.is_phantom_data() } else { false } + } + + #[inline] + pub fn is_bool(self) -> bool { + self.kind() == ty::Bool + } + + /// Returns `true` if this type is a `str`. + #[inline] + pub fn is_str(self) -> bool { + self.kind() == ty::Str + } + + /// Returns true if this type is `&str`. The reference's lifetime is ignored. + #[inline] + pub fn is_imm_ref_str(self) -> bool { + matches!(self.kind(), ty::Ref(_, inner, Mutability::Not) if inner.is_str()) + } + + #[inline] + pub fn is_param(self, index: u32) -> bool { + match self.kind() { + ty::Param(data) => data.index() == index, + _ => false, + } + } + + #[inline] + pub fn is_slice(self) -> bool { + matches!(self.kind(), ty::Slice(_)) + } + + #[inline] + pub fn is_array_slice(self) -> bool { + match self.kind() { + ty::Slice(_) => true, + ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => matches!(ty.kind(), ty::Slice(_)), + _ => false, + } + } + + #[inline] + pub fn is_array(self) -> bool { + matches!(self.kind(), ty::Array(..)) + } + + #[inline] + pub fn is_simd(self) -> bool { + match self.kind() { + ty::Adt(def, _) => def.repr_is_simd(), + _ => false, + } + } + + #[inline] + pub fn is_scalable_vector(self) -> bool { + match self.kind() { + ty::Adt(def, _) => def.scalable_element_cnt().is_some(), + _ => false, + } + } + + pub fn sequence_element_type(self, interner: I) -> Ty { + match self.kind() { + ty::Array(ty, _) | ty::Slice(ty) => ty, + ty::Str => interner.u8_type(), + _ => panic!("`sequence_element_type` called on non-sequence value: {:?}", self), + } + } + + pub fn scalable_vector_element_count_and_type(self, interner: I) -> (u16, Ty) { + let ty::Adt(def, args) = self.kind() else { + panic!("`scalable_vector_size_and_type` called on invalid type") + }; + let Some(element_count) = def.scalable_element_cnt() else { + panic!("`scalable_vector_size_and_type` called on non-scalable vector type"); + }; + assert_eq!(def.non_enum_variant().fields_len(), 1); + let field_ty = def.non_enum_variant().field_zero_ty(interner, args); + (element_count, field_ty) + } + + pub fn simd_size_and_type(self, interner: I) -> (u64, Ty) { + let ty::Adt(def, args) = self.kind() else { + panic!("`simd_size_and_type` called on invalid type") + }; + assert!(def.repr_is_simd(), "`simd_size_and_type` called on non-SIMD type"); + assert_eq!(def.non_enum_variant().fields_len(), 1); + + let field_ty = def.non_enum_variant().field_zero_ty(interner, args); + + let ty::Array(f0_elem_ty, f0_len) = field_ty.kind() else { + panic!("Simd type has non-array field type {field_ty:?}") + }; + // FIXME(repr_simd): https://github.com/rust-lang/rust/pull/78863#discussion_r522784112 + // The way we evaluate the `N` in `[T; N]` here only works since we use + // `simd_size_and_type` post-monomorphization. It will probably start to ICE + // if we use it in generic code. See the `simd-array-trait` ui test. + ( + f0_len + .try_to_target_usize(interner) + .expect("expected SIMD field to have definite array size"), + f0_elem_ty, + ) + } + + pub fn pinned_ty(self) -> Option> { + match self.kind() { + ty::Adt(def, args) if def.is_pin() => Some(args.type_at(0)), + _ => None, + } + } + + pub fn maybe_pinned_ref(self) -> Option<(Ty, ty::Pinnedness, ty::Mutability, I::Region)> { + match self.kind() { + ty::Adt(def, args) + if def.is_pin() + && let ty::Ref(region, ty, mutbl) = args.type_at(0).kind() => + { + Some((ty, ty::Pinnedness::Pinned, mutbl, region)) + } + ty::Ref(region, ty, mutbl) => Some((ty, ty::Pinnedness::Not, mutbl, region)), + _ => None, + } + } + + /// Panics if called on any type other than `Box`. + pub fn expect_boxed_ty(self) -> Ty { + self.boxed_ty() + .unwrap_or_else(|| panic!("`expect_boxed_ty` is called on non-box type {:?}", self)) + } + + /// A scalar type is one that denotes an atomic datum, with no sub-components. + /// (A RawPtr is scalar because it represents a non-managed pointer, so its + /// contents are abstract to rustc.) + #[inline] + pub fn is_scalar(self) -> bool { + matches!( + self.kind(), + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Float(_) + | ty::Uint(_) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::RawPtr(_, _) + | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) + ) + } + + #[inline] + pub fn is_enum(self) -> bool { + matches!(self.kind(), ty::Adt(adt_def, _) if adt_def.is_enum()) + } + + #[inline] + pub fn is_union(self) -> bool { + matches!(self.kind(), ty::Adt(adt_def, _) if adt_def.is_union()) + } + + #[inline] + pub fn is_closure(self) -> bool { + matches!(self.kind(), ty::Closure(..)) + } + + #[inline] + pub fn is_coroutine(self) -> bool { + matches!(self.kind(), ty::Coroutine(..)) + } + + #[inline] + pub fn is_coroutine_closure(self) -> bool { + matches!(self.kind(), ty::CoroutineClosure(..)) + } + + #[inline] + pub fn is_fresh_ty(self) -> bool { + matches!(self.kind(), ty::Infer(ty::FreshTy(_))) + } + + #[inline] + pub fn is_fresh(self) -> bool { + matches!(self.kind(), ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))) + } + + #[inline] + pub fn is_char(self) -> bool { + matches!(self.kind(), ty::Char) + } + + #[inline] + pub fn is_numeric(self) -> bool { + self.is_integral() || self.is_floating_point() + } + + #[inline] + pub fn is_signed(self) -> bool { + matches!(self.kind(), ty::Int(_)) + } + + #[inline] + pub fn is_ptr_sized_integral(self) -> bool { + matches!(self.kind(), ty::Int(ty::IntTy::Isize) | ty::Uint(ty::UintTy::Usize)) + } + + #[inline] + pub fn has_concrete_skeleton(self) -> bool { + !matches!(self.kind(), ty::Param(_) | ty::Infer(_) | ty::Error(_)) + } + + /// Checks whether a type recursively contains another type + /// + /// Example: `Option<()>` contains `()` + pub fn contains(self, other: Ty) -> bool { + struct ContainsTyVisitor(Ty); + + impl TypeVisitor for ContainsTyVisitor { + type Result = ControlFlow<()>; + + fn visit_ty(&mut self, t: Ty) -> Self::Result { + if self.0 == t { ControlFlow::Break(()) } else { t.super_visit_with(self) } + } + } + + let cf = self.visit_with(&mut ContainsTyVisitor(other)); + cf.is_break() + } + + /// Checks whether a type recursively contains any closure + /// + /// Example: `Option<{closure@file.rs:4:20}>` returns true + pub fn contains_closure(self) -> bool { + struct ContainsClosureVisitor; + + impl TypeVisitor for ContainsClosureVisitor { + type Result = ControlFlow<()>; + + fn visit_ty(&mut self, t: Ty) -> Self::Result { + if let ty::Closure(..) = t.kind() { + ControlFlow::Break(()) + } else { + t.super_visit_with(self) + } + } + } + + let cf = self.visit_with(&mut ContainsClosureVisitor); + cf.is_break() + } + + /// Returns the deepest `async_drop_in_place::{closure}` implementation. + /// + /// `async_drop_in_place::{closure}`, when T is a coroutine, is a proxy-impl + /// to call async drop poll from impl coroutine. + pub fn find_async_drop_impl_coroutine)>(self, interner: I, mut f: F) -> Ty { + assert!(self.is_coroutine()); + let mut cor_ty = self; + let mut ty = cor_ty; + loop { + let ty::Coroutine(def_id, args) = ty.kind() else { return cor_ty }; + cor_ty = ty; + f(ty); + if !interner.is_async_drop_in_place_coroutine(def_id.into()) { + return cor_ty; + } + ty = args.first().unwrap().expect_ty(); + } + } + + /// Returns the type of `*ty`. + /// + /// The parameter `explicit` indicates if this is an *explicit* dereference. + /// Some types -- notably raw ptrs -- can only be dereferenced explicitly. + pub fn builtin_deref(self, explicit: bool) -> Option> { + match self.kind() { + _ if let Some(boxed) = self.boxed_ty() => Some(boxed), + ty::Ref(_, ty, _) => Some(ty), + ty::RawPtr(ty, _) if explicit => Some(ty), + _ => None, + } + } + + /// Returns the type of `ty[i]`. + pub fn builtin_index(self) -> Option> { + match self.kind() { + ty::Array(ty, _) | ty::Slice(ty) => Some(ty), + _ => None, + } + } + + #[inline] + pub fn is_fn(self) -> bool { + matches!(self.kind(), ty::FnDef(..) | ty::FnPtr(..)) + } + + #[inline] + pub fn is_impl_trait(self) -> bool { + matches!(self.kind(), ty::Alias(ty::Opaque, ..)) + } + + #[inline] + pub fn ty_adt_def(self) -> Option { + match self.kind() { + ty::Adt(adt, _) => Some(adt), + _ => None, + } + } + + /// Iterates over tuple fields. + /// Panics when called on anything but a tuple. + #[inline] + pub fn tuple_fields(self) -> I::Tys { + match self.kind() { + ty::Tuple(tys) => tys, + _ => panic!("tuple_fields called on non-tuple: {self:?}"), + } + } + + /// If the type contains variants, returns the valid range of variant indices. + // + // FIXME: This requires the optimized MIR in the case of coroutines. + #[inline] + pub fn variant_range(self, interner: I) -> Option> { + match self.kind() { + TyKind::Adt(adt, _) => Some(adt.variant_range()), + TyKind::Coroutine(def_id, args) => { + // @PROBLEM - I am not sure `coroutine_variant_range(...)` should be on `interner` + let coroutine_args = + interner.coroutine_variant_range(def_id.into(), args.as_coroutine()); + Some(coroutine_args) + } + _ => None, + } + } + + /// If the type contains variants, returns the variant for `variant_index`. + /// Panics if `variant_index` is out of range. + // + // FIXME: This requires the optimized MIR in the case of coroutines. + #[inline] + pub fn discriminant_for_variant( + self, + interner: I, + variant_index: I::VariantIdx, + ) -> Option { + match self.kind() { + TyKind::Adt(adt, _) if adt.is_enum() => { + Some(adt.discriminant_for_variant(interner, variant_index)) + } + TyKind::Coroutine(def_id, args) => Some(args.coroutine_discriminant_for_variant( + def_id.into(), + interner, + variant_index, + )), + _ => None, + } + } + + #[inline] + pub fn is_mutable_ptr(self) -> bool { + matches!(self.kind(), ty::RawPtr(_, Mutability::Mut) | ty::Ref(_, _, Mutability::Mut)) + } + + /// Get the mutability of the reference or `None` when not a reference + #[inline] + pub fn ref_mutability(self) -> Option { + match self.kind() { + ty::Ref(_, _, mutability) => Some(mutability), + _ => None, + } + } + + #[inline] + pub fn is_raw_ptr(self) -> bool { + matches!(self.kind(), ty::RawPtr(_, _)) + } + + /// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer). + /// `Box` is *not* considered a pointer here! + #[inline] + pub fn is_any_ptr(self) -> bool { + self.is_ref() || self.is_raw_ptr() || self.is_fn_ptr() + } + + #[inline] + pub fn is_box(self) -> bool { + match self.kind() { + ty::Adt(def, _) => def.is_box(), + _ => false, + } + } + + /// Tests whether this is a Box definitely using the global allocator. + /// + /// If the allocator is still generic, the answer is `false`, but it may + /// later turn out that it does use the global allocator. + #[inline] + pub fn is_box_global(self, interner: I) -> bool { + match self.kind() { + ty::Adt(def, args) if def.is_box() => { + let Some(alloc) = args.get(1) else { + // Single-argument Box is always global. (for "minicore" tests) + return true; + }; + alloc.expect_ty().ty_adt_def().is_some_and(|alloc_adt| { + interner.is_lang_item(alloc_adt.def_id().into(), SolverLangItem::GlobalAlloc) + }) + } + _ => false, + } + } + + pub fn boxed_ty(self) -> Option> { + match self.kind() { + ty::Adt(def, args) if def.is_box() => Some(args.type_at(0)), + _ => None, + } + } + + #[inline] + pub fn is_ty_error(self) -> bool { + matches!(self.kind(), ty::Error(_)) + } + + /// Returns `true` if this type is a floating point type. + #[inline] + pub fn is_floating_point(self) -> bool { + matches!(self.kind(), ty::Float(_) | ty::Infer(ty::FloatVar(_))) + } + + #[inline] + pub fn is_trait(self) -> bool { + matches!(self.kind(), ty::Dynamic(_, _)) + } + + #[inline] + pub fn is_integral(self) -> bool { + matches!(self.kind(), ty::Infer(ty::IntVar(_)) | ty::Int(_) | ty::Uint(_)) + } + + #[inline] + pub fn is_fn_ptr(self) -> bool { + matches!(self.kind(), ty::FnPtr(..)) + } + + #[inline] + pub fn has_unsafe_fields(self) -> bool { + match self.kind() { + ty::Adt(adt_def, _) => adt_def.has_unsafe_fields(), + _ => false, + } + } + + #[inline] + #[tracing::instrument(level = "trace", skip(interner))] + pub fn fn_sig(self, interner: I) -> ty::Binder> { + self.kind().fn_sig(interner) + } + + /// Returns the type of the discriminant of this type. + #[inline] + pub fn discriminant_ty(self, interner: I) -> Ty { + match self.kind() { + ty::Adt(adt, _) if adt.is_enum() => adt.repr_discr_type_to_ty(interner), + ty::Coroutine(_, args) => args.as_coroutine_discr_ty(interner), + + ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => { + let mut assoc_items = interner + .associated_type_def_ids( + interner.require_trait_lang_item(SolverTraitLangItem::DiscriminantKind), + ) + .into_iter(); + Ty::new_projection_from_args( + interner, + assoc_items.next().expect("DiscriminantKind should have an associated type"), + interner.mk_args(&[self.into()]), + ) + } + + ty::Pat(ty, _) => ty.discriminant_ty(interner), + + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Adt(..) + | ty::Foreign(_) + | ty::Str + | ty::Array(..) + | ty::Slice(_) + | ty::RawPtr(_, _) + | ty::Ref(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::Dynamic(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::CoroutineWitness(..) + | ty::Never + | ty::Tuple(_) + | ty::UnsafeBinder(_) + | ty::Error(_) + | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => interner.u8_type(), + + ty::Bound(..) + | ty::Placeholder(_) + | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { + panic!("`discriminant_ty` applied to unexpected type: {:?}", self) + } + } + } + + /// Returns the type of metadata for (potentially wide) pointers to this type, + /// or the struct tail if the metadata type cannot be determined. + pub fn ptr_metadata_ty_or_tail( + self, + interner: I, + cause: &I::ObligationCause, + normalize: impl FnMut(Ty) -> Ty, + ) -> Result, Ty> { + let tail = interner.struct_tail_raw(self, cause, normalize, || {}); + match tail.kind() { + // Sized types + ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) + | ty::Uint(_) + | ty::Int(_) + | ty::Bool + | ty::Float(_) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::RawPtr(..) + | ty::Char + | ty::Ref(..) + | ty::Coroutine(..) + | ty::CoroutineWitness(..) + | ty::Array(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Never + | ty::Error(_) + // Extern types have metadata = (). + | ty::Foreign(..) + // If returned by `struct_tail_raw` this is a unit struct + // without any fields, or not a struct, and therefore is Sized. + | ty::Adt(..) + // If returned by `struct_tail_raw` this is the empty tuple, + // a.k.a. unit type, which is Sized + | ty::Tuple(..) => Ok(interner.unit_type()), + + ty::Str | ty::Slice(_) => Ok(interner.usize_type()), + + ty::Dynamic(_, _) => { + let dyn_metadata = interner.require_lang_item(SolverLangItem::DynMetadata); + Ok(interner.type_of(dyn_metadata).instantiate(interner, &[tail.into()])) + } + + // We don't know the metadata of `self`, but it must be equal to the + // metadata of `tail`. + ty::Param(_) | ty::Alias(..) => Err(tail), + + | ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"), + + ty::Infer(ty::TyVar(_)) + | ty::Pat(..) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => panic!( + "`ptr_metadata_ty_or_tail` applied to unexpected type: {self:?} (tail = {tail:?})" + ), + } + } + + /// Returns the type of metadata for (potentially wide) pointers to this type. + /// Causes an ICE if the metadata type cannot be determined. + pub fn ptr_metadata_ty( + self, + interner: I, + cause: &I::ObligationCause, + normalize: impl FnMut(Ty) -> Ty, + ) -> Ty { + match self.ptr_metadata_ty_or_tail(interner, cause, normalize) { + Ok(metadata) => metadata, + Err(tail) => panic!( + "`ptr_metadata_ty` failed to get metadata for type: {self:?} (tail = {tail:?})" + ), + } + } + + /// Given a pointer or reference type, returns the type of the *pointee*'s + /// metadata. If it can't be determined exactly (perhaps due to still + /// being generic) then a projection through `ptr::Pointee` will be returned. + /// + /// This is particularly useful for getting the type of the result of + /// [`UnOp::PtrMetadata`](crate::mir::UnOp::PtrMetadata). + /// + /// Panics if `self` is not dereferenceable. + #[track_caller] + pub fn pointee_metadata_ty_or_projection( + self, + cause: &I::ObligationCause, + interner: I, + ) -> Ty { + let Some(pointee_ty) = self.builtin_deref(true) else { + panic!("Type {self:?} is not a pointer or reference type") + }; + if pointee_ty.has_trivial_sizedness(interner, SizedTraitKind::Sized) { + interner.unit_type() + } else { + match pointee_ty.ptr_metadata_ty_or_tail(interner, cause, |x| x) { + Ok(metadata_ty) => metadata_ty, + Err(tail_ty) => { + let metadata_def_id = interner.require_lang_item(SolverLangItem::Metadata); + Ty::new_projection(interner, metadata_def_id, [tail_ty]) + } + } + } + } + + /// When we create a closure, we record its kind (i.e., what trait + /// it implements, constrained by how it uses its borrows) into its + /// [`ty::ClosureArgs`] or [`ty::CoroutineClosureArgs`] 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 + /// kind. To go the other way, use [`Ty::from_closure_kind`]. + /// + /// Note that during type checking, we use an inference variable + /// to represent the closure kind, because it has not yet been + /// inferred. Once upvar inference (in `rustc_hir_analysis/src/check/upvar.rs`) + /// is complete, that type variable will be unified with one of + /// the integral types. + /// + /// ```rust,ignore (snippet of compiler code) + /// if let TyKind::Closure(def_id, args) = closure_ty.kind() + /// && let Some(closure_kind) = args.as_closure().kind_ty().to_opt_closure_kind() + /// { + /// println!("{closure_kind:?}"); + /// } else if let TyKind::CoroutineClosure(def_id, args) = closure_ty.kind() + /// && let Some(closure_kind) = args.as_coroutine_closure().kind_ty().to_opt_closure_kind() + /// { + /// println!("{closure_kind:?}"); + /// } + /// ``` + /// + /// After upvar analysis, you should instead use [`ty::ClosureArgs::kind()`] + /// or [`ty::CoroutineClosureArgs::kind()`] to assert that the `ClosureKind` + /// has been constrained instead of manually calling this method. + /// + /// ```rust,ignore (snippet of compiler code) + /// if let TyKind::Closure(def_id, args) = closure_ty.kind() + /// { + /// println!("{:?}", args.as_closure().kind()); + /// } else if let TyKind::CoroutineClosure(def_id, args) = closure_ty.kind() + /// { + /// println!("{:?}", args.as_coroutine_closure().kind()); + /// } + /// ``` + pub fn to_opt_closure_kind(self) -> Option { + match self.kind() { + ty::Int(int_ty) => match int_ty { + ty::IntTy::I8 => Some(ty::ClosureKind::Fn), + ty::IntTy::I16 => Some(ty::ClosureKind::FnMut), + ty::IntTy::I32 => Some(ty::ClosureKind::FnOnce), + _ => panic!("cannot convert type `{:?}` to a closure kind", self), + }, + + // "Bound" types appear in canonical queries when the + // closure type is not yet known, and `Placeholder` and `Param` + // may be encountered in generic `AsyncFnKindHelper` goals. + ty::Bound(..) | ty::Placeholder(_) | ty::Param(_) | ty::Infer(_) => None, + + ty::Error(_) => Some(ty::ClosureKind::Fn), + + _ => panic!("cannot convert type `{:?}` to a closure kind", self), + } + } + + /// Inverse of [`Ty::to_opt_closure_kind`]. See docs on that method + /// for explanation of the relationship between `Ty` and [`ty::ClosureKind`]. + pub fn from_closure_kind(interner: I, kind: ty::ClosureKind) -> Ty { + match kind { + ty::ClosureKind::Fn => interner.i8_type(), + ty::ClosureKind::FnMut => interner.i16_type(), + ty::ClosureKind::FnOnce => interner.i32_type(), + } + } + + /// Like [`Ty::to_opt_closure_kind`], but it caps the "maximum" closure kind + /// to `FnMut`. This is because although we have three capability states, + /// `AsyncFn`/`AsyncFnMut`/`AsyncFnOnce`, we only need to distinguish two coroutine + /// bodies: by-ref and by-value. + /// + /// See the definition of `AsyncFn` and `AsyncFnMut` and the `CallRefFuture` + /// associated type for why we don't distinguish [`ty::ClosureKind::Fn`] and + /// [`ty::ClosureKind::FnMut`] for the purpose of the generated MIR bodies. + /// + /// This method should be used when constructing a `Coroutine` out of a + /// `CoroutineClosure`, when the `Coroutine`'s `kind` field is being populated + /// directly from the `CoroutineClosure`'s `kind`. + pub fn from_coroutine_closure_kind(interner: I, kind: ty::ClosureKind) -> Ty { + match kind { + ty::ClosureKind::Fn | ty::ClosureKind::FnMut => interner.i16_type(), + ty::ClosureKind::FnOnce => interner.i32_type(), + } + } + + /// Fast path helper for testing if a type is `Sized` or `MetaSized`. + /// + /// Returning true means the type is known to implement the sizedness trait. Returning `false` + /// means nothing -- could be sized, might not be. + /// + /// Note that we could never rely on the fact that a type such as `[_]` is trivially `!Sized` + /// because we could be in a type environment with a bound such as `[_]: Copy`. A function with + /// such a bound obviously never can be called, but that doesn't mean it shouldn't typecheck. + /// This is why this method doesn't return `Option`. + #[instrument(skip(interner), level = "debug")] + pub fn has_trivial_sizedness(self, interner: I, sizedness: SizedTraitKind) -> bool { + match self.kind() { + ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) + | ty::Uint(_) + | ty::Int(_) + | ty::Bool + | ty::Float(_) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::UnsafeBinder(_) + | ty::RawPtr(..) + | ty::Char + | ty::Ref(..) + | ty::Coroutine(..) + | ty::CoroutineWitness(..) + | ty::Array(..) + | ty::Pat(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Never + | ty::Error(_) => true, + + ty::Str | ty::Slice(_) | ty::Dynamic(_, _) => match sizedness { + SizedTraitKind::Sized => false, + SizedTraitKind::MetaSized => true, + }, + + ty::Foreign(..) => match sizedness { + SizedTraitKind::Sized | SizedTraitKind::MetaSized => false, + }, + + ty::Tuple(tys) => { + tys.last().is_none_or(|ty| ty.has_trivial_sizedness(interner, sizedness)) + } + + ty::Adt(def, args) => def.sizedness_constraint(interner, sizedness).is_none_or(|ty| { + ty.instantiate(interner, args).has_trivial_sizedness(interner, sizedness) + }), + + ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) | ty::Bound(..) => false, + + ty::Infer(ty::TyVar(_)) => false, + + ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { + panic!("`has_trivial_sizedness` applied to unexpected type: {:?}", self) + } + } + } + + /// Fast path helper for primitives which are always `Copy` and which + /// have a side-effect-free `Clone` impl. + /// + /// Returning true means the type is known to be pure and `Copy+Clone`. + /// Returning `false` means nothing -- could be `Copy`, might not be. + /// + /// This is mostly useful for optimizations, as these are the types + /// on which we can replace cloning with dereferencing. + pub fn is_trivially_pure_clone_copy(self) -> bool { + match self.kind() { + ty::Bool | ty::Char | ty::Never => true, + + // These aren't even `Clone` + ty::Str | ty::Slice(..) | ty::Foreign(..) | ty::Dynamic(..) => false, + + ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_)) + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) => true, + + // ZST which can't be named are fine. + ty::FnDef(..) => true, + + ty::Array(element_ty, _len) => element_ty.is_trivially_pure_clone_copy(), + + // A 100-tuple isn't "trivial", so doing this only for reasonable sizes. + ty::Tuple(field_tys) => { + field_tys.len() <= 3 && field_tys.iter().all(Self::is_trivially_pure_clone_copy) + } + + ty::Pat(ty, _) => ty.is_trivially_pure_clone_copy(), + + // Sometimes traits aren't implemented for every ABI or arity, + // because we can't be generic over everything yet. + ty::FnPtr(..) => false, + + // Definitely absolutely not copy. + ty::Ref(_, _, Mutability::Mut) => false, + + // The standard library has a blanket Copy impl for shared references and raw pointers, + // for all unsized types. + ty::Ref(_, _, Mutability::Not) | ty::RawPtr(..) => true, + + ty::Coroutine(..) | ty::CoroutineWitness(..) => false, + + // Might be, but not "trivial" so just giving the safe answer. + ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) => false, + + ty::UnsafeBinder(_) => false, + + // Needs normalisation or revealing to determine, so no is the safe answer. + ty::Alias(..) => false, + + ty::Param(..) | ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(..) => { + false + } + } + } + + pub fn is_trivially_wf(self, interner: I) -> bool { + match self.kind() { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Str + | ty::Never + | ty::Param(_) + | ty::Placeholder(_) + | ty::Bound(..) => true, + + ty::Slice(ty) => { + ty.is_trivially_wf(interner) + && ty.has_trivial_sizedness(interner, SizedTraitKind::Sized) + } + ty::RawPtr(ty, _) => ty.is_trivially_wf(interner), + + ty::FnPtr(sig_tys, _) => sig_tys + .skip_binder() + .inputs_and_output + .iter() + .all(|ty: Ty| ty.is_trivially_wf(interner)), + ty::Ref(_, ty, _) => ty.is_global() && ty.is_trivially_wf(interner), + + ty::Infer(infer) => match infer { + ty::TyVar(_) => false, + ty::IntVar(_) | ty::FloatVar(_) => true, + ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => true, + }, + + ty::Adt(_, _) + | ty::Tuple(_) + | ty::Array(..) + | ty::Foreign(_) + | ty::Pat(_, _) + | ty::FnDef(..) + | ty::UnsafeBinder(..) + | ty::Dynamic(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + | ty::CoroutineWitness(..) + | ty::Alias(..) + | ty::Error(_) => false, + } + } + + /// If `self` is a primitive, return its [`Symbol`]. + pub fn primitive_symbol(self) -> Option + where + I::Symbol: From, + { + match self.kind() { + ty::Bool => Some(sym::bool.into()), + ty::Char => Some(sym::char.into()), + ty::Float(f) => match f { + ty::FloatTy::F16 => Some(sym::f16.into()), + ty::FloatTy::F32 => Some(sym::f32.into()), + ty::FloatTy::F64 => Some(sym::f64.into()), + ty::FloatTy::F128 => Some(sym::f128.into()), + }, + ty::Int(f) => match f { + ty::IntTy::Isize => Some(sym::isize.into()), + ty::IntTy::I8 => Some(sym::i8.into()), + ty::IntTy::I16 => Some(sym::i16.into()), + ty::IntTy::I32 => Some(sym::i32.into()), + ty::IntTy::I64 => Some(sym::i64.into()), + ty::IntTy::I128 => Some(sym::i128.into()), + }, + ty::Uint(f) => match f { + ty::UintTy::Usize => Some(sym::usize.into()), + ty::UintTy::U8 => Some(sym::u8.into()), + ty::UintTy::U16 => Some(sym::u16.into()), + ty::UintTy::U32 => Some(sym::u32.into()), + ty::UintTy::U64 => Some(sym::u64.into()), + ty::UintTy::U128 => Some(sym::u128.into()), + }, + ty::Str => Some(sym::str.into()), + _ => None, + } + } + + pub fn is_c_void(self, interner: I) -> bool { + match self.kind() { + ty::Adt(adt, _) => interner.is_c_void(adt), + _ => false, + } + } + + pub fn is_async_drop_in_place_coroutine(self, interner: I) -> bool { + match self.kind() { + ty::Coroutine(def, ..) => interner.is_async_drop_in_place_coroutine(def.into()), + _ => false, + } + } + + /// Returns `true` when the outermost type cannot be further normalized, + /// resolved, or instantiated. This includes all primitive types, but also + /// things like ADTs and trait objects, since even if their arguments or + /// nested types may be further simplified, the outermost [`TyKind`] or + /// type constructor remains the same. + #[inline] + pub fn is_known_rigid(self) -> bool { + self.kind().is_known_rigid() + } + + /// Iterator that walks `self` and any types reachable from + /// `self`, in depth-first order. Note that just walks the types + /// that appear in `self`, it does not descend into the fields of + /// structs or variants. For example: + /// + /// ```text + /// isize => { isize } + /// Foo> => { Foo>, Bar, isize } + /// [isize] => { [isize], isize } + /// ``` + pub fn walk(self) -> TypeWalker { + TypeWalker::new(self.into()) + } + + #[inline] + pub fn is_guaranteed_unsized_raw(self) -> bool { + match self.kind() { + ty::Dynamic(_, _) | ty::Slice(_) | ty::Str => true, + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Adt(_, _) + | ty::Foreign(_) + | ty::Array(_, _) + | ty::Pat(_, _) + | ty::RawPtr(_, _) + | ty::Ref(_, _, _) + | ty::FnDef(_, _) + | ty::FnPtr(_, _) + | ty::UnsafeBinder(_) + | ty::Closure(_, _) + | ty::CoroutineClosure(_, _) + | ty::Coroutine(_, _) + | ty::CoroutineWitness(_, _) + | ty::Never + | ty::Tuple(_) + | ty::Alias(_, _) + | ty::Param(_) + | ty::Bound(_, _) + | ty::Placeholder(_) + | ty::Infer(_) + | ty::Error(_) => false, + } + } + + #[inline] + pub fn new_int(interner: I, i: ty::IntTy) -> Self { + use ty::IntTy::*; + let int_ty = match i { + Isize => ty::Int(ty::IntTy::Isize), + I8 => ty::Int(ty::IntTy::I8), + I16 => ty::Int(ty::IntTy::I16), + I32 => ty::Int(ty::IntTy::I32), + I64 => ty::Int(ty::IntTy::I64), + I128 => ty::Int(ty::IntTy::I128), + }; + Self::new(interner, int_ty) + } + + #[inline] + pub fn new_uint(interner: I, ui: ty::UintTy) -> Self { + use ty::UintTy::*; + let unsigned_int_ty = match ui { + Usize => ty::Uint(ty::UintTy::Usize), + U8 => ty::Uint(ty::UintTy::U8), + U16 => ty::Uint(ty::UintTy::U16), + U32 => ty::Uint(ty::UintTy::U32), + U64 => ty::Uint(ty::UintTy::U64), + U128 => ty::Uint(ty::UintTy::U128), + }; + Self::new(interner, unsigned_int_ty) + } + + #[inline] + pub fn new_float(interner: I, f: ty::FloatTy) -> Self { + use ty::FloatTy::*; + let float_ty = match f { + F16 => ty::Float(ty::FloatTy::F16), + F32 => ty::Float(ty::FloatTy::F32), + F64 => ty::Float(ty::FloatTy::F64), + F128 => ty::Float(ty::FloatTy::F128), + }; + Self::new(interner, float_ty) + } + + #[inline] + pub fn new_field_representing_type( + interner: I, + base: Self, + variant: VariantIdx, + field: FieldIdx, + ) -> Self { + interner.new_field_representing_type(base, variant, field) + } +} diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 8e7414674c6e7..90c3d7d1afe65 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -11,7 +11,7 @@ use rustc_type_ir_macros::{ use crate::data_structures::HashMap; use crate::inherent::*; -use crate::{self as ty, Interner, TypingMode, UniverseIndex}; +use crate::{self as ty, Interner, Ty, TypingMode, UniverseIndex}; #[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, V)] #[derive_where(Copy; I: Interner, V: Copy)] diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index 2f7c78d497a4f..4a86791918aba 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -6,7 +6,7 @@ use crate::data_structures::HashSet; use crate::inherent::*; use crate::lang_items::SolverTraitLangItem; use crate::outlives::{Component, push_outlives_components}; -use crate::{self as ty, Interner, Upcast as _}; +use crate::{self as ty, Interner, Ty, Upcast as _}; /// "Elaboration" is the process of identifying all the predicates that /// are implied by a source predicate. Currently, this basically means diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs index eba4c7c6644ac..ef542af7f1f9a 100644 --- a/compiler/rustc_type_ir/src/error.rs +++ b/compiler/rustc_type_ir/src/error.rs @@ -2,7 +2,7 @@ use derive_where::derive_where; use rustc_type_ir_macros::{GenericTypeVisitable, TypeFoldable_Generic, TypeVisitable_Generic}; use crate::solve::NoSolution; -use crate::{self as ty, Interner}; +use crate::{self as ty, Interner, Ty}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(TypeFoldable_Generic, TypeVisitable_Generic, GenericTypeVisitable)] @@ -36,15 +36,15 @@ pub enum TypeError { RegionsInsufficientlyPolymorphic(ty::BoundRegion, I::Region), RegionsPlaceholderMismatch, - Sorts(ExpectedFound), - ArgumentSorts(ExpectedFound, usize), + Sorts(ExpectedFound>), + ArgumentSorts(ExpectedFound>, usize), Traits(ExpectedFound), VariadicMismatch(ExpectedFound), /// Instantiating a type variable with the given type would have /// created a cycle (because it appears somewhere within that /// type). - CyclicTy(I::Ty), + CyclicTy(Ty), CyclicConst(I::Const), ProjectionMismatched(ExpectedFound), ExistentialMismatch(ExpectedFound), diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index ed6416a7f55f2..8a14e6e6eaf5f 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -13,7 +13,7 @@ use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContex use crate::inherent::*; use crate::visit::TypeVisitableExt as _; -use crate::{self as ty, Interner}; +use crate::{self as ty, Interner, Ty}; /// See `simplify_type`. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] @@ -113,7 +113,7 @@ pub enum TreatParams { /// ¹ meaning that if the outermost layers are different, then the whole types are also different. pub fn simplify_type( cx: I, - ty: I::Ty, + ty: Ty, treat_params: TreatParams, ) -> Option> { match ty.kind() { @@ -236,11 +236,11 @@ impl bool { + pub fn types_may_unify(self, lhs: Ty, rhs: Ty) -> bool { self.types_may_unify_inner(lhs, rhs, Self::STARTING_DEPTH) } - pub fn types_may_unify_with_depth(self, lhs: I::Ty, rhs: I::Ty, depth_limit: usize) -> bool { + pub fn types_may_unify_with_depth(self, lhs: Ty, rhs: Ty, depth_limit: usize) -> bool { self.types_may_unify_inner(lhs, rhs, depth_limit) } @@ -268,7 +268,7 @@ impl bool { + fn types_may_unify_inner(self, lhs: Ty, rhs: Ty, depth: usize) -> bool { if lhs == rhs { return true; } @@ -527,7 +527,7 @@ impl bool { + fn var_and_ty_may_unify(self, var: ty::InferTy, ty: Ty) -> bool { if !ty.is_known_rigid() { return true; } diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 8b057e5866cd9..19d7465ba2c50 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -1,6 +1,6 @@ use crate::inherent::*; use crate::visit::Flags; -use crate::{self as ty, Interner}; +use crate::{self as ty, Interner, Ty}; bitflags::bitflags! { /// Flags that we track on types. These flags are propagated upwards @@ -430,7 +430,7 @@ impl FlagComputation { } } - fn add_ty(&mut self, ty: I::Ty) { + fn add_ty(&mut self, ty: Ty) { self.add_flags(ty.flags()); self.add_exclusive_binder(ty.outer_exclusive_binder()); } diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index d1a50599e8b9c..67170b83042a5 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -55,7 +55,7 @@ use tracing::{debug, instrument}; use crate::inherent::*; use crate::visit::{TypeVisitable, TypeVisitableExt as _}; -use crate::{self as ty, BoundVarIndexKind, Interner, TypeFlags}; +use crate::{self as ty, BoundVarIndexKind, Interner, Ty, TypeFlags}; /// This trait is implemented for every type that can be folded, /// providing the skeleton of the traversal. @@ -135,7 +135,7 @@ pub trait TypeFolder: Sized { t.super_fold_with(self) } - fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn fold_ty(&mut self, t: Ty) -> Ty { t.super_fold_with(self) } @@ -177,7 +177,7 @@ pub trait FallibleTypeFolder: Sized { t.try_super_fold_with(self) } - fn try_fold_ty(&mut self, t: I::Ty) -> Result { + fn try_fold_ty(&mut self, t: Ty) -> Result, Self::Error> { t.try_super_fold_with(self) } @@ -408,7 +408,7 @@ impl TypeFolder for Shifter { } } - fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { + fn fold_ty(&mut self, ty: Ty) -> Ty { match ty.kind() { ty::Bound(BoundVarIndexKind::Bound(debruijn), bound_ty) if debruijn >= self.current_index => @@ -538,7 +538,7 @@ where } } - fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn fold_ty(&mut self, t: Ty) -> Ty { if t.has_type_flags( TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_RE_BOUND | TypeFlags::HAS_RE_ERASED, ) { diff --git a/compiler/rustc_type_ir/src/generic_arg.rs b/compiler/rustc_type_ir/src/generic_arg.rs index 5d612740fdd84..22a4ebd03b69c 100644 --- a/compiler/rustc_type_ir/src/generic_arg.rs +++ b/compiler/rustc_type_ir/src/generic_arg.rs @@ -3,7 +3,7 @@ use derive_where::derive_where; use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use rustc_type_ir_macros::GenericTypeVisitable; -use crate::Interner; +use crate::{Interner, Ty}; #[derive_where(Clone, Copy, PartialEq, Debug; I: Interner)] #[derive(GenericTypeVisitable)] @@ -13,7 +13,7 @@ use crate::Interner; )] pub enum GenericArgKind { Lifetime(I::Region), - Type(I::Ty), + Type(Ty), Const(I::Const), } @@ -26,7 +26,7 @@ impl Eq for GenericArgKind {} derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) )] pub enum TermKind { - Ty(I::Ty), + Ty(Ty), Const(I::Const), } diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index feafcee7bad9e..843d1eb37b7d9 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -6,7 +6,7 @@ use crate::fold::TypeFoldable; use crate::inherent::*; use crate::relate::RelateResult; use crate::relate::combine::PredicateEmittingRelation; -use crate::{self as ty, Interner, TyVid}; +use crate::{self as ty, Interner, Ty, TyVid}; /// The current typing mode of an inference context. We unfortunately have some /// slightly different typing rules depending on the current context. See the @@ -161,12 +161,9 @@ pub trait InferCtxtLike: Sized { fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid; fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid; - fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> ::Ty; - fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> ::Ty; - fn opportunistic_resolve_float_var( - &self, - vid: ty::FloatVid, - ) -> ::Ty; + fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> Ty; + fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty; + fn opportunistic_resolve_float_var(&self, vid: ty::FloatVid) -> Ty; fn opportunistic_resolve_ct_var( &self, vid: ty::ConstVid, @@ -179,7 +176,7 @@ pub trait InferCtxtLike: Sized { fn is_changed_arg(&self, arg: ::GenericArg) -> bool; fn next_region_infer(&self) -> ::Region; - fn next_ty_infer(&self) -> ::Ty; + fn next_ty_infer(&self) -> Ty; fn next_const_infer(&self) -> ::Const; fn fresh_args_for_item( &self, @@ -209,7 +206,7 @@ pub trait InferCtxtLike: Sized { target_is_expected: bool, target_vid: ty::TyVid, instantiation_variance: ty::Variance, - source_ty: ::Ty, + source_ty: Ty, ) -> RelateResult; fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue); fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue); @@ -223,10 +220,7 @@ pub trait InferCtxtLike: Sized { fn set_tainted_by_errors(&self, e: ::ErrorGuaranteed); - fn shallow_resolve( - &self, - ty: ::Ty, - ) -> ::Ty; + fn shallow_resolve(&self, ty: Ty) -> Ty; fn shallow_resolve_const( &self, ty: ::Const, @@ -254,7 +248,7 @@ pub trait InferCtxtLike: Sized { fn register_ty_outlives( &self, - ty: ::Ty, + ty: Ty, r: ::Region, span: ::Span, ); @@ -263,26 +257,26 @@ pub trait InferCtxtLike: Sized { fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries; fn clone_opaque_types_lookup_table( &self, - ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; + ) -> Vec<(ty::OpaqueTypeKey, Ty)>; fn clone_duplicate_opaque_types( &self, - ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; + ) -> Vec<(ty::OpaqueTypeKey, Ty)>; fn clone_opaque_types_added_since( &self, prev_entries: Self::OpaqueTypeStorageEntries, - ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; + ) -> Vec<(ty::OpaqueTypeKey, Ty)>; fn opaques_with_sub_unified_hidden_type(&self, ty: TyVid) -> Vec>; fn register_hidden_type_in_storage( &self, opaque_type_key: ty::OpaqueTypeKey, - hidden_ty: ::Ty, + hidden_ty: Ty, span: ::Span, - ) -> Option<::Ty>; + ) -> Option>; fn add_duplicate_opaque_type( &self, opaque_type_key: ty::OpaqueTypeKey, - hidden_ty: ::Ty, + hidden_ty: Ty, span: ::Span, ); diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 8256ea7ed312e..2f4b02d46017d 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -3,206 +3,23 @@ //! scope when programming in interner-agnostic settings, and to avoid importing any of these //! directly elsewhere (i.e. specify the full path for an implementation downstream). +use core::ops::Range; use std::fmt::Debug; use std::hash::Hash; -use rustc_ast_ir::Mutability; - use crate::elaborate::Elaboratable; use crate::fold::{TypeFoldable, TypeSuperFoldable}; use crate::relate::Relate; use crate::solve::{AdtDestructorKind, SizedTraitKind}; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; -use crate::{ - self as ty, ClauseKind, CollectAndApply, FieldInfo, Interner, PredicateKind, UpcastFrom, -}; - -pub trait Ty>: - Copy - + Debug - + Hash - + Eq - + Into - + Into - + IntoKind> - + TypeSuperVisitable - + TypeSuperFoldable - + Relate - + Flags -{ - fn new_unit(interner: I) -> Self; - - fn new_bool(interner: I) -> Self; - - fn new_u8(interner: I) -> Self; - - fn new_usize(interner: I) -> Self; - - fn new_infer(interner: I, var: ty::InferTy) -> Self; - - fn new_var(interner: I, var: ty::TyVid) -> Self; - - fn new_param(interner: I, param: I::ParamTy) -> Self; - - fn new_placeholder(interner: I, param: ty::PlaceholderType) -> Self; - - fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundTy) -> Self; - - fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self; - - fn new_canonical_bound(interner: I, var: ty::BoundVar) -> Self; - - fn new_alias(interner: I, kind: ty::AliasTyKind, alias_ty: ty::AliasTy) -> Self; - - fn new_projection_from_args(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self { - Ty::new_alias( - interner, - ty::AliasTyKind::Projection, - ty::AliasTy::new_from_args(interner, def_id, args), - ) - } - - fn new_projection( - interner: I, - def_id: I::DefId, - args: impl IntoIterator>, - ) -> Self { - Ty::new_alias( - interner, - ty::AliasTyKind::Projection, - ty::AliasTy::new(interner, def_id, args), - ) - } - - fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self; - - fn new_adt(interner: I, adt_def: I::AdtDef, args: I::GenericArgs) -> Self; - - fn new_foreign(interner: I, def_id: I::ForeignId) -> Self; - - fn new_dynamic(interner: I, preds: I::BoundExistentialPredicates, region: I::Region) -> Self; - - fn new_coroutine(interner: I, def_id: I::CoroutineId, args: I::GenericArgs) -> Self; - - fn new_coroutine_closure( - interner: I, - def_id: I::CoroutineClosureId, - args: I::GenericArgs, - ) -> Self; - - fn new_closure(interner: I, def_id: I::ClosureId, args: I::GenericArgs) -> Self; - - fn new_coroutine_witness(interner: I, def_id: I::CoroutineId, args: I::GenericArgs) -> Self; - - fn new_coroutine_witness_for_coroutine( - interner: I, - def_id: I::CoroutineId, - coroutine_args: I::GenericArgs, - ) -> Self; - - fn new_ptr(interner: I, ty: Self, mutbl: Mutability) -> Self; - - fn new_ref(interner: I, region: I::Region, ty: Self, mutbl: Mutability) -> Self; - - fn new_array_with_const_len(interner: I, ty: Self, len: I::Const) -> Self; - - fn new_slice(interner: I, ty: Self) -> Self; - - fn new_tup(interner: I, tys: &[I::Ty]) -> Self; - - fn new_tup_from_iter(interner: I, iter: It) -> T::Output - where - It: Iterator, - T: CollectAndApply; - - fn new_fn_def(interner: I, def_id: I::FunctionId, args: I::GenericArgs) -> Self; - - fn new_fn_ptr(interner: I, sig: ty::Binder>) -> Self; - - fn new_pat(interner: I, ty: Self, pat: I::Pat) -> Self; - - fn new_unsafe_binder(interner: I, ty: ty::Binder) -> Self; - - fn tuple_fields(self) -> I::Tys; - - fn to_opt_closure_kind(self) -> Option; - - fn from_closure_kind(interner: I, kind: ty::ClosureKind) -> Self; - - fn from_coroutine_closure_kind(interner: I, kind: ty::ClosureKind) -> Self; - - fn is_ty_var(self) -> bool { - matches!(self.kind(), ty::Infer(ty::TyVar(_))) - } - - fn is_ty_error(self) -> bool { - matches!(self.kind(), ty::Error(_)) - } - - fn is_floating_point(self) -> bool { - matches!(self.kind(), ty::Float(_) | ty::Infer(ty::FloatVar(_))) - } - - fn is_integral(self) -> bool { - matches!(self.kind(), ty::Infer(ty::IntVar(_)) | ty::Int(_) | ty::Uint(_)) - } - - fn is_fn_ptr(self) -> bool { - matches!(self.kind(), ty::FnPtr(..)) - } - - /// Checks whether this type is an ADT that has unsafe fields. - fn has_unsafe_fields(self) -> bool; - - fn fn_sig(self, interner: I) -> ty::Binder> { - self.kind().fn_sig(interner) - } - - fn discriminant_ty(self, interner: I) -> I::Ty; - - fn is_known_rigid(self) -> bool { - self.kind().is_known_rigid() - } - - fn is_guaranteed_unsized_raw(self) -> bool { - match self.kind() { - ty::Dynamic(_, _) | ty::Slice(_) | ty::Str => true, - ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Adt(_, _) - | ty::Foreign(_) - | ty::Array(_, _) - | ty::Pat(_, _) - | ty::RawPtr(_, _) - | ty::Ref(_, _, _) - | ty::FnDef(_, _) - | ty::FnPtr(_, _) - | ty::UnsafeBinder(_) - | ty::Closure(_, _) - | ty::CoroutineClosure(_, _) - | ty::Coroutine(_, _) - | ty::CoroutineWitness(_, _) - | ty::Never - | ty::Tuple(_) - | ty::Alias(_, _) - | ty::Param(_) - | ty::Bound(_, _) - | ty::Placeholder(_) - | ty::Infer(_) - | ty::Error(_) => false, - } - } -} +use crate::{self as ty, ClauseKind, FieldInfo, Interner, PredicateKind, Ty, UpcastFrom}; pub trait Tys>: - Copy + Debug + Hash + Eq + SliceLike + TypeFoldable + Default + Copy + Debug + Hash + Eq + SliceLike> + TypeFoldable + Default { fn inputs(self) -> I::FnInputTys; - fn output(self) -> I::Ty; + fn output(self) -> Ty; } pub trait Abi>: Copy + Debug + Hash + Eq { @@ -287,10 +104,14 @@ pub trait Const>: fn is_ct_error(self) -> bool { matches!(self.kind(), ty::ConstKind::Error(_)) } + + fn try_to_target_usize(self, interner: I) -> Option; + + fn from_target_usize(interner: I, n: u64) -> Self; } pub trait ValueConst>: Copy + Debug + Hash + Eq { - fn ty(self) -> I::Ty; + fn ty(self) -> Ty; fn valtree(self) -> I::ValTree; } @@ -316,7 +137,7 @@ pub trait GenericArg>: + IntoKind> + TypeVisitable + Relate - + From + + From> + From + From + From @@ -329,11 +150,11 @@ pub trait GenericArg>: } } - fn as_type(&self) -> Option { + fn as_type(&self) -> Option> { if let ty::GenericArgKind::Type(ty) = self.kind() { Some(ty) } else { None } } - fn expect_ty(&self) -> I::Ty { + fn expect_ty(&self) -> Ty { self.as_type().expect("expected a type") } @@ -363,13 +184,20 @@ pub trait GenericArg>: } pub trait Term>: - Copy + Debug + Hash + Eq + IntoKind> + TypeFoldable + Relate + Copy + + Debug + + Hash + + Eq + + From> + + IntoKind> + + TypeFoldable + + Relate { - fn as_type(&self) -> Option { + fn as_type(&self) -> Option> { if let ty::TermKind::Ty(ty) = self.kind() { Some(ty) } else { None } } - fn expect_ty(&self) -> I::Ty { + fn expect_ty(&self) -> Ty { self.as_type().expect("expected a type, but found a const") } @@ -419,7 +247,7 @@ pub trait GenericArgs>: target: I::GenericArgs, ) -> I::GenericArgs; - fn type_at(self, i: usize) -> I::Ty; + fn type_at(self, i: usize) -> Ty; fn region_at(self, i: usize) -> I::Region; @@ -446,6 +274,15 @@ pub trait GenericArgs>: fn as_coroutine(self) -> ty::CoroutineArgs { ty::CoroutineArgs { args: self } } + + fn coroutine_discriminant_for_variant( + self, + def_id: I::DefId, + interner: I, + variant_index: I::VariantIdx, + ) -> I::Discr; + + fn as_coroutine_discr_ty(self, interner: I) -> Ty; } pub trait Predicate>: @@ -465,7 +302,7 @@ pub trait Predicate>: + UpcastFrom> + UpcastFrom>> + UpcastFrom> - + UpcastFrom> + + UpcastFrom>> + UpcastFrom> + IntoKind>> + Elaboratable @@ -581,10 +418,18 @@ pub trait AdtDef: Copy + Debug + Hash + Eq { fn is_packed(self) -> bool; + fn is_box(self) -> bool; + + fn is_pin(self) -> bool; + + fn is_enum(self) -> bool; + + fn is_union(self) -> bool; + /// Returns the type of the struct tail. /// /// Expects the `AdtDef` to be a struct. If it is not, then this will panic. - fn struct_tail_ty(self, interner: I) -> Option>; + fn struct_tail_ty(self, interner: I) -> Option>>; fn is_phantom_data(self) -> bool; @@ -596,18 +441,38 @@ pub trait AdtDef: Copy + Debug + Hash + Eq { args: I::GenericArgs, ) -> Option>; + fn has_unsafe_fields(self) -> bool; + // FIXME: perhaps use `all_fields` and expose `FieldDef`. - fn all_field_tys(self, interner: I) -> ty::EarlyBinder>; + fn all_field_tys(self, interner: I) -> ty::EarlyBinder>>; fn sizedness_constraint( self, interner: I, sizedness: SizedTraitKind, - ) -> Option>; + ) -> Option>>; fn is_fundamental(self) -> bool; fn destructor(self, interner: I) -> Option; + + fn non_enum_variant(self) -> I::VariantDef; + + fn repr_is_simd(self) -> bool; + + fn scalable_element_cnt(self) -> Option; + + fn variant_range(self) -> Range; + + fn discriminant_for_variant(self, interner: I, variant_index: I::VariantIdx) -> I::Discr; + + fn repr_discr_type_to_ty(self, interner: I) -> Ty; +} + +pub trait VariantDef: Debug + Hash { + fn field_zero_ty(self, interner: I, args: I::GenericArgs) -> Ty; + + fn fields_len(self) -> usize; } pub trait ParamEnv: Copy + Debug + Hash + Eq + TypeFoldable { @@ -701,6 +566,10 @@ pub trait SliceLike: Sized + Copy { fn split_last(&self) -> Option<(&Self::Item, &[Self::Item])> { self.as_slice().split_last() } + + fn first(&self) -> Option<&Self::Item> { + self.as_slice().first() + } } impl<'a, T: Copy> SliceLike for &'a [T] { @@ -745,3 +614,7 @@ impl<'a, S: SliceLike> SliceLike for &'a S { pub trait Symbol: Copy + Hash + PartialEq + Eq + Debug { fn is_kw_underscore_lifetime(self) -> bool; } + +pub trait Interned: Clone + Copy + Hash + PartialEq + Eq + Debug { + fn new_unchecked(t: &T) -> Self; +} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 8f446cdfba6d5..2b3e5df21eb90 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -1,8 +1,9 @@ use std::borrow::Borrow; use std::fmt::Debug; use std::hash::Hash; -use std::ops::Deref; +use std::ops::{Deref, Range}; +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_ast_ir::Movability; use rustc_index::bit_set::DenseBitSet; @@ -13,7 +14,7 @@ use crate::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem}; use crate::relate::Relate; use crate::solve::{CanonicalInput, Certainty, ExternalConstraintsData, QueryResult, inspect}; use crate::visit::{Flags, TypeVisitable}; -use crate::{self as ty, CanonicalParamEnvCacheEntry, search_graph}; +use crate::{self as ty, CanonicalParamEnvCacheEntry, Ty, search_graph}; #[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_interner")] pub trait Interner: @@ -52,6 +53,8 @@ pub trait Interner: type CoroutineClosureId: SpecificDefId; type CoroutineId: SpecificDefId; type AdtId: SpecificDefId; + type AdtDef: AdtDef; + type VariantDef: VariantDef; type ImplId: SpecificDefId; type UnevaluatedConstId: SpecificDefId; type Span: Span; @@ -73,10 +76,10 @@ pub trait Interner: + Hash + Eq + TypeFoldable - + SliceLike, Self::Ty)>; + + SliceLike, Ty)>; fn mk_predefined_opaques_in_body( self, - data: &[(ty::OpaqueTypeKey, Self::Ty)], + data: &[(ty::OpaqueTypeKey, Ty)], ) -> Self::PredefinedOpaques; type LocalDefIds: Copy @@ -120,14 +123,13 @@ pub trait Interner: fn with_cached_task(self, task: impl FnOnce() -> T) -> (T, Self::DepNodeIndex); // Kinds of tys - type Ty: Ty; type Tys: Tys; - type FnInputTys: Copy + Debug + Hash + Eq + SliceLike + TypeVisitable; + type FnInputTys: Copy + Debug + Hash + Eq + SliceLike> + TypeVisitable; type ParamTy: ParamLike; type Symbol: Symbol; // Things stored inside of tys - type ErrorGuaranteed: Copy + Debug + Hash + Eq; + type ErrorGuaranteed: Copy + Debug + Hash + Eq + TypeVisitable; type BoundExistentialPredicates: BoundExistentialPredicates; type AllocId: Copy + Debug + Hash + Eq; type Pat: Copy @@ -174,6 +176,18 @@ pub trait Interner: type Clause: Clause; type Clauses: Clauses; + type Interned: Copy + + Clone + + Debug + + Hash + + Eq + + PartialEq + + Deref; + type VariantIdx; + type Discr: Debug + Copy + Clone; + type ObligationCause: Debug + Clone; + type LangItem: Debug + Copy + Clone; + fn with_global_cache(self, f: impl FnOnce(&mut search_graph::GlobalCache) -> R) -> R; fn canonical_param_env_cache_get_or_insert( @@ -201,13 +215,12 @@ pub trait Interner: def_id: Self::DefId, ) -> Option; - fn type_of(self, def_id: Self::DefId) -> ty::EarlyBinder; + fn type_of(self, def_id: Self::DefId) -> ty::EarlyBinder>; fn type_of_opaque_hir_typeck(self, def_id: Self::LocalDefId) - -> ty::EarlyBinder; + -> ty::EarlyBinder>; fn const_of_item(self, def_id: Self::DefId) -> ty::EarlyBinder; fn anon_const_kind(self, def_id: Self::DefId) -> ty::AnonConstKind; - type AdtDef: AdtDef; fn adt_def(self, adt_def_id: Self::AdtId) -> Self::AdtDef; fn alias_ty_kind(self, alias: ty::AliasTy) -> ty::AliasTyKind; @@ -231,6 +244,12 @@ pub trait Interner: fn debug_assert_args_compatible(self, def_id: Self::DefId, args: Self::GenericArgs); + fn debug_assert_adt_def_compatible(self, adt: Self::AdtDef); + + fn debug_assert_new_dynamic_compatible(self, obj: Self::BoundExistentialPredicates); + + fn typeck_root_def_id(self, def_id: Self::DefId) -> Self::DefId; + /// Assert that the args from an `ExistentialTraitRef` or `ExistentialProjection` /// are compatible with the `DefId`. fn debug_assert_existential_args_compatible(self, def_id: Self::DefId, args: Self::GenericArgs); @@ -238,7 +257,17 @@ pub trait Interner: fn mk_type_list_from_iter(self, args: I) -> T::Output where I: Iterator, - T: CollectAndApply; + T: CollectAndApply, Self::Tys>; + + fn mk_ty_from_kind(self, kind: ty::TyKind) -> Ty; + + fn mk_coroutine_witness_for_coroutine( + self, + def_id: Self::CoroutineId, + args: Self::GenericArgs, + ) -> Ty; + + fn ty_discriminant_ty(self, ty: Ty) -> Ty; fn parent(self, def_id: Self::DefId) -> Self::DefId; @@ -329,6 +358,8 @@ pub trait Interner: fn is_lang_item(self, def_id: Self::DefId, lang_item: SolverLangItem) -> bool; + fn is_c_void(self, def_id: Self::AdtDef) -> bool; + fn is_trait_lang_item(self, def_id: Self::TraitId, lang_item: SolverTraitLangItem) -> bool; fn is_adt_lang_item(self, def_id: Self::AdtId, lang_item: SolverAdtLangItem) -> bool; @@ -351,7 +382,7 @@ pub trait Interner: fn for_each_relevant_impl( self, trait_def_id: Self::TraitId, - self_ty: Self::Ty, + self_ty: Ty, f: impl FnMut(Self::ImplId), ); fn for_each_blanket_impl(self, trait_def_id: Self::TraitId, f: impl FnMut(Self::ImplId)); @@ -412,6 +443,86 @@ pub trait Interner: ) -> (QueryResult, Self::Probe); fn item_name(self, item_index: Self::DefId) -> Self::Symbol; + + fn i8_type(self) -> Ty; + + fn i16_type(self) -> Ty; + + fn i32_type(self) -> Ty; + + fn u8_type(self) -> Ty; + + fn usize_type(self) -> Ty; + + fn unit_type(self) -> Ty; + + fn is_async_drop_in_place_coroutine(self, def_id: Self::DefId) -> bool; + + fn coroutine_variant_range( + self, + def_id: Self::DefId, + coroutine_args: ty::CoroutineArgs, + ) -> Range; + + fn struct_tail_raw( + self, + ty: Ty, + cause: &Self::ObligationCause, + normalize: impl FnMut(Ty) -> Ty, + f: impl FnMut() -> (), + ) -> Ty; + + fn get_ty_var(self, id: usize) -> Option>; + + fn get_fresh_ty(self, id: usize) -> Option>; + + fn get_fresh_ty_int(self, id: usize) -> Option>; + + fn get_fresh_ty_float(self, id: usize) -> Option>; + + fn get_anon_bound_ty(self, id: usize) -> Option>>; + + fn get_anon_canonical_bound_ty(self, id: usize) -> Option>; + + fn get_generic_args_for_item(self, def_id: Self::DefId) -> Self::GenericArgs; + + fn new_static_str(self) -> Ty; + + fn get_generic_adt_args( + self, + wrapper_def_id: Self::DefId, + ty_param: Ty, + ) -> Self::GenericArgs; + + fn get_lang_item(self, item: Self::LangItem) -> Option; + + fn get_diagnostic_item(self, name: Self::Symbol) -> Option; + + fn require_lang_item_owned_box(self) -> Self::DefId; + + fn require_lang_item_option(self) -> Self::DefId; + + fn require_lang_item_maybe_uninit(self) -> Self::DefId; + + fn require_lang_item_pin(self) -> Self::DefId; + + fn require_lang_item_context(self) -> Self::DefId; + + fn new_field_representing_type( + self, + base: Ty, + variant: VariantIdx, + field: FieldIdx, + ) -> Ty; + + fn get_re_erased_region(self) -> Self::Region; + + fn new_generic_adt(self, wrapper_def_id: Self::DefId, ty_param: Ty) -> Ty; + + fn new_pinned_ref(self, r: Self::Region, ty: Ty, mutbl: ty::Mutability) -> Ty; + + /// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes. + fn new_task_context(self) -> Ty; } /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter` diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs index 5af2bd811bab4..1fc296f4787e1 100644 --- a/compiler/rustc_type_ir/src/ir_print.rs +++ b/compiler/rustc_type_ir/src/ir_print.rs @@ -3,7 +3,7 @@ use std::fmt; use crate::{ AliasTerm, AliasTy, Binder, ClosureKind, CoercePredicate, ExistentialProjection, ExistentialTraitRef, FnSig, HostEffectPredicate, Interner, NormalizesTo, OutlivesPredicate, - PatternKind, Placeholder, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef, + PatternKind, Placeholder, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef, Ty, UnevaluatedConst, }; @@ -54,6 +54,15 @@ define_display_via_print!( define_debug_via_print!(TraitRef, ExistentialTraitRef, PatternKind); +impl fmt::Display for Ty +where + I: IrPrint>, +{ + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + >>::print(self, fmt) + } +} + impl fmt::Display for OutlivesPredicate where I: IrPrint>, @@ -117,6 +126,15 @@ mod into_diag_arg_impls { } } + impl IntoDiagArg for Ty + where + I: IrPrint>, + { + fn into_diag_arg(self, path: &mut Option) -> DiagArgValue { + self.to_string().into_diag_arg(path) + } + } + impl IntoDiagArg for ClosureKind { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(self.as_str().into()) diff --git a/compiler/rustc_type_ir/src/lang_items.rs b/compiler/rustc_type_ir/src/lang_items.rs index f1c45a4d98b5e..d828726cca82e 100644 --- a/compiler/rustc_type_ir/src/lang_items.rs +++ b/compiler/rustc_type_ir/src/lang_items.rs @@ -12,6 +12,7 @@ pub enum SolverLangItem { FieldBase, FieldType, FutureOutput, + GlobalAlloc, Metadata, // tidy-alphabetical-end } diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 62965f947387c..cce229fdbb8e9 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -5,7 +5,18 @@ #![allow(rustc::usage_of_type_ir_inherent)] #![allow(rustc::usage_of_type_ir_traits)] #![cfg_attr(feature = "nightly", allow(internal_features))] -#![cfg_attr(feature = "nightly", feature(associated_type_defaults, rustc_attrs, negative_impls))] +#![cfg_attr( + feature = "nightly", + feature( + associated_type_defaults, + core_intrinsics, + discriminant_kind, + if_let_guard, + negative_impls, + rustc_attrs, + sized_hierarchy + ) +)] // tidy-alphabetical-end extern crate self as rustc_type_ir; @@ -18,6 +29,7 @@ use rustc_abi::{FieldIdx, VariantIdx}; use rustc_macros::{Decodable, Encodable, HashStable_NoContext}; // These modules are `pub` since they are not glob-imported. +#[cfg(feature = "nightly")] pub mod data_structures; pub mod elaborate; pub mod error; @@ -443,8 +455,8 @@ impl fmt::Display for ClosureKind { } pub struct FieldInfo { - pub base: I::Ty, - pub ty: I::Ty, + pub base: Ty, + pub ty: Ty, pub variant: Option, pub variant_idx: VariantIdx, pub name: I::Symbol, diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index 300e5c0b46956..cc79d6589e6fb 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -8,7 +8,7 @@ use smallvec::{SmallVec, smallvec}; use crate::data_structures::SsoHashSet; use crate::inherent::*; use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt as _, TypeVisitor}; -use crate::{self as ty, Interner}; +use crate::{self as ty, Interner, Ty}; #[derive_where(Debug; I: Interner)] pub enum Component { @@ -55,7 +55,7 @@ pub enum Component { /// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**. pub fn push_outlives_components( cx: I, - ty: I::Ty, + ty: Ty, out: &mut SmallVec<[Component; 4]>, ) { ty.visit_with(&mut OutlivesCollector { cx, out, visited: Default::default() }); @@ -64,14 +64,14 @@ pub fn push_outlives_components( struct OutlivesCollector<'a, I: Interner> { cx: I, out: &'a mut SmallVec<[Component; 4]>, - visited: SsoHashSet, + visited: SsoHashSet>, } impl TypeVisitor for OutlivesCollector<'_, I> { #[cfg(not(feature = "nightly"))] type Result = (); - fn visit_ty(&mut self, ty: I::Ty) -> Self::Result { + fn visit_ty(&mut self, ty: Ty) -> Self::Result { if !self.visited.insert(ty) { return; } diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 113192cc02eb8..908364068ec33 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -14,7 +14,7 @@ use crate::inherent::*; use crate::lift::Lift; use crate::upcast::{Upcast, UpcastFrom}; use crate::visit::TypeVisitableExt as _; -use crate::{self as ty, Interner}; +use crate::{self as ty, Interner, Ty}; /// `A: 'region` #[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, A)] @@ -101,7 +101,7 @@ impl TraitRef { ) } - pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self { + pub fn with_replaced_self_ty(self, interner: I, self_ty: Ty) -> Self { TraitRef::new( interner, self.def_id, @@ -110,13 +110,13 @@ impl TraitRef { } #[inline] - pub fn self_ty(&self) -> I::Ty { + pub fn self_ty(&self) -> Ty { self.args.type_at(0) } } impl ty::Binder> { - pub fn self_ty(&self) -> ty::Binder { + pub fn self_ty(&self) -> ty::Binder> { self.map_bound_ref(|tr| tr.self_ty()) } @@ -152,7 +152,7 @@ pub struct TraitPredicate { impl Eq for TraitPredicate {} impl TraitPredicate { - pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self { + pub fn with_replaced_self_ty(self, interner: I, self_ty: Ty) -> Self { Self { trait_ref: self.trait_ref.with_replaced_self_ty(interner, self_ty), polarity: self.polarity, @@ -163,7 +163,7 @@ impl TraitPredicate { self.trait_ref.def_id } - pub fn self_ty(self) -> I::Ty { + pub fn self_ty(self) -> Ty { self.trait_ref.self_ty() } } @@ -174,7 +174,7 @@ impl ty::Binder> { self.skip_binder().def_id() } - pub fn self_ty(self) -> ty::Binder { + pub fn self_ty(self) -> ty::Binder> { self.map_bound(|trait_ref| trait_ref.self_ty()) } @@ -307,7 +307,7 @@ impl ty::Binder> { /// Given an existential predicate like `?Self: PartialEq` (e.g., derived from `dyn PartialEq`), /// 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`, in our example). - pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> I::Clause { + pub fn with_self_ty(&self, cx: I, self_ty: Ty) -> I::Clause { match self.skip_binder() { ExistentialPredicate::Trait(tr) => self.rebind(tr).with_self_ty(cx, self_ty).upcast(cx), ExistentialPredicate::Projection(p) => { @@ -384,7 +384,7 @@ impl ExistentialTraitRef { /// we convert the principal trait-ref into a normal trait-ref, /// you must give *some* self type. A common choice is `mk_err()` /// or some placeholder type. - pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> TraitRef { + pub fn with_self_ty(self, interner: I, self_ty: Ty) -> TraitRef { // otherwise the escaping vars would be captured by the binder // debug_assert!(!self_ty.has_escaping_bound_vars()); @@ -401,7 +401,7 @@ impl ty::Binder> { /// we convert the principal trait-ref into a normal trait-ref, /// you must give *some* self type. A common choice is `mk_err()` /// or some placeholder type. - pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> ty::Binder> { + pub fn with_self_ty(&self, cx: I, self_ty: Ty) -> ty::Binder> { self.map_bound(|trait_ref| trait_ref.with_self_ty(cx, self_ty)) } } @@ -459,7 +459,7 @@ impl ExistentialProjection { ExistentialTraitRef::new_from_args(interner, def_id.try_into().unwrap(), args) } - pub fn with_self_ty(&self, interner: I, self_ty: I::Ty) -> ProjectionPredicate { + pub fn with_self_ty(&self, interner: I, self_ty: Ty) -> ProjectionPredicate { // otherwise the escaping regions would be captured by the binders debug_assert!(!self_ty.has_escaping_bound_vars()); @@ -487,7 +487,7 @@ impl ExistentialProjection { } impl ty::Binder> { - pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> ty::Binder> { + pub fn with_self_ty(&self, cx: I, self_ty: Ty) -> ty::Binder> { self.map_bound(|p| p.with_self_ty(cx, self_ty)) } @@ -683,11 +683,11 @@ impl AliasTerm { /// The following methods work only with (trait) associated term projections. impl AliasTerm { - pub fn self_ty(self) -> I::Ty { + pub fn self_ty(self) -> Ty { self.args.type_at(0) } - pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self { + pub fn with_replaced_self_ty(self, interner: I, self_ty: Ty) -> Self { AliasTerm::new( interner, self.def_id, @@ -796,11 +796,11 @@ pub struct ProjectionPredicate { impl Eq for ProjectionPredicate {} impl ProjectionPredicate { - pub fn self_ty(self) -> I::Ty { + pub fn self_ty(self) -> Ty { self.projection_term.self_ty() } - pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> ProjectionPredicate { + pub fn with_replaced_self_ty(self, interner: I, self_ty: Ty) -> ProjectionPredicate { Self { projection_term: self.projection_term.with_replaced_self_ty(interner, self_ty), ..self @@ -859,11 +859,11 @@ pub struct NormalizesTo { impl Eq for NormalizesTo {} impl NormalizesTo { - pub fn self_ty(self) -> I::Ty { + pub fn self_ty(self) -> Ty { self.alias.self_ty() } - pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> NormalizesTo { + pub fn with_replaced_self_ty(self, interner: I, self_ty: Ty) -> NormalizesTo { Self { alias: self.alias.with_replaced_self_ty(interner, self_ty), ..self } } @@ -896,11 +896,11 @@ pub struct HostEffectPredicate { impl Eq for HostEffectPredicate {} impl HostEffectPredicate { - pub fn self_ty(self) -> I::Ty { + pub fn self_ty(self) -> Ty { self.trait_ref.self_ty() } - pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self { + pub fn with_replaced_self_ty(self, interner: I, self_ty: Ty) -> Self { Self { trait_ref: self.trait_ref.with_replaced_self_ty(interner, self_ty), ..self } } @@ -915,7 +915,7 @@ impl ty::Binder> { self.skip_binder().def_id() } - pub fn self_ty(self) -> ty::Binder { + pub fn self_ty(self) -> ty::Binder> { self.map_bound(|trait_ref| trait_ref.self_ty()) } @@ -936,8 +936,8 @@ impl ty::Binder> { )] pub struct SubtypePredicate { pub a_is_expected: bool, - pub a: I::Ty, - pub b: I::Ty, + pub a: Ty, + pub b: Ty, } impl Eq for SubtypePredicate {} @@ -950,8 +950,8 @@ impl Eq for SubtypePredicate {} derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) )] pub struct CoercePredicate { - pub a: I::Ty, - pub b: I::Ty, + pub a: Ty, + pub b: Ty, } impl Eq for CoercePredicate {} diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index 445e85a888fca..b6ff27fb238e6 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -5,7 +5,7 @@ use derive_where::derive_where; use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use rustc_type_ir_macros::{GenericTypeVisitable, TypeFoldable_Generic, TypeVisitable_Generic}; -use crate::{self as ty, Interner}; +use crate::{self as ty, Interner, Ty}; /// A clause is something that can appear in where bounds or be inferred /// by implied bounds. @@ -25,7 +25,7 @@ pub enum ClauseKind { RegionOutlives(ty::OutlivesPredicate), /// `where T: 'r` - TypeOutlives(ty::OutlivesPredicate), + TypeOutlives(ty::OutlivesPredicate>), /// `where ::Name == X`, approximately. /// See the `ProjectionPredicate` struct for details. @@ -33,7 +33,7 @@ pub enum ClauseKind { /// Ensures that a const generic argument to a parameter `const N: u8` /// is of type `u8`. - ConstArgHasType(I::Const, I::Ty), + ConstArgHasType(I::Const, Ty), /// No syntax: `T` well-formed. WellFormed(I::Term), diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 3610605462ba9..ce66c9065d697 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -7,13 +7,20 @@ use tracing::{instrument, trace}; use crate::error::{ExpectedFound, TypeError}; use crate::fold::TypeFoldable; use crate::inherent::*; -use crate::{self as ty, Interner}; +use crate::{self as ty, Interner, Ty}; pub mod combine; pub mod solver_relating; pub type RelateResult = Result>; +impl Relate for Ty { + #[inline] + fn relate>(relation: &mut R, a: Ty, b: Ty) -> RelateResult> { + relation.tys(a, b) + } +} + /// Whether aliases should be related structurally or not. Used /// to adjust the behavior of generalization and combine. /// @@ -44,7 +51,7 @@ pub enum VarianceDiagInfo { Invariant { /// The generic type containing the generic parameter /// that changes the variance (e.g. `*mut T`, `MyStruct`) - ty: I::Ty, + ty: Ty, /// The index of the generic parameter being used /// (e.g. `0` for `*mut T`, `1` for `MyStruct<'CovariantParam, 'InvariantParam>`) param_index: u32, @@ -75,13 +82,13 @@ pub trait TypeRelation: Sized { fn relate_ty_args( &mut self, - a_ty: I::Ty, - b_ty: I::Ty, + a_ty: Ty, + b_ty: Ty, ty_def_id: I::DefId, a_arg: I::GenericArgs, b_arg: I::GenericArgs, - mk: impl FnOnce(I::GenericArgs) -> I::Ty, - ) -> RelateResult; + mk: impl FnOnce(I::GenericArgs) -> Ty, + ) -> RelateResult>; /// Switch variance for the purpose of relating `a` and `b`. fn relate_with_variance>( @@ -98,7 +105,7 @@ pub trait TypeRelation: Sized { // additional hooks for other types in the future if needed // without making older code, which called `relate`, obsolete. - fn tys(&mut self, a: I::Ty, b: I::Ty) -> RelateResult; + fn tys(&mut self, a: Ty, b: Ty) -> RelateResult>; fn regions(&mut self, a: I::Region, b: I::Region) -> RelateResult; @@ -332,9 +339,9 @@ impl Relate for ty::ExistentialTraitRef { #[instrument(level = "trace", skip(relation), ret)] pub fn structurally_relate_tys>( relation: &mut R, - a: I::Ty, - b: I::Ty, -) -> RelateResult { + a: Ty, + b: Ty, +) -> RelateResult> { let cx = relation.cx(); match (a.kind(), b.kind()) { (ty::Infer(_), _) | (_, ty::Infer(_)) => { diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 64b87fac77f94..a5b94c07442e6 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -11,7 +11,7 @@ use crate::inherent::*; use crate::relate::VarianceDiagInfo; use crate::solve::Goal; use crate::visit::TypeVisitableExt as _; -use crate::{self as ty, InferCtxtLike, Interner, TypingMode, Upcast}; +use crate::{self as ty, InferCtxtLike, Interner, Ty, TypingMode, Upcast}; pub trait PredicateEmittingRelation::Interner>: TypeRelation @@ -39,15 +39,15 @@ where ); /// Register `AliasRelate` obligation(s) that both types must be related to each other. - fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty); + fn register_alias_relate_predicate(&mut self, a: Ty, b: Ty); } pub fn super_combine_tys( infcx: &Infcx, relation: &mut R, - a: I::Ty, - b: I::Ty, -) -> RelateResult + a: Ty, + b: Ty, +) -> RelateResult> where Infcx: InferCtxtLike, I: Interner, @@ -226,13 +226,13 @@ where pub fn combine_ty_args( infcx: &Infcx, relation: &mut R, - a_ty: I::Ty, - b_ty: I::Ty, + a_ty: Ty, + b_ty: Ty, variances: I::VariancesOf, a_args: I::GenericArgs, b_args: I::GenericArgs, - mk: impl FnOnce(I::GenericArgs) -> I::Ty, -) -> RelateResult + mk: impl FnOnce(I::GenericArgs) -> Ty, +) -> RelateResult> where Infcx: InferCtxtLike, I: Interner, diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index 82ee4f75fcb0a..1494d67d3c603 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -5,7 +5,7 @@ use crate::data_structures::DelayedSet; use crate::relate::combine::combine_ty_args; pub use crate::relate::*; use crate::solve::Goal; -use crate::{self as ty, InferCtxtLike, Interner}; +use crate::{self as ty, InferCtxtLike, Interner, Ty}; pub trait RelateExt: InferCtxtLike { fn relate>( @@ -104,7 +104,7 @@ pub struct SolverRelating<'infcx, Infcx, I: Interner> { /// constrain `?1` to `u32`. When using the cache entry from the /// first time we've related these types, this only happens when /// later proving the `Subtype(?0, ?1)` goal from the first relation. - cache: DelayedSet<(ty::Variance, I::Ty, I::Ty)>, + cache: DelayedSet<(ty::Variance, Ty, Ty)>, } impl<'infcx, Infcx, I> SolverRelating<'infcx, Infcx, I> @@ -142,13 +142,13 @@ where fn relate_ty_args( &mut self, - a_ty: I::Ty, - b_ty: I::Ty, + a_ty: Ty, + b_ty: Ty, def_id: I::DefId, a_args: I::GenericArgs, b_args: I::GenericArgs, - _: impl FnOnce(I::GenericArgs) -> I::Ty, - ) -> RelateResult { + _: impl FnOnce(I::GenericArgs) -> Ty, + ) -> RelateResult> { if self.ambient_variance == ty::Invariant { // Avoid fetching the variance if we are in an invariant // context; no need, and it can induce dependency cycles @@ -178,7 +178,7 @@ where } #[instrument(skip(self), level = "trace")] - fn tys(&mut self, a: I::Ty, b: I::Ty) -> RelateResult { + fn tys(&mut self, a: Ty, b: Ty) -> RelateResult> { if a == b { return Ok(a); } @@ -383,7 +383,7 @@ where self.goals.extend(obligations); } - fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty) { + fn register_alias_relate_predicate(&mut self, a: Ty, b: Ty) { self.register_predicates([ty::Binder::dummy(match self.ambient_variance { ty::Covariant => ty::PredicateKind::AliasRelate( a.into(), diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 72b7df22b30d5..23e6075452b18 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -11,7 +11,7 @@ use rustc_type_ir_macros::{ use crate::lang_items::SolverTraitLangItem; use crate::search_graph::PathKind; -use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Upcast}; +use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Ty, Upcast}; pub type CanonicalInput::Predicate> = ty::CanonicalQueryInput>; @@ -254,7 +254,7 @@ impl Eq for Response {} #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub struct ExternalConstraintsData { pub region_constraints: Vec>, - pub opaque_types: Vec<(ty::OpaqueTypeKey, I::Ty)>, + pub opaque_types: Vec<(ty::OpaqueTypeKey, Ty)>, pub normalization_nested_goals: NestedNormalizationGoals, } diff --git a/compiler/rustc_type_ir/src/ty_info.rs b/compiler/rustc_type_ir/src/ty_info.rs index 53994b5dbf637..4ad8b41d53ea9 100644 --- a/compiler/rustc_type_ir/src/ty_info.rs +++ b/compiler/rustc_type_ir/src/ty_info.rs @@ -17,7 +17,7 @@ use crate::{DebruijnIndex, TypeFlags}; /// StableHash::ZERO for the hash, in which case the hash gets computed each time. /// This is useful if you have values that you intern but never (can?) use for stable /// hashing. -#[derive(Copy, Clone, GenericTypeVisitable)] +#[derive(Copy, Clone, Debug, GenericTypeVisitable)] pub struct WithCachedTypeInfo { pub internee: T, diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 983d8f0820b6b..ef6074c1c492a 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -17,7 +17,7 @@ pub use self::closure::*; use crate::inherent::*; #[cfg(feature = "nightly")] use crate::visit::TypeVisitable; -use crate::{self as ty, BoundVarIndexKind, FloatTy, IntTy, Interner, UintTy}; +use crate::{self as ty, BoundVarIndexKind, FloatTy, IntTy, Interner, Ty, UintTy}; mod closure; @@ -100,7 +100,7 @@ pub enum TyKind { Str, /// An array with the given length. Written as `[T; N]`. - Array(I::Ty, I::Const), + Array(Ty, I::Const), /// A pattern newtype. /// @@ -109,17 +109,17 @@ pub enum TyKind { /// Only `Copy` and `Clone` will automatically get implemented for pattern types. /// Auto-traits treat this as if it were an aggregate with a single nested type. /// Only supports integer range patterns for now. - Pat(I::Ty, I::Pat), + Pat(Ty, I::Pat), /// The pointee of an array slice. Written as `[T]`. - Slice(I::Ty), + Slice(Ty), /// A raw pointer. Written as `*mut T` or `*const T` - RawPtr(I::Ty, Mutability), + RawPtr(Ty, Mutability), /// A reference; a pointer with an associated lifetime. Written as /// `&'a mut T` or `&'a T`. - Ref(I::Region, I::Ty, Mutability), + Ref(I::Region, Ty, Mutability), /// The anonymous type of a function declaration/definition. /// @@ -438,7 +438,7 @@ pub struct AliasTy { /// aka. `interner.parent(def_id)`. pub def_id: I::DefId, - /// This field exists to prevent the creation of `AliasTy` without using [`AliasTy::new_from_args`]. + /// This field exists to prevent the creation of `AliasTy` without using [`Alias>::new_from_args`]. #[derive_where(skip(Debug))] pub(crate) _use_alias_ty_new_instead: (), } @@ -469,18 +469,18 @@ impl AliasTy { matches!(self.kind(interner), AliasTyKind::Opaque) } - pub fn to_ty(self, interner: I) -> I::Ty { + pub fn to_ty(self, interner: I) -> Ty { Ty::new_alias(interner, self.kind(interner), self) } } /// The following methods work only with (trait) associated type projections. impl AliasTy { - pub fn self_ty(self) -> I::Ty { + pub fn self_ty(self) -> Ty { self.args.type_at(0) } - pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self { + pub fn with_replaced_self_ty(self, interner: I, self_ty: Ty) -> Self { AliasTy::new( interner, self.def_id, @@ -735,7 +735,7 @@ impl fmt::Debug for InferTy { )] #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)] pub struct TypeAndMut { - pub ty: I::Ty, + pub ty: Ty, pub mutbl: Mutability, } @@ -765,7 +765,7 @@ impl FnSig { self.inputs_and_output.inputs() } - pub fn output(self) -> I::Ty { + pub fn output(self) -> Ty { self.inputs_and_output.output() } @@ -783,7 +783,7 @@ impl ty::Binder> { #[inline] #[track_caller] - pub fn input(self, index: usize) -> ty::Binder { + pub fn input(self, index: usize) -> ty::Binder> { self.map_bound(|fn_sig| fn_sig.inputs().get(index).unwrap()) } @@ -792,7 +792,7 @@ impl ty::Binder> { } #[inline] - pub fn output(self) -> ty::Binder { + pub fn output(self) -> ty::Binder> { self.map_bound(|fn_sig| fn_sig.output()) } @@ -856,21 +856,21 @@ impl fmt::Debug for FnSig { } // FIXME: this is a distinct type because we need to define `Encode`/`Decode` -// impls in this crate for `Binder`. +// impls in this crate for `Binder>`. #[derive_where(Clone, Copy, PartialEq, Hash; I: Interner)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)] -pub struct UnsafeBinderInner(ty::Binder); +pub struct UnsafeBinderInner(ty::Binder>); impl Eq for UnsafeBinderInner {} -impl From> for UnsafeBinderInner { - fn from(value: ty::Binder) -> Self { +impl From>> for UnsafeBinderInner { + fn from(value: ty::Binder>) -> Self { UnsafeBinderInner(value) } } -impl From> for ty::Binder { +impl From> for ty::Binder> { fn from(value: UnsafeBinderInner) -> Self { value.0 } @@ -883,7 +883,7 @@ impl fmt::Debug for UnsafeBinderInner { } impl Deref for UnsafeBinderInner { - type Target = ty::Binder; + type Target = ty::Binder>; fn deref(&self) -> &Self::Target { &self.0 @@ -894,7 +894,7 @@ impl Deref for UnsafeBinderInner { impl rustc_serialize::Encodable for UnsafeBinderInner where - I::Ty: rustc_serialize::Encodable, + Ty: rustc_serialize::Encodable, I::BoundVarKinds: rustc_serialize::Encodable, { fn encode(&self, e: &mut E) { @@ -907,7 +907,7 @@ where impl rustc_serialize::Decodable for UnsafeBinderInner where - I::Ty: TypeVisitable + rustc_serialize::Decodable, + Ty: TypeVisitable + rustc_serialize::Decodable, I::BoundVarKinds: rustc_serialize::Decodable, { fn decode(decoder: &mut D) -> Self { @@ -937,7 +937,7 @@ impl FnSigTys { self.inputs_and_output.inputs() } - pub fn output(self) -> I::Ty { + pub fn output(self) -> Ty { self.inputs_and_output.output() } } @@ -960,7 +960,7 @@ impl ty::Binder> { #[inline] #[track_caller] - pub fn input(self, index: usize) -> ty::Binder { + pub fn input(self, index: usize) -> ty::Binder> { self.map_bound(|sig_tys| sig_tys.inputs().get(index).unwrap()) } @@ -969,7 +969,7 @@ impl ty::Binder> { } #[inline] - pub fn output(self) -> ty::Binder { + pub fn output(self) -> ty::Binder> { self.map_bound(|sig_tys| sig_tys.output()) } } diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index e8f94c8e7cc92..37981e5b683bd 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -9,7 +9,7 @@ use crate::data_structures::DelayedMap; use crate::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable, shift_region}; use crate::inherent::*; use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; -use crate::{self as ty, Interner}; +use crate::{self as ty, Interner, Ty}; /// A closure can be modeled as a struct that looks like: /// ```ignore (illustrative) @@ -121,13 +121,13 @@ pub struct ClosureArgsParts { /// This is the args of the typeck root. pub parent_args: I::GenericArgsSlice, /// Represents the maximum calling capability of the closure. - pub closure_kind_ty: I::Ty, + pub closure_kind_ty: Ty, /// Captures the closure's signature. This closure signature is "tupled", and /// thus has a peculiar signature of `extern "rust-call" fn((Args, ...)) -> Ty`. - pub closure_sig_as_fn_ptr_ty: I::Ty, + pub closure_sig_as_fn_ptr_ty: Ty, /// The upvars captured by the closure. Remains an inference variable /// until the upvar analysis, which happens late in HIR typeck. - pub tupled_upvars_ty: I::Ty, + pub tupled_upvars_ty: Ty, } impl ClosureArgs { @@ -169,14 +169,14 @@ impl ClosureArgs { /// Returns the tuple type representing the upvars for this closure. #[inline] - pub fn tupled_upvars_ty(self) -> I::Ty { + pub fn tupled_upvars_ty(self) -> Ty { self.split().tupled_upvars_ty } /// 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(args)`. - pub fn kind_ty(self) -> I::Ty { + pub fn kind_ty(self) -> Ty { self.split().closure_kind_ty } @@ -185,7 +185,7 @@ impl ClosureArgs { // FIXME(eddyb) this should be unnecessary, as the shallowly resolved // 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) -> I::Ty { + pub fn sig_as_fn_ptr_ty(self) -> Ty { self.split().closure_sig_as_fn_ptr_ty } @@ -223,7 +223,7 @@ pub struct CoroutineClosureArgsParts { /// This is the args of the typeck root. pub parent_args: I::GenericArgsSlice, /// Represents the maximum calling capability of the closure. - pub closure_kind_ty: I::Ty, + pub closure_kind_ty: Ty, /// Represents all of the relevant parts of the coroutine returned by this /// coroutine-closure. This signature parts type will have the general /// shape of `fn(tupled_inputs, resume_ty) -> (return_ty, yield_ty)`, where @@ -232,10 +232,10 @@ pub struct CoroutineClosureArgsParts { /// /// Use `coroutine_closure_sig` to break up this type rather than using it /// yourself. - pub signature_parts_ty: I::Ty, + pub signature_parts_ty: Ty, /// The upvars captured by the closure. Remains an inference variable /// until the upvar analysis, which happens late in HIR typeck. - pub tupled_upvars_ty: I::Ty, + pub tupled_upvars_ty: Ty, /// a function pointer that has the shape `for<'env> fn() -> (&'env T, ...)`. /// This allows us to represent the binder of the self-captures of the closure. /// @@ -243,7 +243,7 @@ pub struct CoroutineClosureArgsParts { /// from the closure's upvars, this will be `for<'env> fn() -> (&'env String,)`, /// while the `tupled_upvars_ty`, representing the by-move version of the same /// captures, will be `(String,)`. - pub coroutine_captures_by_ref_ty: I::Ty, + pub coroutine_captures_by_ref_ty: Ty, } impl CoroutineClosureArgs { @@ -277,11 +277,11 @@ impl CoroutineClosureArgs { } #[inline] - pub fn tupled_upvars_ty(self) -> I::Ty { + pub fn tupled_upvars_ty(self) -> Ty { self.split().tupled_upvars_ty } - pub fn kind_ty(self) -> I::Ty { + pub fn kind_ty(self) -> Ty { self.split().closure_kind_ty } @@ -289,7 +289,7 @@ impl CoroutineClosureArgs { self.kind_ty().to_opt_closure_kind().unwrap() } - pub fn signature_parts_ty(self) -> I::Ty { + pub fn signature_parts_ty(self) -> Ty { self.split().signature_parts_ty } @@ -314,7 +314,7 @@ impl CoroutineClosureArgs { }) } - pub fn coroutine_captures_by_ref_ty(self) -> I::Ty { + pub fn coroutine_captures_by_ref_ty(self) -> Ty { self.split().coroutine_captures_by_ref_ty } @@ -358,10 +358,10 @@ impl TypeVisitor for HasRegionsBoundAt { #[derive_where(Clone, Copy, PartialEq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)] pub struct CoroutineClosureSignature { - pub tupled_inputs_ty: I::Ty, - pub resume_ty: I::Ty, - pub yield_ty: I::Ty, - pub return_ty: I::Ty, + pub tupled_inputs_ty: Ty, + pub resume_ty: Ty, + pub yield_ty: Ty, + pub return_ty: Ty, // Like the `fn_sig_as_fn_ptr_ty` of a regular closure, these types // never actually differ. But we save them rather than recreating them @@ -393,10 +393,10 @@ impl CoroutineClosureSignature { self, cx: I, parent_args: I::GenericArgsSlice, - coroutine_kind_ty: I::Ty, + coroutine_kind_ty: Ty, coroutine_def_id: I::CoroutineId, - tupled_upvars_ty: I::Ty, - ) -> I::Ty { + tupled_upvars_ty: Ty, + ) -> Ty { let coroutine_args = ty::CoroutineArgs::new( cx, ty::CoroutineArgsParts { @@ -424,9 +424,9 @@ impl CoroutineClosureSignature { coroutine_def_id: I::CoroutineId, goal_kind: ty::ClosureKind, env_region: I::Region, - closure_tupled_upvars_ty: I::Ty, - coroutine_captures_by_ref_ty: I::Ty, - ) -> I::Ty { + closure_tupled_upvars_ty: Ty, + coroutine_captures_by_ref_ty: Ty, + ) -> Ty { let tupled_upvars_ty = Self::tupled_upvars_by_closure_kind( cx, goal_kind, @@ -457,11 +457,11 @@ impl CoroutineClosureSignature { pub fn tupled_upvars_by_closure_kind( cx: I, kind: ty::ClosureKind, - tupled_inputs_ty: I::Ty, - closure_tupled_upvars_ty: I::Ty, - coroutine_captures_by_ref_ty: I::Ty, + tupled_inputs_ty: Ty, + closure_tupled_upvars_ty: Ty, + coroutine_captures_by_ref_ty: Ty, env_region: I::Region, - ) -> I::Ty { + ) -> Ty { match kind { ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { let ty::FnPtr(sig_tys, _) = coroutine_captures_by_ref_ty.kind() else { @@ -503,7 +503,7 @@ struct FoldEscapingRegions { // Depends on `debruijn` because we may have types with regions of different // debruijn depths depending on the binders we've entered. - cache: DelayedMap<(ty::DebruijnIndex, I::Ty), I::Ty>, + cache: DelayedMap<(ty::DebruijnIndex, Ty), Ty>, } impl TypeFolder for FoldEscapingRegions { @@ -511,7 +511,7 @@ impl TypeFolder for FoldEscapingRegions { self.interner } - fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn fold_ty(&mut self, t: Ty) -> Ty { if !t.has_vars_bound_at_or_above(self.debruijn) { t } else if let Some(&t) = self.cache.get(&(self.debruijn, t)) { @@ -553,9 +553,9 @@ impl TypeFolder for FoldEscapingRegions { #[derive_where(Clone, Copy, PartialEq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)] pub struct GenSig { - pub resume_ty: I::Ty, - pub yield_ty: I::Ty, - pub return_ty: I::Ty, + pub resume_ty: Ty, + pub yield_ty: Ty, + pub return_ty: Ty, } impl Eq for GenSig {} @@ -581,15 +581,15 @@ pub struct CoroutineArgsParts { /// kind: `i8`/`i16`/`i32`. /// /// For regular coroutines, this field will always just be `()`. - pub kind_ty: I::Ty, + pub kind_ty: Ty, - pub resume_ty: I::Ty, - pub yield_ty: I::Ty, - pub return_ty: I::Ty, + pub resume_ty: Ty, + pub yield_ty: Ty, + pub return_ty: Ty, /// The upvars captured by the closure. Remains an inference variable /// until the upvar analysis, which happens late in HIR typeck. - pub tupled_upvars_ty: I::Ty, + pub tupled_upvars_ty: Ty, } impl CoroutineArgs { @@ -619,7 +619,7 @@ impl CoroutineArgs { } // Returns the kind of the coroutine. See docs on the `kind_ty` field. - pub fn kind_ty(self) -> I::Ty { + pub fn kind_ty(self) -> Ty { self.split().kind_ty } @@ -638,22 +638,22 @@ impl CoroutineArgs { /// Returns the tuple type representing the upvars for this coroutine. #[inline] - pub fn tupled_upvars_ty(self) -> I::Ty { + pub fn tupled_upvars_ty(self) -> Ty { self.split().tupled_upvars_ty } /// Returns the type representing the resume type of the coroutine. - pub fn resume_ty(self) -> I::Ty { + pub fn resume_ty(self) -> Ty { self.split().resume_ty } /// Returns the type representing the yield type of the coroutine. - pub fn yield_ty(self) -> I::Ty { + pub fn yield_ty(self) -> Ty { self.split().yield_ty } /// Returns the type representing the return type of the coroutine. - pub fn return_ty(self) -> I::Ty { + pub fn return_ty(self) -> Ty { self.split().return_ty } diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 6e62e1031a969..1ee4bff6b7a11 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -52,7 +52,7 @@ use smallvec::SmallVec; use thin_vec::ThinVec; use crate::inherent::*; -use crate::{self as ty, Interner, TypeFlags}; +use crate::{self as ty, Interner, Ty, TypeFlags}; /// This trait is implemented for every type that can be visited, /// providing the skeleton of the traversal. @@ -98,7 +98,7 @@ pub trait TypeVisitor: Sized { t.super_visit_with(self) } - fn visit_ty(&mut self, t: I::Ty) -> Self::Result { + fn visit_ty(&mut self, t: Ty) -> Self::Result { t.super_visit_with(self) } @@ -417,7 +417,7 @@ impl TypeVisitor for HasTypeFlagsVisitor { } #[inline] - fn visit_ty(&mut self, t: I::Ty) -> Self::Result { + fn visit_ty(&mut self, t: Ty) -> Self::Result { // Note: no `super_visit_with` call. let flags = t.flags(); if flags.intersects(self.flags) { @@ -522,7 +522,7 @@ impl TypeVisitor for HasEscapingVarsVisitor { } #[inline] - fn visit_ty(&mut self, t: I::Ty) -> Self::Result { + fn visit_ty(&mut self, t: Ty) -> Self::Result { // If the outer-exclusive-binder is *strictly greater* than // `outer_index`, that means that `t` contains some content // bound at `outer_index` or above (because diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs index 59cfd3fdc98c1..b6360f904992c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs @@ -231,7 +231,7 @@ fn contains_illegal_self_type_reference<'db, T: rustc_type_ir::TypeVisitable as rustc_type_ir::Interner>::Ty, + ty: rustc_type_ir::Ty>, ) -> Self::Result { let interner = DbInterner::new_no_crate(self.db); match ty.kind() { @@ -499,7 +499,7 @@ fn contains_illegal_impl_trait_in_trait<'db>( fn visit_ty( &mut self, - ty: as rustc_type_ir::Interner>::Ty, + ty: rustc_type_ir::Ty>, ) -> Self::Result { if let rustc_type_ir::TyKind::Alias(AliasTyKind::Opaque, op) = ty.kind() { let id = match op.def_id { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generic_arg.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generic_arg.rs index 72cf2f9f07f20..ad683d3385b3b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generic_arg.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generic_arg.rs @@ -638,7 +638,7 @@ impl<'db> rustc_type_ir::inherent::GenericArgs> for GenericArgs< } }) } - fn type_at(self, i: usize) -> as rustc_type_ir::Interner>::Ty { + fn type_at(self, i: usize) -> rustc_type_ir::Ty> { self.get(i) .and_then(|g| g.as_type()) .unwrap_or_else(|| Ty::new_error(DbInterner::conjure(), ErrorGuaranteed)) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs index e17bdac68cdd0..02e69ff0f15ee 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs @@ -769,6 +769,11 @@ impl<'db> inherent::AdtDef> for AdtDef { fn is_manually_drop(self) -> bool { self.inner().flags.is_manually_drop } + + fn has_unsafe_fields(self) -> bool { + // TODO: track field safety in next-solver adt metadata. + false + } } impl fmt::Debug for AdtDef { @@ -1300,6 +1305,22 @@ impl<'db> Interner for DbInterner<'db> { Tys::new_from_iter(self, args) } + fn mk_ty_from_kind(self, kind: TyKind<'db>) -> Ty<'db> { + Ty::new(self, kind) + } + + fn mk_coroutine_witness_for_coroutine( + self, + def_id: Self::CoroutineId, + args: Self::GenericArgs, + ) -> Ty<'db> { + Ty::new(self, TyKind::CoroutineWitness(def_id, args)) + } + + fn ty_discriminant_ty(self, _ty: Ty<'db>) -> Ty<'db> { + Ty::new_uint(self, UintTy::U8) + } + fn parent(self, def_id: Self::DefId) -> Self::DefId { use hir_def::Lookup; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs index 1173028a1092d..ce851a0eefac9 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs @@ -1179,7 +1179,7 @@ impl<'db> rustc_type_ir::inherent::Ty> for Ty<'db> { Ty::new(interner, TyKind::Slice(ty)) } - fn new_tup(interner: DbInterner<'db>, tys: &[ as Interner>::Ty]) -> Self { + fn new_tup(interner: DbInterner<'db>, tys: &[rustc_type_ir::Ty>]) -> Self { Ty::new(interner, TyKind::Tuple(Tys::new_from_slice(tys))) } @@ -1217,7 +1217,7 @@ impl<'db> rustc_type_ir::inherent::Ty> for Ty<'db> { fn new_unsafe_binder( interner: DbInterner<'db>, - ty: rustc_type_ir::Binder, as Interner>::Ty>, + ty: rustc_type_ir::Binder, rustc_type_ir::Ty>>, ) -> Self { Ty::new(interner, TyKind::UnsafeBinder(ty.into())) } @@ -1275,7 +1275,7 @@ impl<'db> rustc_type_ir::inherent::Ty> for Ty<'db> { false } - fn discriminant_ty(self, interner: DbInterner<'db>) -> as Interner>::Ty { + fn discriminant_ty(self, interner: DbInterner<'db>) -> rustc_type_ir::Ty> { match self.kind() { TyKind::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(interner), TyKind::Coroutine(_, args) => args.as_coroutine().discr_ty(interner), @@ -1346,7 +1346,7 @@ impl<'db> rustc_type_ir::inherent::Tys> for Tys<'db> { self.as_slice().split_last().unwrap().1 } - fn output(self) -> as Interner>::Ty { + fn output(self) -> rustc_type_ir::Ty> { *self.as_slice().split_last().unwrap().0 } }