From 70dd70b1fcbbbe2e60849412412ef05e7d31eb0a Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Wed, 13 Nov 2019 09:56:33 +0300
Subject: [PATCH] Reduce duplication between uncertain floats & ints

---
 crates/ra_hir/src/lib.rs                  |  4 +--
 crates/ra_hir/src/ty.rs                   |  6 ++---
 crates/ra_hir/src/ty/infer.rs             | 28 ++++++++------------
 crates/ra_hir/src/ty/infer/expr.rs        | 30 ++++++++++-----------
 crates/ra_hir/src/ty/lower.rs             | 14 +++++-----
 crates/ra_hir/src/ty/method_resolution.rs | 11 ++++----
 crates/ra_hir/src/ty/primitive.rs         | 32 +++++++++--------------
 7 files changed, 55 insertions(+), 70 deletions(-)

diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 92d71b9e88f..5ba847d3515 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -77,9 +77,7 @@ pub use crate::{
     source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
     ty::{
         display::HirDisplay,
-        primitive::{
-            FloatBitness, FloatTy, IntBitness, IntTy, Signedness, UncertainFloatTy, UncertainIntTy,
-        },
+        primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain},
         ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
     },
 };
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 6f24cfad602..ff6030ac426 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -21,7 +21,7 @@ use crate::{
     expr::ExprId,
     generics::{GenericParams, HasGenericParams},
     util::make_mut_slice,
-    Adt, Crate, DefWithBody, Mutability, Name, Trait, TypeAlias,
+    Adt, Crate, DefWithBody, FloatTy, IntTy, Mutability, Name, Trait, TypeAlias, Uncertain,
 };
 use display::{HirDisplay, HirFormatter};
 
@@ -47,10 +47,10 @@ pub enum TypeCtor {
     Char,
 
     /// A primitive integer type. For example, `i32`.
-    Int(primitive::UncertainIntTy),
+    Int(Uncertain<IntTy>),
 
     /// A primitive floating-point type. For example, `f64`.
-    Float(primitive::UncertainFloatTy),
+    Float(Uncertain<FloatTy>),
 
     /// Structures, enumerations and unions.
     Adt(Adt),
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index f17c6c61433..c092608642d 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -31,10 +31,10 @@ use ra_prof::profile;
 use test_utils::tested_by;
 
 use super::{
-    lower, primitive,
+    lower,
     traits::{Guidance, Obligation, ProjectionPredicate, Solution},
     ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypableDef,
-    TypeCtor, TypeWalk,
+    TypeCtor, TypeWalk, Uncertain,
 };
 use crate::{
     adt::VariantDef,
@@ -43,7 +43,7 @@ use crate::{
     expr::{BindingAnnotation, Body, ExprId, PatId},
     resolve::{Resolver, TypeNs},
     ty::infer::diagnostics::InferenceDiagnostic,
-    Adt, AssocItem, ConstData, DefWithBody, FnData, Function, Path, StructField,
+    Adt, AssocItem, ConstData, DefWithBody, FloatTy, FnData, Function, IntTy, Path, StructField,
 };
 
 macro_rules! ty_app {
@@ -358,14 +358,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
     fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
         match ty {
             Ty::Unknown => self.new_type_var(),
-            Ty::Apply(ApplicationTy {
-                ctor: TypeCtor::Int(primitive::UncertainIntTy::Unknown),
-                ..
-            }) => self.new_integer_var(),
-            Ty::Apply(ApplicationTy {
-                ctor: TypeCtor::Float(primitive::UncertainFloatTy::Unknown),
-                ..
-            }) => self.new_float_var(),
+            Ty::Apply(ApplicationTy { ctor: TypeCtor::Int(Uncertain::Unknown), .. }) => {
+                self.new_integer_var()
+            }
+            Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(Uncertain::Unknown), .. }) => {
+                self.new_float_var()
+            }
             _ => ty,
         }
     }
@@ -684,12 +682,8 @@ impl InferTy {
     fn fallback_value(self) -> Ty {
         match self {
             InferTy::TypeVar(..) => Ty::Unknown,
-            InferTy::IntVar(..) => {
-                Ty::simple(TypeCtor::Int(primitive::UncertainIntTy::Known(primitive::IntTy::i32())))
-            }
-            InferTy::FloatVar(..) => Ty::simple(TypeCtor::Float(
-                primitive::UncertainFloatTy::Known(primitive::FloatTy::f64()),
-            )),
+            InferTy::IntVar(..) => Ty::simple(TypeCtor::Int(Uncertain::Known(IntTy::i32()))),
+            InferTy::FloatVar(..) => Ty::simple(TypeCtor::Float(Uncertain::Known(FloatTy::f64()))),
             InferTy::MaybeNeverTypeVar(..) => Ty::simple(TypeCtor::Never),
         }
     }
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs
index c6802487a0c..5e68a1678f4 100644
--- a/crates/ra_hir/src/ty/infer/expr.rs
+++ b/crates/ra_hir/src/ty/infer/expr.rs
@@ -3,7 +3,10 @@
 use std::iter::{repeat, repeat_with};
 use std::sync::Arc;
 
-use hir_def::path::{GenericArg, GenericArgs};
+use hir_def::{
+    builtin_type::Signedness,
+    path::{GenericArg, GenericArgs},
+};
 use hir_expand::name;
 
 use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch};
@@ -12,8 +15,9 @@ use crate::{
     expr::{self, Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
     generics::{GenericParams, HasGenericParams},
     ty::{
-        autoderef, method_resolution, op, primitive, CallableDef, InferTy, Mutability, Namespace,
+        autoderef, method_resolution, op, CallableDef, InferTy, IntTy, Mutability, Namespace,
         Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
+        Uncertain,
     },
     Adt, Name,
 };
@@ -337,13 +341,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                     UnaryOp::Neg => {
                         match &inner_ty {
                             Ty::Apply(a_ty) => match a_ty.ctor {
-                                TypeCtor::Int(primitive::UncertainIntTy::Unknown)
-                                | TypeCtor::Int(primitive::UncertainIntTy::Known(
-                                    primitive::IntTy {
-                                        signedness: primitive::Signedness::Signed,
-                                        ..
-                                    },
-                                ))
+                                TypeCtor::Int(Uncertain::Unknown)
+                                | TypeCtor::Int(Uncertain::Known(IntTy {
+                                    signedness: Signedness::Signed,
+                                    ..
+                                }))
                                 | TypeCtor::Float(..) => inner_ty,
                                 _ => Ty::Unknown,
                             },
@@ -428,9 +430,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                         );
                         self.infer_expr(
                             *repeat,
-                            &Expectation::has_type(Ty::simple(TypeCtor::Int(
-                                primitive::UncertainIntTy::Known(primitive::IntTy::usize()),
-                            ))),
+                            &Expectation::has_type(Ty::simple(TypeCtor::Int(Uncertain::Known(
+                                IntTy::usize(),
+                            )))),
                         );
                     }
                 }
@@ -443,9 +445,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                     Ty::apply_one(TypeCtor::Ref(Mutability::Shared), Ty::simple(TypeCtor::Str))
                 }
                 Literal::ByteString(..) => {
-                    let byte_type = Ty::simple(TypeCtor::Int(primitive::UncertainIntTy::Known(
-                        primitive::IntTy::u8(),
-                    )));
+                    let byte_type = Ty::simple(TypeCtor::Int(Uncertain::Known(IntTy::u8())));
                     let slice_type = Ty::apply_one(TypeCtor::Slice, byte_type);
                     Ty::apply_one(TypeCtor::Ref(Mutability::Shared), slice_type)
                 }
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 1832fcf5042..de3c56097bd 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -25,7 +25,7 @@ use crate::{
     generics::{GenericDef, WherePredicate},
     resolve::{Resolver, TypeNs},
     ty::{
-        primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy},
+        primitive::{FloatTy, IntTy, Uncertain},
         Adt,
     },
     util::make_mut_slice,
@@ -674,20 +674,20 @@ impl From<BuiltinFloat> for FloatTy {
     }
 }
 
-impl From<Option<BuiltinInt>> for UncertainIntTy {
+impl From<Option<BuiltinInt>> for Uncertain<IntTy> {
     fn from(t: Option<BuiltinInt>) -> Self {
         match t {
-            None => UncertainIntTy::Unknown,
-            Some(t) => UncertainIntTy::Known(t.into()),
+            None => Uncertain::Unknown,
+            Some(t) => Uncertain::Known(t.into()),
         }
     }
 }
 
-impl From<Option<BuiltinFloat>> for UncertainFloatTy {
+impl From<Option<BuiltinFloat>> for Uncertain<FloatTy> {
     fn from(t: Option<BuiltinFloat>) -> Self {
         match t {
-            None => UncertainFloatTy::Unknown,
-            Some(t) => UncertainFloatTy::Known(t.into()),
+            None => Uncertain::Unknown,
+            Some(t) => Uncertain::Known(t.into()),
         }
     }
 }
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 8c3d32d09dc..eb5ca6769a1 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -8,16 +8,17 @@ use arrayvec::ArrayVec;
 use hir_def::CrateModuleId;
 use rustc_hash::FxHashMap;
 
-use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef};
 use crate::{
     db::HirDatabase,
     impl_block::{ImplBlock, ImplId},
     resolve::Resolver,
-    ty::primitive::{FloatBitness, UncertainFloatTy, UncertainIntTy},
+    ty::primitive::{FloatBitness, Uncertain},
     ty::{Ty, TypeCtor},
     AssocItem, Crate, Function, Module, Mutability, Name, Trait,
 };
 
+use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef};
+
 /// This is used as a key for indexing impls.
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub enum TyFingerprint {
@@ -140,14 +141,12 @@ fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayV
             TypeCtor::Adt(def_id) => Some(std::iter::once(def_id.krate(db)?).collect()),
             TypeCtor::Bool => lang_item_crate!(db, cur_crate, "bool"),
             TypeCtor::Char => lang_item_crate!(db, cur_crate, "char"),
-            TypeCtor::Float(UncertainFloatTy::Known(f)) => match f.bitness {
+            TypeCtor::Float(Uncertain::Known(f)) => match f.bitness {
                 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime)
                 FloatBitness::X32 => lang_item_crate!(db, cur_crate, "f32", "f32_runtime"),
                 FloatBitness::X64 => lang_item_crate!(db, cur_crate, "f64", "f64_runtime"),
             },
-            TypeCtor::Int(UncertainIntTy::Known(i)) => {
-                lang_item_crate!(db, cur_crate, i.ty_to_string())
-            }
+            TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(db, cur_crate, i.ty_to_string()),
             TypeCtor::Str => lang_item_crate!(db, cur_crate, "str_alloc", "str"),
             TypeCtor::Slice => lang_item_crate!(db, cur_crate, "slice_alloc", "slice"),
             TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!(db, cur_crate, "const_ptr"),
diff --git a/crates/ra_hir/src/ty/primitive.rs b/crates/ra_hir/src/ty/primitive.rs
index 7362de4c3f7..47789db8775 100644
--- a/crates/ra_hir/src/ty/primitive.rs
+++ b/crates/ra_hir/src/ty/primitive.rs
@@ -4,44 +4,38 @@ use std::fmt;
 
 pub use hir_def::builtin_type::{FloatBitness, IntBitness, Signedness};
 
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum UncertainIntTy {
+#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
+pub enum Uncertain<T> {
     Unknown,
-    Known(IntTy),
+    Known(T),
 }
 
-impl From<IntTy> for UncertainIntTy {
+impl From<IntTy> for Uncertain<IntTy> {
     fn from(ty: IntTy) -> Self {
-        UncertainIntTy::Known(ty)
+        Uncertain::Known(ty)
     }
 }
 
-impl fmt::Display for UncertainIntTy {
+impl fmt::Display for Uncertain<IntTy> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            UncertainIntTy::Unknown => write!(f, "{{integer}}"),
-            UncertainIntTy::Known(ty) => write!(f, "{}", ty),
+            Uncertain::Unknown => write!(f, "{{integer}}"),
+            Uncertain::Known(ty) => write!(f, "{}", ty),
         }
     }
 }
 
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum UncertainFloatTy {
-    Unknown,
-    Known(FloatTy),
-}
-
-impl From<FloatTy> for UncertainFloatTy {
+impl From<FloatTy> for Uncertain<FloatTy> {
     fn from(ty: FloatTy) -> Self {
-        UncertainFloatTy::Known(ty)
+        Uncertain::Known(ty)
     }
 }
 
-impl fmt::Display for UncertainFloatTy {
+impl fmt::Display for Uncertain<FloatTy> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            UncertainFloatTy::Unknown => write!(f, "{{float}}"),
-            UncertainFloatTy::Known(ty) => write!(f, "{}", ty),
+            Uncertain::Unknown => write!(f, "{{float}}"),
+            Uncertain::Known(ty) => write!(f, "{}", ty),
         }
     }
 }