diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index cfe9cedb0de..b4801cb2158 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -3,9 +3,9 @@
 use std::{borrow::Cow, fmt};
 
 use crate::{
-    db::HirDatabase, utils::generics, ApplicationTy, CallableDefId, FnSig, GenericPredicate,
-    Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs, TraitRef, Ty,
-    TypeCtor,
+    db::HirDatabase, primitive, utils::generics, ApplicationTy, CallableDefId, FnSig,
+    GenericPredicate, Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs,
+    TraitRef, Ty, TypeCtor,
 };
 use arrayvec::ArrayVec;
 use hir_def::{
@@ -244,9 +244,11 @@ impl HirDisplay for ApplicationTy {
         match self.ctor {
             TypeCtor::Scalar(Scalar::Bool) => write!(f, "bool")?,
             TypeCtor::Scalar(Scalar::Char) => write!(f, "char")?,
-            TypeCtor::Scalar(Scalar::Float(t)) => write!(f, "{}", t)?,
-            TypeCtor::Scalar(Scalar::Int(t)) => write!(f, "{}", t)?,
-            TypeCtor::Scalar(Scalar::Uint(t)) => write!(f, "{}", t)?,
+            TypeCtor::Scalar(Scalar::Float(t)) => {
+                write!(f, "{}", primitive::float_ty_to_string(t))?
+            }
+            TypeCtor::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
+            TypeCtor::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
             TypeCtor::Str => write!(f, "str")?,
             TypeCtor::Slice => {
                 let t = self.parameters.as_single();
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index c25f3f34b29..3fec0e43184 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -15,7 +15,7 @@ use test_utils::mark;
 
 use crate::{
     autoderef, method_resolution, op,
-    primitive::UintTy,
+    primitive::{self, UintTy},
     traits::{FnTrait, InEnvironment},
     utils::{generics, variant_data, Generics},
     ApplicationTy, Binders, CallableDefId, InferTy, Mutability, Obligation, OpaqueTyId, Rawness,
@@ -730,17 +730,21 @@ impl<'a> InferenceContext<'a> {
                 }
                 Literal::Char(..) => Ty::simple(TypeCtor::Scalar(Scalar::Char)),
                 Literal::Int(_v, ty) => match ty {
-                    Some(int_ty) => Ty::simple(TypeCtor::Scalar(Scalar::Int((*int_ty).into()))),
+                    Some(int_ty) => Ty::simple(TypeCtor::Scalar(Scalar::Int(
+                        primitive::int_ty_from_builtin(*int_ty),
+                    ))),
                     None => self.table.new_integer_var(),
                 },
                 Literal::Uint(_v, ty) => match ty {
-                    Some(int_ty) => Ty::simple(TypeCtor::Scalar(Scalar::Uint((*int_ty).into()))),
+                    Some(int_ty) => Ty::simple(TypeCtor::Scalar(Scalar::Uint(
+                        primitive::uint_ty_from_builtin(*int_ty),
+                    ))),
                     None => self.table.new_integer_var(),
                 },
                 Literal::Float(_v, ty) => match ty {
-                    Some(float_ty) => {
-                        Ty::simple(TypeCtor::Scalar(Scalar::Float((*float_ty).into())))
-                    }
+                    Some(float_ty) => Ty::simple(TypeCtor::Scalar(Scalar::Float(
+                        primitive::float_ty_from_builtin(*float_ty),
+                    ))),
                     None => self.table.new_float_var(),
                 },
             },
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 2a45479a8e7..676519594b4 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -38,7 +38,6 @@ use itertools::Itertools;
 use crate::{
     db::HirDatabase,
     display::HirDisplay,
-    primitive::{FloatTy, IntTy, UintTy},
     utils::{generics, make_mut_slice, Generics},
 };
 
@@ -50,7 +49,7 @@ pub use lower::{
 };
 pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
 
-pub use chalk_ir::{BoundVar, DebruijnIndex};
+pub use chalk_ir::{BoundVar, DebruijnIndex, Scalar};
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub enum Lifetime {
@@ -58,17 +57,6 @@ pub enum Lifetime {
     Static,
 }
 
-/// Types of scalar values.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[allow(missing_docs)]
-pub enum Scalar {
-    Bool,
-    Char,
-    Int(IntTy),
-    Uint(UintTy),
-    Float(FloatTy),
-}
-
 /// A type constructor or type name: this might be something like the primitive
 /// type `bool`, a struct like `Vec`, or things like function pointers or
 /// tuples.
@@ -736,9 +724,13 @@ impl Ty {
             BuiltinType::Char => TypeCtor::Scalar(Scalar::Char),
             BuiltinType::Bool => TypeCtor::Scalar(Scalar::Bool),
             BuiltinType::Str => TypeCtor::Str,
-            BuiltinType::Int(t) => TypeCtor::Scalar(Scalar::Int(t.into())),
-            BuiltinType::Uint(t) => TypeCtor::Scalar(Scalar::Uint(t.into())),
-            BuiltinType::Float(t) => TypeCtor::Scalar(Scalar::Float(t.into())),
+            BuiltinType::Int(t) => TypeCtor::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))),
+            BuiltinType::Uint(t) => {
+                TypeCtor::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t)))
+            }
+            BuiltinType::Float(t) => {
+                TypeCtor::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t)))
+            }
         })
     }
 
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 3c817701d4e..66d8de95917 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -16,7 +16,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
 use crate::{
     autoderef,
     db::HirDatabase,
-    primitive::{FloatTy, IntTy, UintTy},
+    primitive::{self, FloatTy, IntTy, UintTy},
     utils::all_super_traits,
     ApplicationTy, Canonical, DebruijnIndex, InEnvironment, Scalar, Substs, TraitEnvironment,
     TraitRef, Ty, TyKind, TypeCtor, TypeWalk,
@@ -225,8 +225,12 @@ impl Ty {
                     FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"),
                     FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"),
                 },
-                TypeCtor::Scalar(Scalar::Int(t)) => lang_item_crate!(t.ty_to_string()),
-                TypeCtor::Scalar(Scalar::Uint(t)) => lang_item_crate!(t.ty_to_string()),
+                TypeCtor::Scalar(Scalar::Int(t)) => {
+                    lang_item_crate!(primitive::int_ty_to_string(t))
+                }
+                TypeCtor::Scalar(Scalar::Uint(t)) => {
+                    lang_item_crate!(primitive::uint_ty_to_string(t))
+                }
                 TypeCtor::Str => lang_item_crate!("str_alloc", "str"),
                 TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"),
                 TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"),
diff --git a/crates/hir_ty/src/primitive.rs b/crates/hir_ty/src/primitive.rs
index e727c9581cb..2449addfb75 100644
--- a/crates/hir_ty/src/primitive.rs
+++ b/crates/hir_ty/src/primitive.rs
@@ -3,128 +3,63 @@
 //! * during type inference, they can be uncertain (ie, `let x = 92;`)
 //! * they don't belong to any particular crate.
 
-use std::fmt;
-
+pub use chalk_ir::{FloatTy, IntTy, UintTy};
 pub use hir_def::builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint};
 
-/// Different signed int types.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum IntTy {
-    Isize,
-    I8,
-    I16,
-    I32,
-    I64,
-    I128,
-}
-
-/// Different unsigned int types.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum UintTy {
-    Usize,
-    U8,
-    U16,
-    U32,
-    U64,
-    U128,
-}
-
-impl fmt::Display for IntTy {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.ty_to_string())
+pub fn int_ty_to_string(ty: IntTy) -> &'static str {
+    match ty {
+        IntTy::Isize => "isize",
+        IntTy::I8 => "i8",
+        IntTy::I16 => "i16",
+        IntTy::I32 => "i32",
+        IntTy::I64 => "i64",
+        IntTy::I128 => "i128",
     }
 }
 
-impl IntTy {
-    pub fn ty_to_string(self) -> &'static str {
-        match self {
-            IntTy::Isize => "isize",
-            IntTy::I8 => "i8",
-            IntTy::I16 => "i16",
-            IntTy::I32 => "i32",
-            IntTy::I64 => "i64",
-            IntTy::I128 => "i128",
-        }
+pub fn uint_ty_to_string(ty: UintTy) -> &'static str {
+    match ty {
+        UintTy::Usize => "usize",
+        UintTy::U8 => "u8",
+        UintTy::U16 => "u16",
+        UintTy::U32 => "u32",
+        UintTy::U64 => "u64",
+        UintTy::U128 => "u128",
     }
 }
 
-impl fmt::Display for UintTy {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.ty_to_string())
+pub fn float_ty_to_string(ty: FloatTy) -> &'static str {
+    match ty {
+        FloatTy::F32 => "f32",
+        FloatTy::F64 => "f64",
     }
 }
 
-impl UintTy {
-    pub fn ty_to_string(self) -> &'static str {
-        match self {
-            UintTy::Usize => "usize",
-            UintTy::U8 => "u8",
-            UintTy::U16 => "u16",
-            UintTy::U32 => "u32",
-            UintTy::U64 => "u64",
-            UintTy::U128 => "u128",
-        }
+pub(super) fn int_ty_from_builtin(t: BuiltinInt) -> IntTy {
+    match t {
+        BuiltinInt::Isize => IntTy::Isize,
+        BuiltinInt::I8 => IntTy::I8,
+        BuiltinInt::I16 => IntTy::I16,
+        BuiltinInt::I32 => IntTy::I32,
+        BuiltinInt::I64 => IntTy::I64,
+        BuiltinInt::I128 => IntTy::I128,
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum FloatTy {
-    F32,
-    F64,
-}
-
-impl fmt::Debug for FloatTy {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(self, f)
+pub(super) fn uint_ty_from_builtin(t: BuiltinUint) -> UintTy {
+    match t {
+        BuiltinUint::Usize => UintTy::Usize,
+        BuiltinUint::U8 => UintTy::U8,
+        BuiltinUint::U16 => UintTy::U16,
+        BuiltinUint::U32 => UintTy::U32,
+        BuiltinUint::U64 => UintTy::U64,
+        BuiltinUint::U128 => UintTy::U128,
     }
 }
 
-impl fmt::Display for FloatTy {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.ty_to_string())
-    }
-}
-
-impl FloatTy {
-    pub fn ty_to_string(self) -> &'static str {
-        match self {
-            FloatTy::F32 => "f32",
-            FloatTy::F64 => "f64",
-        }
-    }
-}
-
-impl From<BuiltinInt> for IntTy {
-    fn from(t: BuiltinInt) -> Self {
-        match t {
-            BuiltinInt::Isize => Self::Isize,
-            BuiltinInt::I8 => Self::I8,
-            BuiltinInt::I16 => Self::I16,
-            BuiltinInt::I32 => Self::I32,
-            BuiltinInt::I64 => Self::I64,
-            BuiltinInt::I128 => Self::I128,
-        }
-    }
-}
-
-impl From<BuiltinUint> for UintTy {
-    fn from(t: BuiltinUint) -> Self {
-        match t {
-            BuiltinUint::Usize => Self::Usize,
-            BuiltinUint::U8 => Self::U8,
-            BuiltinUint::U16 => Self::U16,
-            BuiltinUint::U32 => Self::U32,
-            BuiltinUint::U64 => Self::U64,
-            BuiltinUint::U128 => Self::U128,
-        }
-    }
-}
-
-impl From<BuiltinFloat> for FloatTy {
-    fn from(t: BuiltinFloat) -> Self {
-        match t {
-            BuiltinFloat::F32 => Self::F32,
-            BuiltinFloat::F64 => Self::F64,
-        }
+pub(super) fn float_ty_from_builtin(t: BuiltinFloat) -> FloatTy {
+    match t {
+        BuiltinFloat::F32 => FloatTy::F32,
+        BuiltinFloat::F64 => FloatTy::F64,
     }
 }
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index 0e9fc326529..5a3cb790600 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -14,7 +14,7 @@ use hir_def::{type_ref::Mutability, AssocContainerId, GenericDefId, Lookup, Type
 
 use crate::{
     db::HirDatabase,
-    primitive::{FloatTy, IntTy, UintTy},
+    primitive::UintTy,
     traits::{Canonical, Obligation},
     ApplicationTy, CallableDefId, GenericPredicate, InEnvironment, OpaqueTy, OpaqueTyId,
     ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, TraitRef, Ty, TyKind,
@@ -64,31 +64,7 @@ impl ToChalk for Ty {
                     chalk_ir::TyKind::Foreign(foreign_type_id).intern(&Interner)
                 }
 
-                TypeCtor::Scalar(scalar) => chalk_ir::TyKind::Scalar(match scalar {
-                    Scalar::Bool => chalk_ir::Scalar::Bool,
-                    Scalar::Char => chalk_ir::Scalar::Char,
-                    Scalar::Int(it) => chalk_ir::Scalar::Int(match it {
-                        IntTy::Isize => chalk_ir::IntTy::Isize,
-                        IntTy::I8 => chalk_ir::IntTy::I8,
-                        IntTy::I16 => chalk_ir::IntTy::I16,
-                        IntTy::I32 => chalk_ir::IntTy::I32,
-                        IntTy::I64 => chalk_ir::IntTy::I64,
-                        IntTy::I128 => chalk_ir::IntTy::I128,
-                    }),
-                    Scalar::Uint(it) => chalk_ir::Scalar::Uint(match it {
-                        UintTy::Usize => chalk_ir::UintTy::Usize,
-                        UintTy::U8 => chalk_ir::UintTy::U8,
-                        UintTy::U16 => chalk_ir::UintTy::U16,
-                        UintTy::U32 => chalk_ir::UintTy::U32,
-                        UintTy::U64 => chalk_ir::UintTy::U64,
-                        UintTy::U128 => chalk_ir::UintTy::U128,
-                    }),
-                    Scalar::Float(it) => chalk_ir::Scalar::Float(match it {
-                        FloatTy::F32 => chalk_ir::FloatTy::F32,
-                        FloatTy::F64 => chalk_ir::FloatTy::F64,
-                    }),
-                })
-                .intern(&Interner),
+                TypeCtor::Scalar(scalar) => chalk_ir::TyKind::Scalar(scalar).intern(&Interner),
 
                 TypeCtor::Tuple { cardinality } => {
                     let substitution = apply_ty.parameters.to_chalk(db);
@@ -232,38 +208,7 @@ impl ToChalk for Ty {
                 apply_ty_from_chalk(db, TypeCtor::OpaqueType(from_chalk(db, opaque_type_id)), subst)
             }
 
-            chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Bool) => {
-                Ty::simple(TypeCtor::Scalar(Scalar::Bool))
-            }
-            chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Char) => {
-                Ty::simple(TypeCtor::Scalar(Scalar::Char))
-            }
-            chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Int(int_ty)) => {
-                Ty::simple(TypeCtor::Scalar(Scalar::Int(match int_ty {
-                    chalk_ir::IntTy::Isize => IntTy::Isize,
-                    chalk_ir::IntTy::I8 => IntTy::I8,
-                    chalk_ir::IntTy::I16 => IntTy::I16,
-                    chalk_ir::IntTy::I32 => IntTy::I32,
-                    chalk_ir::IntTy::I64 => IntTy::I64,
-                    chalk_ir::IntTy::I128 => IntTy::I128,
-                })))
-            }
-            chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(int_ty)) => {
-                Ty::simple(TypeCtor::Scalar(Scalar::Uint(match int_ty {
-                    chalk_ir::UintTy::Usize => UintTy::Usize,
-                    chalk_ir::UintTy::U8 => UintTy::U8,
-                    chalk_ir::UintTy::U16 => UintTy::U16,
-                    chalk_ir::UintTy::U32 => UintTy::U32,
-                    chalk_ir::UintTy::U64 => UintTy::U64,
-                    chalk_ir::UintTy::U128 => UintTy::U128,
-                })))
-            }
-            chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Float(float_ty)) => {
-                Ty::simple(TypeCtor::Scalar(Scalar::Float(match float_ty {
-                    chalk_ir::FloatTy::F32 => FloatTy::F32,
-                    chalk_ir::FloatTy::F64 => FloatTy::F64,
-                })))
-            }
+            chalk_ir::TyKind::Scalar(scalar) => Ty::simple(TypeCtor::Scalar(scalar)),
             chalk_ir::TyKind::Tuple(cardinality, subst) => {
                 apply_ty_from_chalk(db, TypeCtor::Tuple { cardinality: cardinality as u16 }, subst)
             }
@@ -321,8 +266,7 @@ fn ref_to_chalk(
 /// fake constant here, because Chalks built-in logic may expect it to be there.
 fn array_to_chalk(db: &dyn HirDatabase, subst: Substs) -> chalk_ir::Ty<Interner> {
     let arg = subst[0].clone().to_chalk(db);
-    let usize_ty =
-        chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize)).intern(&Interner);
+    let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
     let const_ = chalk_ir::ConstData {
         ty: usize_ty,
         value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }),