Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/next_solver/ty.rs')
-rw-r--r--crates/hir-ty/src/next_solver/ty.rs339
1 files changed, 223 insertions, 116 deletions
diff --git a/crates/hir-ty/src/next_solver/ty.rs b/crates/hir-ty/src/next_solver/ty.rs
index b8406fecda..030ba37015 100644
--- a/crates/hir-ty/src/next_solver/ty.rs
+++ b/crates/hir-ty/src/next_solver/ty.rs
@@ -5,16 +5,17 @@ use std::ops::ControlFlow;
use hir_def::{
AdtId, HasModule, TypeParamId,
hir::generics::{TypeOrConstParamData, TypeParamProvenance},
- lang_item::LangItem,
};
use hir_def::{TraitId, type_ref::Rawness};
+use intern::{Interned, InternedRef, impl_internable};
+use macros::GenericTypeVisitable;
use rustc_abi::{Float, Integer, Size};
use rustc_ast_ir::{Mutability, try_visit, visit::VisitorResult};
use rustc_type_ir::{
AliasTyKind, BoundVar, BoundVarIndexKind, ClosureKind, CoroutineArgs, CoroutineArgsParts,
- DebruijnIndex, FlagComputation, Flags, FloatTy, FloatVid, InferTy, IntTy, IntVid, Interner,
- TyVid, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
- TypeVisitor, UintTy, Upcast, WithCachedTypeInfo,
+ DebruijnIndex, FlagComputation, Flags, FloatTy, FloatVid, GenericTypeVisitable, InferTy, IntTy,
+ IntVid, Interner, TyVid, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
+ TypeVisitableExt, TypeVisitor, UintTy, Upcast, WithCachedTypeInfo,
inherent::{
AdtDef as _, BoundExistentialPredicates, BoundVarLike, Const as _, GenericArgs as _,
IntoKind, ParamLike, PlaceholderLike, Safety as _, SliceLike, Ty as _,
@@ -25,54 +26,66 @@ use rustc_type_ir::{
};
use crate::{
- ImplTraitId,
+ FnAbi,
db::{HirDatabase, InternedCoroutine},
+ lower::GenericPredicates,
next_solver::{
AdtDef, AliasTy, Binder, CallableIdWrapper, Clause, ClauseKind, ClosureIdWrapper, Const,
- CoroutineIdWrapper, FnSig, GenericArg, PolyFnSig, Region, TraitRef, TypeAliasIdWrapper,
+ CoroutineIdWrapper, FnSig, GenericArgKind, PolyFnSig, Region, TraitRef, TypeAliasIdWrapper,
abi::Safety,
- interner::InternedWrapperNoDebug,
+ impl_foldable_for_interned_slice, impl_stored_interned, interned_slice,
util::{CoroutineArgsExt, IntegerTypeExt},
},
};
use super::{
- BoundVarKind, DbInterner, GenericArgs, Placeholder, SolverDefId, interned_vec_db,
+ BoundVarKind, DbInterner, GenericArgs, Placeholder, SolverDefId,
util::{FloatExt, IntegerExt},
};
+pub type SimplifiedType = rustc_type_ir::fast_reject::SimplifiedType<SolverDefId>;
pub type TyKind<'db> = rustc_type_ir::TyKind<DbInterner<'db>>;
pub type FnHeader<'db> = rustc_type_ir::FnHeader<DbInterner<'db>>;
-#[salsa::interned(constructor = new_)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct Ty<'db> {
- #[returns(ref)]
- kind_: InternedWrapperNoDebug<WithCachedTypeInfo<TyKind<'db>>>,
+ pub(super) interned: InternedRef<'db, TyInterned>,
}
+#[derive(PartialEq, Eq, Hash, GenericTypeVisitable)]
+#[repr(align(4))] // Required for `GenericArg` bit-tagging.
+pub(super) struct TyInterned(WithCachedTypeInfo<TyKind<'static>>);
+
+impl_internable!(gc; TyInterned);
+impl_stored_interned!(TyInterned, Ty, StoredTy);
+
const _: () = {
const fn is_copy<T: Copy>() {}
is_copy::<Ty<'static>>();
};
impl<'db> Ty<'db> {
- pub fn new(interner: DbInterner<'db>, kind: TyKind<'db>) -> Self {
+ #[inline]
+ pub fn new(_interner: DbInterner<'db>, kind: TyKind<'db>) -> Self {
+ let kind = unsafe { std::mem::transmute::<TyKind<'db>, TyKind<'static>>(kind) };
let flags = FlagComputation::for_kind(&kind);
let cached = WithCachedTypeInfo {
internee: kind,
flags: flags.flags,
outer_exclusive_binder: flags.outer_exclusive_binder,
};
- Ty::new_(interner.db(), InternedWrapperNoDebug(cached))
+ Self { interned: Interned::new_gc(TyInterned(cached)) }
}
+ #[inline]
pub fn inner(&self) -> &WithCachedTypeInfo<TyKind<'db>> {
- crate::with_attached_db(|db| {
- let inner = &self.kind_(db).0;
- // SAFETY: The caller already has access to a `Ty<'db>`, so borrowchecking will
- // make sure that our returned value is valid for the lifetime `'db`.
- unsafe { std::mem::transmute(inner) }
- })
+ let inner = &self.interned.0;
+ unsafe {
+ std::mem::transmute::<
+ &WithCachedTypeInfo<TyKind<'static>>,
+ &WithCachedTypeInfo<TyKind<'db>>,
+ >(inner)
+ }
}
pub fn new_adt(interner: DbInterner<'db>, adt_id: AdtId, args: GenericArgs<'db>) -> Self {
@@ -99,16 +112,39 @@ impl<'db> Ty<'db> {
Ty::new_infer(interner, InferTy::FloatVar(v))
}
+ #[inline]
pub fn new_int(interner: DbInterner<'db>, i: IntTy) -> Self {
- Ty::new(interner, TyKind::Int(i))
+ let types = interner.default_types();
+ match i {
+ IntTy::Isize => types.types.isize,
+ IntTy::I8 => types.types.i8,
+ IntTy::I16 => types.types.i16,
+ IntTy::I32 => types.types.i32,
+ IntTy::I64 => types.types.i64,
+ IntTy::I128 => types.types.i128,
+ }
}
pub fn new_uint(interner: DbInterner<'db>, ui: UintTy) -> Self {
- Ty::new(interner, TyKind::Uint(ui))
+ let types = interner.default_types();
+ match ui {
+ UintTy::Usize => types.types.usize,
+ UintTy::U8 => types.types.u8,
+ UintTy::U16 => types.types.u16,
+ UintTy::U32 => types.types.u32,
+ UintTy::U64 => types.types.u64,
+ UintTy::U128 => types.types.u128,
+ }
}
pub fn new_float(interner: DbInterner<'db>, f: FloatTy) -> Self {
- Ty::new(interner, TyKind::Float(f))
+ let types = interner.default_types();
+ match f {
+ FloatTy::F16 => types.types.f16,
+ FloatTy::F32 => types.types.f32,
+ FloatTy::F64 => types.types.f64,
+ FloatTy::F128 => types.types.f128,
+ }
}
pub fn new_fresh(interner: DbInterner<'db>, n: u32) -> Self {
@@ -124,7 +160,23 @@ impl<'db> Ty<'db> {
}
pub fn new_empty_tuple(interner: DbInterner<'db>) -> Self {
- Ty::new_tup(interner, &[])
+ interner.default_types().types.unit
+ }
+
+ pub fn new_imm_ptr(interner: DbInterner<'db>, ty: Ty<'db>) -> Self {
+ Ty::new_ptr(interner, ty, Mutability::Not)
+ }
+
+ pub fn new_imm_ref(interner: DbInterner<'db>, region: Region<'db>, ty: Ty<'db>) -> Self {
+ Ty::new_ref(interner, region, ty, Mutability::Not)
+ }
+
+ pub fn new_opaque(
+ interner: DbInterner<'db>,
+ def_id: SolverDefId,
+ args: GenericArgs<'db>,
+ ) -> Self {
+ Ty::new_alias(interner, AliasTyKind::Opaque, AliasTy::new_from_args(interner, def_id, args))
}
/// Returns the `Size` for primitive types (bool, uint, int, char, float).
@@ -327,18 +379,47 @@ impl<'db> Ty<'db> {
}
#[inline]
+ pub fn is_bool(self) -> bool {
+ matches!(self.kind(), TyKind::Bool)
+ }
+
+ /// 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(),
+ TyKind::Bool
+ | TyKind::Char
+ | TyKind::Int(_)
+ | TyKind::Float(_)
+ | TyKind::Uint(_)
+ | TyKind::FnDef(..)
+ | TyKind::FnPtr(..)
+ | TyKind::RawPtr(_, _)
+ | TyKind::Infer(InferTy::IntVar(_) | InferTy::FloatVar(_))
+ )
+ }
+
+ #[inline]
pub fn is_infer(self) -> bool {
matches!(self.kind(), TyKind::Infer(..))
}
#[inline]
+ pub fn is_numeric(self) -> bool {
+ self.is_integral() || self.is_floating_point()
+ }
+
+ #[inline]
pub fn is_str(self) -> bool {
matches!(self.kind(), TyKind::Str)
}
#[inline]
pub fn is_unit(self) -> bool {
- matches!(self.kind(), TyKind::Tuple(tys) if tys.inner().is_empty())
+ matches!(self.kind(), TyKind::Tuple(tys) if tys.is_empty())
}
#[inline]
@@ -346,10 +427,27 @@ impl<'db> Ty<'db> {
matches!(self.kind(), TyKind::RawPtr(..))
}
+ #[inline]
+ pub fn is_array(self) -> bool {
+ matches!(self.kind(), TyKind::Array(..))
+ }
+
+ #[inline]
+ pub fn is_slice(self) -> bool {
+ matches!(self.kind(), TyKind::Slice(..))
+ }
+
pub fn is_union(self) -> bool {
self.as_adt().is_some_and(|(adt, _)| matches!(adt, AdtId::UnionId(_)))
}
+ pub fn boxed_ty(self) -> Option<Ty<'db>> {
+ match self.kind() {
+ TyKind::Adt(adt_def, args) if adt_def.is_box() => Some(args.type_at(0)),
+ _ => None,
+ }
+ }
+
#[inline]
pub fn as_adt(self) -> Option<(AdtId, GenericArgs<'db>)> {
match self.kind() {
@@ -378,11 +476,9 @@ impl<'db> Ty<'db> {
///
/// 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, db: &dyn HirDatabase, explicit: bool) -> Option<Ty<'db>> {
+ pub fn builtin_deref(self, explicit: bool) -> Option<Ty<'db>> {
match self.kind() {
- TyKind::Adt(adt, substs) if crate::lang_items::is_box(db, adt.def_id().0) => {
- Some(substs.as_slice()[0].expect_ty())
- }
+ TyKind::Adt(adt, substs) if adt.is_box() => Some(substs.as_slice()[0].expect_ty()),
TyKind::Ref(_, ty, _) => Some(ty),
TyKind::RawPtr(ty, _) if explicit => Some(ty),
_ => None,
@@ -400,10 +496,9 @@ impl<'db> Ty<'db> {
Some(interner.fn_sig(callable).instantiate(interner, args))
}
TyKind::FnPtr(sig, hdr) => Some(sig.with(hdr)),
- TyKind::Closure(_, closure_args) => closure_args
- .split_closure_args_untupled()
- .closure_sig_as_fn_ptr_ty
- .callable_sig(interner),
+ TyKind::Closure(_, closure_args) => {
+ Some(interner.signature_unclosure(closure_args.as_closure().sig(), Safety::Safe))
+ }
TyKind::CoroutineClosure(coroutine_id, args) => {
Some(args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| {
let unit_ty = Ty::new_unit(interner);
@@ -495,34 +590,34 @@ impl<'db> Ty<'db> {
interner: DbInterner<'db>,
ty: hir_def::builtin_type::BuiltinType,
) -> Ty<'db> {
- let kind = match ty {
- hir_def::builtin_type::BuiltinType::Char => TyKind::Char,
- hir_def::builtin_type::BuiltinType::Bool => TyKind::Bool,
- hir_def::builtin_type::BuiltinType::Str => TyKind::Str,
- hir_def::builtin_type::BuiltinType::Int(int) => TyKind::Int(match int {
- hir_def::builtin_type::BuiltinInt::Isize => rustc_type_ir::IntTy::Isize,
- hir_def::builtin_type::BuiltinInt::I8 => rustc_type_ir::IntTy::I8,
- hir_def::builtin_type::BuiltinInt::I16 => rustc_type_ir::IntTy::I16,
- hir_def::builtin_type::BuiltinInt::I32 => rustc_type_ir::IntTy::I32,
- hir_def::builtin_type::BuiltinInt::I64 => rustc_type_ir::IntTy::I64,
- hir_def::builtin_type::BuiltinInt::I128 => rustc_type_ir::IntTy::I128,
- }),
- hir_def::builtin_type::BuiltinType::Uint(uint) => TyKind::Uint(match uint {
- hir_def::builtin_type::BuiltinUint::Usize => rustc_type_ir::UintTy::Usize,
- hir_def::builtin_type::BuiltinUint::U8 => rustc_type_ir::UintTy::U8,
- hir_def::builtin_type::BuiltinUint::U16 => rustc_type_ir::UintTy::U16,
- hir_def::builtin_type::BuiltinUint::U32 => rustc_type_ir::UintTy::U32,
- hir_def::builtin_type::BuiltinUint::U64 => rustc_type_ir::UintTy::U64,
- hir_def::builtin_type::BuiltinUint::U128 => rustc_type_ir::UintTy::U128,
- }),
- hir_def::builtin_type::BuiltinType::Float(float) => TyKind::Float(match float {
- hir_def::builtin_type::BuiltinFloat::F16 => rustc_type_ir::FloatTy::F16,
- hir_def::builtin_type::BuiltinFloat::F32 => rustc_type_ir::FloatTy::F32,
- hir_def::builtin_type::BuiltinFloat::F64 => rustc_type_ir::FloatTy::F64,
- hir_def::builtin_type::BuiltinFloat::F128 => rustc_type_ir::FloatTy::F128,
- }),
- };
- Ty::new(interner, kind)
+ let types = interner.default_types();
+ match ty {
+ hir_def::builtin_type::BuiltinType::Char => types.types.char,
+ hir_def::builtin_type::BuiltinType::Bool => types.types.bool,
+ hir_def::builtin_type::BuiltinType::Str => types.types.str,
+ hir_def::builtin_type::BuiltinType::Int(int) => match int {
+ hir_def::builtin_type::BuiltinInt::Isize => types.types.isize,
+ hir_def::builtin_type::BuiltinInt::I8 => types.types.i8,
+ hir_def::builtin_type::BuiltinInt::I16 => types.types.i16,
+ hir_def::builtin_type::BuiltinInt::I32 => types.types.i32,
+ hir_def::builtin_type::BuiltinInt::I64 => types.types.i64,
+ hir_def::builtin_type::BuiltinInt::I128 => types.types.i128,
+ },
+ hir_def::builtin_type::BuiltinType::Uint(uint) => match uint {
+ hir_def::builtin_type::BuiltinUint::Usize => types.types.usize,
+ hir_def::builtin_type::BuiltinUint::U8 => types.types.u8,
+ hir_def::builtin_type::BuiltinUint::U16 => types.types.u16,
+ hir_def::builtin_type::BuiltinUint::U32 => types.types.u32,
+ hir_def::builtin_type::BuiltinUint::U64 => types.types.u64,
+ hir_def::builtin_type::BuiltinUint::U128 => types.types.u128,
+ },
+ hir_def::builtin_type::BuiltinType::Float(float) => match float {
+ hir_def::builtin_type::BuiltinFloat::F16 => types.types.f16,
+ hir_def::builtin_type::BuiltinFloat::F32 => types.types.f32,
+ hir_def::builtin_type::BuiltinFloat::F64 => types.types.f64,
+ hir_def::builtin_type::BuiltinFloat::F128 => types.types.f128,
+ },
+ }
}
pub fn as_builtin(self) -> Option<hir_def::builtin_type::BuiltinType> {
@@ -559,29 +654,17 @@ impl<'db> Ty<'db> {
// FIXME: Should this be here?
pub fn impl_trait_bounds(self, db: &'db dyn HirDatabase) -> Option<Vec<Clause<'db>>> {
- let interner = DbInterner::new_with(db, None, None);
+ let interner = DbInterner::new_no_crate(db);
match self.kind() {
- TyKind::Alias(AliasTyKind::Opaque, opaque_ty) => {
- match db.lookup_intern_impl_trait_id(opaque_ty.def_id.expect_opaque_ty()) {
- ImplTraitId::ReturnTypeImplTrait(func, idx) => {
- db.return_type_impl_traits(func).map(|it| {
- let data =
- (*it).as_ref().map_bound(|rpit| &rpit.impl_traits[idx].predicates);
- data.iter_instantiated_copied(interner, opaque_ty.args.as_slice())
- .collect()
- })
- }
- ImplTraitId::TypeAliasImplTrait(alias, idx) => {
- db.type_alias_impl_traits(alias).map(|it| {
- let data =
- (*it).as_ref().map_bound(|rpit| &rpit.impl_traits[idx].predicates);
- data.iter_instantiated_copied(interner, opaque_ty.args.as_slice())
- .collect()
- })
- }
- }
- }
+ TyKind::Alias(AliasTyKind::Opaque, opaque_ty) => Some(
+ opaque_ty
+ .def_id
+ .expect_opaque_ty()
+ .predicates(db)
+ .iter_instantiated_copied(interner, opaque_ty.args.as_slice())
+ .collect(),
+ ),
TyKind::Param(param) => {
// FIXME: We shouldn't use `param.id` here.
let generic_params = db.generic_params(param.id.parent());
@@ -589,11 +672,8 @@ impl<'db> Ty<'db> {
match param_data {
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
TypeParamProvenance::ArgumentImplTrait => {
- let predicates = db
- .generic_predicates(param.id.parent())
- .instantiate_identity()
- .into_iter()
- .flatten()
+ let predicates = GenericPredicates::query_all(db, param.id.parent())
+ .iter_identity_copied()
.filter(|wc| match wc.kind().skip_binder() {
ClauseKind::Trait(tr) => tr.self_ty() == self,
ClauseKind::Projection(pred) => pred.self_ty() == self,
@@ -611,15 +691,15 @@ impl<'db> Ty<'db> {
}
TyKind::Coroutine(coroutine_id, _args) => {
let InternedCoroutine(owner, _) = coroutine_id.0.loc(db);
- let krate = owner.module(db).krate();
- if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) {
+ let krate = owner.module(db).krate(db);
+ if let Some(future_trait) = hir_def::lang_item::lang_items(db, krate).Future {
// This is only used by type walking.
// Parameters will be walked outside, and projection predicate is not used.
// So just provide the Future trait.
- let impl_bound = TraitRef::new(
+ let impl_bound = TraitRef::new_from_args(
interner,
future_trait.into(),
- GenericArgs::new_from_iter(interner, []),
+ GenericArgs::empty(interner),
)
.upcast(interner);
Some(vec![impl_bound])
@@ -685,20 +765,23 @@ impl<'db> std::fmt::Debug for Ty<'db> {
}
}
-impl<'db> std::fmt::Debug for InternedWrapperNoDebug<WithCachedTypeInfo<TyKind<'db>>> {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- self.0.internee.fmt(f)
- }
-}
-
impl<'db> IntoKind for Ty<'db> {
type Kind = TyKind<'db>;
+ #[inline]
fn kind(self) -> Self::Kind {
self.inner().internee
}
}
+impl<'db, V: super::WorldExposer> GenericTypeVisitable<V> for Ty<'db> {
+ fn generic_visit_with(&self, visitor: &mut V) {
+ if visitor.on_interned(self.interned).is_continue() {
+ self.kind().generic_visit_with(visitor);
+ }
+ }
+}
+
impl<'db> TypeVisitable<DbInterner<'db>> for Ty<'db> {
fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
&self,
@@ -897,19 +980,19 @@ impl<'db> Flags for Ty<'db> {
impl<'db> rustc_type_ir::inherent::Ty<DbInterner<'db>> for Ty<'db> {
fn new_unit(interner: DbInterner<'db>) -> Self {
- Ty::new(interner, TyKind::Tuple(Default::default()))
+ interner.default_types().types.unit
}
fn new_bool(interner: DbInterner<'db>) -> Self {
- Ty::new(interner, TyKind::Bool)
+ interner.default_types().types.bool
}
fn new_u8(interner: DbInterner<'db>) -> Self {
- Ty::new(interner, TyKind::Uint(rustc_type_ir::UintTy::U8))
+ interner.default_types().types.u8
}
fn new_usize(interner: DbInterner<'db>) -> Self {
- Ty::new(interner, TyKind::Uint(rustc_type_ir::UintTy::Usize))
+ interner.default_types().types.usize
}
fn new_infer(interner: DbInterner<'db>, var: rustc_type_ir::InferTy) -> Self {
@@ -1023,9 +1106,9 @@ impl<'db> rustc_type_ir::inherent::Ty<DbInterner<'db>> for Ty<'db> {
// to unnecessary overflows in async code. See the issue:
// <https://github.com/rust-lang/rust/issues/145151>.
let coroutine_args = interner.mk_args_from_iter(coroutine_args.iter().map(|arg| {
- match arg {
- GenericArg::Ty(_) | GenericArg::Const(_) => arg,
- GenericArg::Lifetime(_) => {
+ match arg.kind() {
+ GenericArgKind::Type(_) | GenericArgKind::Const(_) => arg,
+ GenericArgKind::Lifetime(_) => {
crate::next_solver::Region::new(interner, rustc_type_ir::RegionKind::ReErased)
.into()
}
@@ -1060,7 +1143,7 @@ impl<'db> rustc_type_ir::inherent::Ty<DbInterner<'db>> for Ty<'db> {
}
fn new_tup(interner: DbInterner<'db>, tys: &[<DbInterner<'db> as Interner>::Ty]) -> Self {
- Ty::new(interner, TyKind::Tuple(Tys::new_from_iter(interner, tys.iter().cloned())))
+ Ty::new(interner, TyKind::Tuple(Tys::new_from_slice(tys)))
}
fn new_tup_from_iter<It, T>(interner: DbInterner<'db>, iter: It) -> T::Output
@@ -1132,10 +1215,11 @@ impl<'db> rustc_type_ir::inherent::Ty<DbInterner<'db>> for Ty<'db> {
}
fn from_closure_kind(interner: DbInterner<'db>, kind: rustc_type_ir::ClosureKind) -> Self {
+ let types = interner.default_types();
match kind {
- ClosureKind::Fn => Ty::new(interner, TyKind::Int(IntTy::I8)),
- ClosureKind::FnMut => Ty::new(interner, TyKind::Int(IntTy::I16)),
- ClosureKind::FnOnce => Ty::new(interner, TyKind::Int(IntTy::I32)),
+ ClosureKind::Fn => types.types.i8,
+ ClosureKind::FnMut => types.types.i16,
+ ClosureKind::FnOnce => types.types.i32,
}
}
@@ -1143,9 +1227,10 @@ impl<'db> rustc_type_ir::inherent::Ty<DbInterner<'db>> for Ty<'db> {
interner: DbInterner<'db>,
kind: rustc_type_ir::ClosureKind,
) -> Self {
+ let types = interner.default_types();
match kind {
- ClosureKind::Fn | ClosureKind::FnMut => Ty::new(interner, TyKind::Int(IntTy::I16)),
- ClosureKind::FnOnce => Ty::new(interner, TyKind::Int(IntTy::I32)),
+ ClosureKind::Fn | ClosureKind::FnMut => types.types.i16,
+ ClosureKind::FnOnce => types.types.i32,
}
}
@@ -1192,7 +1277,7 @@ impl<'db> rustc_type_ir::inherent::Ty<DbInterner<'db>> for Ty<'db> {
| TyKind::Tuple(_)
| TyKind::Error(_)
| TyKind::Infer(InferTy::IntVar(_) | InferTy::FloatVar(_)) => {
- Ty::new(interner, TyKind::Uint(UintTy::U8))
+ interner.default_types().types.u8
}
TyKind::Bound(..)
@@ -1209,20 +1294,19 @@ impl<'db> rustc_type_ir::inherent::Ty<DbInterner<'db>> for Ty<'db> {
}
}
-interned_vec_db!(Tys, Ty);
+interned_slice!(TysStorage, Tys, StoredTys, tys, Ty<'db>, Ty<'static>);
+impl_foldable_for_interned_slice!(Tys);
impl<'db> Tys<'db> {
- pub fn inputs(&self) -> &[Ty<'db>] {
+ #[inline]
+ pub fn inputs(self) -> &'db [Ty<'db>] {
self.as_slice().split_last().unwrap().1
}
}
impl<'db> rustc_type_ir::inherent::Tys<DbInterner<'db>> for Tys<'db> {
fn inputs(self) -> <DbInterner<'db> as Interner>::FnInputTys {
- Tys::new_from_iter(
- DbInterner::conjure(),
- self.as_slice().split_last().unwrap().1.iter().copied(),
- )
+ self.as_slice().split_last().unwrap().1
}
fn output(self) -> <DbInterner<'db> as Interner>::Ty {
@@ -1278,6 +1362,10 @@ pub enum BoundTyKind {
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct ErrorGuaranteed;
+impl<V> GenericTypeVisitable<V> for ErrorGuaranteed {
+ fn generic_visit_with(&self, _visitor: &mut V) {}
+}
+
impl<'db> TypeVisitable<DbInterner<'db>> for ErrorGuaranteed {
fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
&self,
@@ -1338,3 +1426,22 @@ impl<'db> PlaceholderLike<DbInterner<'db>> for PlaceholderTy {
Placeholder { universe: ui, bound: BoundTy { var, kind: BoundTyKind::Anon } }
}
}
+
+impl<'db> DbInterner<'db> {
+ /// Given a closure signature, returns an equivalent fn signature. Detuples
+ /// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then
+ /// you would get a `fn(u32, i32)`.
+ /// `unsafety` determines the unsafety of the fn signature. If you pass
+ /// `Safety::Unsafe` in the previous example, then you would get
+ /// an `unsafe fn (u32, i32)`.
+ /// It cannot convert a closure that requires unsafe.
+ pub fn signature_unclosure(self, sig: PolyFnSig<'db>, safety: Safety) -> PolyFnSig<'db> {
+ sig.map_bound(|s| {
+ let params = match s.inputs()[0].kind() {
+ TyKind::Tuple(params) => params,
+ _ => panic!(),
+ };
+ self.mk_fn_sig(params, s.output(), s.c_variadic, safety, FnAbi::Rust)
+ })
+ }
+}