]> git.lizzy.rs Git - rust.git/commitdiff
Refactor FnSig a bit
authorFlorian Diebold <flodiebold@gmail.com>
Sat, 16 Mar 2019 16:21:32 +0000 (17:21 +0100)
committerFlorian Diebold <flodiebold@gmail.com>
Sat, 16 Mar 2019 16:21:32 +0000 (17:21 +0100)
crates/ra_hir/src/ty.rs
crates/ra_hir/src/ty/infer.rs
crates/ra_hir/src/ty/lower.rs

index 884cea52a7d2559c3ef346fca8f50254d4de79ef..31f726f3584a8b10f1dedbcf0d654b959b706fc2 100644 (file)
@@ -78,7 +78,7 @@ pub enum Ty {
         /// The definition of the function / constructor.
         def: CallableDef,
         /// Parameters and return type
-        sig: Arc<FnSig>,
+        sig: FnSig,
         /// Substitutions for the generic parameters of the type
         substs: Substs,
     },
@@ -91,7 +91,7 @@ pub enum Ty {
     /// fn foo() -> i32 { 1 }
     /// let bar: fn() -> i32 = foo;
     /// ```
-    FnPtr(Arc<FnSig>),
+    FnPtr(FnSig),
 
     /// The never type `!`.
     Never,
@@ -128,13 +128,44 @@ impl Substs {
     pub fn empty() -> Substs {
         Substs(Arc::new([]))
     }
+
+    pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
+        // Without an Arc::make_mut_slice, we can't avoid the clone here:
+        let mut v: Vec<_> = self.0.iter().cloned().collect();
+        for t in &mut v {
+            t.walk_mut(f);
+        }
+        self.0 = v.into();
+    }
 }
 
 /// A function signature.
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct FnSig {
-    input: Vec<Ty>,
-    output: Ty,
+    params_and_return: Arc<[Ty]>,
+}
+
+impl FnSig {
+    pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig {
+        params.push(ret);
+        FnSig { params_and_return: params.into() }
+    }
+    pub fn params(&self) -> &[Ty] {
+        &self.params_and_return[0..self.params_and_return.len() - 1]
+    }
+
+    pub fn ret(&self) -> &Ty {
+        &self.params_and_return[self.params_and_return.len() - 1]
+    }
+
+    pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
+        // Without an Arc::make_mut_slice, we can't avoid the clone here:
+        let mut v: Vec<_> = self.params_and_return.iter().cloned().collect();
+        for t in &mut v {
+            t.walk_mut(f);
+        }
+        self.params_and_return = v.into();
+    }
 }
 
 impl Ty {
@@ -153,16 +184,16 @@ pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
                 }
             }
             Ty::FnPtr(sig) => {
-                for input in &sig.input {
+                for input in sig.params() {
                     input.walk(f);
                 }
-                sig.output.walk(f);
+                sig.ret().walk(f);
             }
             Ty::FnDef { substs, sig, .. } => {
-                for input in &sig.input {
+                for input in sig.params() {
                     input.walk(f);
                 }
-                sig.output.walk(f);
+                sig.ret().walk(f);
                 for t in substs.0.iter() {
                     t.walk(f);
                 }
@@ -199,32 +230,14 @@ fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
                 *ts = v.into();
             }
             Ty::FnPtr(sig) => {
-                let sig_mut = Arc::make_mut(sig);
-                for input in &mut sig_mut.input {
-                    input.walk_mut(f);
-                }
-                sig_mut.output.walk_mut(f);
+                sig.walk_mut(f);
             }
             Ty::FnDef { substs, sig, .. } => {
-                let sig_mut = Arc::make_mut(sig);
-                for input in &mut sig_mut.input {
-                    input.walk_mut(f);
-                }
-                sig_mut.output.walk_mut(f);
-                // Without an Arc::make_mut_slice, we can't avoid the clone here:
-                let mut v: Vec<_> = substs.0.iter().cloned().collect();
-                for t in &mut v {
-                    t.walk_mut(f);
-                }
-                substs.0 = v.into();
+                sig.walk_mut(f);
+                substs.walk_mut(f);
             }
             Ty::Adt { substs, .. } => {
-                // Without an Arc::make_mut_slice, we can't avoid the clone here:
-                let mut v: Vec<_> = substs.0.iter().cloned().collect();
-                for t in &mut v {
-                    t.walk_mut(f);
-                }
-                substs.0 = v.into();
+                substs.walk_mut(f);
             }
             Ty::Bool
             | Ty::Char
@@ -328,8 +341,8 @@ fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
             }
             Ty::FnPtr(sig) => {
                 write!(f, "fn(")?;
-                f.write_joined(&sig.input, ", ")?;
-                write!(f, ") -> {}", sig.output.display(f.db))?;
+                f.write_joined(sig.params(), ", ")?;
+                write!(f, ") -> {}", sig.ret().display(f.db))?;
             }
             Ty::FnDef { def, substs, sig, .. } => {
                 let name = match def {
@@ -347,8 +360,8 @@ fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
                     write!(f, ">")?;
                 }
                 write!(f, "(")?;
-                f.write_joined(&sig.input, ", ")?;
-                write!(f, ") -> {}", sig.output.display(f.db))?;
+                f.write_joined(sig.params(), ", ")?;
+                write!(f, ") -> {}", sig.ret().display(f.db))?;
             }
             Ty::Adt { def_id, substs, .. } => {
                 let name = match def_id {
index 268d2c1104692942ad1afb77b9df2d0f25d28729..2eb73726e777a12fbf44b3edf49d3d1d7f9dcd73 100644 (file)
@@ -724,11 +724,11 @@ fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
             Expr::Call { callee, args } => {
                 let callee_ty = self.infer_expr(*callee, &Expectation::none());
                 let (param_tys, ret_ty) = match &callee_ty {
-                    Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()),
+                    Ty::FnPtr(sig) => (sig.params().to_vec(), sig.ret().clone()),
                     Ty::FnDef { substs, sig, .. } => {
-                        let ret_ty = sig.output.clone().subst(&substs);
+                        let ret_ty = sig.ret().clone().subst(&substs);
                         let param_tys =
-                            sig.input.iter().map(|ty| ty.clone().subst(&substs)).collect();
+                            sig.params().iter().map(|ty| ty.clone().subst(&substs)).collect();
                         (param_tys, ret_ty)
                     }
                     _ => {
@@ -762,19 +762,20 @@ fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                 let method_ty = self.insert_type_vars(method_ty);
                 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty {
                     Ty::FnPtr(sig) => {
-                        if !sig.input.is_empty() {
-                            (sig.input[0].clone(), sig.input[1..].to_vec(), sig.output.clone())
+                        if !sig.params().is_empty() {
+                            (sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone())
                         } else {
-                            (Ty::Unknown, Vec::new(), sig.output.clone())
+                            (Ty::Unknown, Vec::new(), sig.ret().clone())
                         }
                     }
                     Ty::FnDef { substs, sig, .. } => {
-                        let ret_ty = sig.output.clone().subst(&substs);
+                        let ret_ty = sig.ret().clone().subst(&substs);
 
-                        if !sig.input.is_empty() {
-                            let mut arg_iter = sig.input.iter().map(|ty| ty.clone().subst(&substs));
-                            let receiver_ty = arg_iter.next().unwrap();
-                            (receiver_ty, arg_iter.collect(), ret_ty)
+                        if !sig.params().is_empty() {
+                            let mut params_iter =
+                                sig.params().iter().map(|ty| ty.clone().subst(&substs));
+                            let receiver_ty = params_iter.next().unwrap();
+                            (receiver_ty, params_iter.collect(), ret_ty)
                         } else {
                             (Ty::Unknown, Vec::new(), ret_ty)
                         }
index ee4508bb26286915b06b494a95a07d0dda3d9c50..7d065203afdfa4da9a1c11377b92dcfafbda5a97 100644 (file)
@@ -51,12 +51,10 @@ pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &Ty
             }
             TypeRef::Placeholder => Ty::Unknown,
             TypeRef::Fn(params) => {
-                let mut inner_tys =
+                let inner_tys =
                     params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>();
-                let return_ty =
-                    inner_tys.pop().expect("TypeRef::Fn should always have at least return type");
-                let sig = FnSig { input: inner_tys, output: return_ty };
-                Ty::FnPtr(Arc::new(sig))
+                let sig = FnSig { params_and_return: inner_tys.into() };
+                Ty::FnPtr(sig)
             }
             TypeRef::Error => Ty::Unknown,
         }
@@ -226,16 +224,20 @@ pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty {
     Ty::from_hir(db, &resolver, type_ref)
 }
 
+fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig {
+    let signature = def.signature(db);
+    let resolver = def.resolver(db);
+    let params =
+        signature.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
+    let ret = Ty::from_hir(db, &resolver, signature.ret_type());
+    FnSig::from_params_and_return(params, ret)
+}
+
 /// Build the declared type of a function. This should not need to look at the
 /// function body.
 fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
-    let signature = def.signature(db);
-    let resolver = def.resolver(db);
+    let sig = fn_sig_for_fn(db, def);
     let generics = def.generic_params(db);
-    let input =
-        signature.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
-    let output = Ty::from_hir(db, &resolver, signature.ret_type());
-    let sig = Arc::new(FnSig { input, output });
     let substs = make_substs(&generics);
     Ty::FnDef { def: def.into(), sig, substs }
 }
@@ -256,41 +258,59 @@ fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty {
     Ty::from_hir(db, &resolver, signature.type_ref())
 }
 
-/// Build the type of a tuple struct constructor.
-fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
+fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
     let var_data = def.variant_data(db);
     let fields = match var_data.fields() {
         Some(fields) => fields,
-        None => return type_for_struct(db, def), // Unit struct
+        None => panic!("fn_sig_for_struct_constructor called on unit struct"),
     };
     let resolver = def.resolver(db);
-    let generics = def.generic_params(db);
-    let input = fields
+    let params = fields
         .iter()
         .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
         .collect::<Vec<_>>();
-    let output = type_for_struct(db, def);
-    let sig = Arc::new(FnSig { input, output });
+    let ret = type_for_struct(db, def);
+    FnSig::from_params_and_return(params, ret)
+}
+
+/// Build the type of a tuple struct constructor.
+fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
+    let var_data = def.variant_data(db);
+    if var_data.fields().is_none() {
+        return type_for_struct(db, def); // Unit struct
+    }
+    let sig = fn_sig_for_struct_constructor(db, def);
+    let generics = def.generic_params(db);
     let substs = make_substs(&generics);
     Ty::FnDef { def: def.into(), sig, substs }
 }
 
-/// Build the type of a tuple enum variant constructor.
-fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty {
+fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig {
     let var_data = def.variant_data(db);
     let fields = match var_data.fields() {
         Some(fields) => fields,
-        None => return type_for_enum(db, def.parent_enum(db)), // Unit variant
+        None => panic!("fn_sig_for_enum_variant_constructor called for unit variant"),
     };
     let resolver = def.parent_enum(db).resolver(db);
-    let generics = def.parent_enum(db).generic_params(db);
-    let input = fields
+    let params = fields
         .iter()
         .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
         .collect::<Vec<_>>();
+    let generics = def.parent_enum(db).generic_params(db);
+    let substs = make_substs(&generics);
+    let ret = type_for_enum(db, def.parent_enum(db)).subst(&substs);
+    FnSig::from_params_and_return(params, ret)
+}
+
+/// Build the type of a tuple enum variant constructor.
+fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty {
+    let var_data = def.variant_data(db);
+    if var_data.fields().is_none() {
+        return type_for_enum(db, def.parent_enum(db)); // Unit variant
+    }
+    let sig = fn_sig_for_enum_variant_constructor(db, def);
+    let generics = def.parent_enum(db).generic_params(db);
     let substs = make_substs(&generics);
-    let output = type_for_enum(db, def.parent_enum(db)).subst(&substs);
-    let sig = Arc::new(FnSig { input, output });
     Ty::FnDef { def: def.into(), sig, substs }
 }