aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-03-16 16:21:32 +0000
committerFlorian Diebold <[email protected]>2019-03-16 16:21:32 +0000
commita9ddaba905348897606948658798f9f46854acf7 (patch)
treef907c61b8a13f33c2c9f315651d938b9dca0579d /crates
parent628b530e92c1579f3924c37290ad59ac0512d2a0 (diff)
Refactor FnSig a bit
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/ty.rs81
-rw-r--r--crates/ra_hir/src/ty/infer.rs23
-rw-r--r--crates/ra_hir/src/ty/lower.rs70
3 files changed, 104 insertions, 70 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 884cea52a..31f726f35 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -78,7 +78,7 @@ pub enum Ty {
78 /// The definition of the function / constructor. 78 /// The definition of the function / constructor.
79 def: CallableDef, 79 def: CallableDef,
80 /// Parameters and return type 80 /// Parameters and return type
81 sig: Arc<FnSig>, 81 sig: FnSig,
82 /// Substitutions for the generic parameters of the type 82 /// Substitutions for the generic parameters of the type
83 substs: Substs, 83 substs: Substs,
84 }, 84 },
@@ -91,7 +91,7 @@ pub enum Ty {
91 /// fn foo() -> i32 { 1 } 91 /// fn foo() -> i32 { 1 }
92 /// let bar: fn() -> i32 = foo; 92 /// let bar: fn() -> i32 = foo;
93 /// ``` 93 /// ```
94 FnPtr(Arc<FnSig>), 94 FnPtr(FnSig),
95 95
96 /// The never type `!`. 96 /// The never type `!`.
97 Never, 97 Never,
@@ -128,13 +128,44 @@ impl Substs {
128 pub fn empty() -> Substs { 128 pub fn empty() -> Substs {
129 Substs(Arc::new([])) 129 Substs(Arc::new([]))
130 } 130 }
131
132 pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
133 // Without an Arc::make_mut_slice, we can't avoid the clone here:
134 let mut v: Vec<_> = self.0.iter().cloned().collect();
135 for t in &mut v {
136 t.walk_mut(f);
137 }
138 self.0 = v.into();
139 }
131} 140}
132 141
133/// A function signature. 142/// A function signature.
134#[derive(Clone, PartialEq, Eq, Debug)] 143#[derive(Clone, PartialEq, Eq, Debug)]
135pub struct FnSig { 144pub struct FnSig {
136 input: Vec<Ty>, 145 params_and_return: Arc<[Ty]>,
137 output: Ty, 146}
147
148impl FnSig {
149 pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig {
150 params.push(ret);
151 FnSig { params_and_return: params.into() }
152 }
153 pub fn params(&self) -> &[Ty] {
154 &self.params_and_return[0..self.params_and_return.len() - 1]
155 }
156
157 pub fn ret(&self) -> &Ty {
158 &self.params_and_return[self.params_and_return.len() - 1]
159 }
160
161 pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
162 // Without an Arc::make_mut_slice, we can't avoid the clone here:
163 let mut v: Vec<_> = self.params_and_return.iter().cloned().collect();
164 for t in &mut v {
165 t.walk_mut(f);
166 }
167 self.params_and_return = v.into();
168 }
138} 169}
139 170
140impl Ty { 171impl Ty {
@@ -153,16 +184,16 @@ impl Ty {
153 } 184 }
154 } 185 }
155 Ty::FnPtr(sig) => { 186 Ty::FnPtr(sig) => {
156 for input in &sig.input { 187 for input in sig.params() {
157 input.walk(f); 188 input.walk(f);
158 } 189 }
159 sig.output.walk(f); 190 sig.ret().walk(f);
160 } 191 }
161 Ty::FnDef { substs, sig, .. } => { 192 Ty::FnDef { substs, sig, .. } => {
162 for input in &sig.input { 193 for input in sig.params() {
163 input.walk(f); 194 input.walk(f);
164 } 195 }
165 sig.output.walk(f); 196 sig.ret().walk(f);
166 for t in substs.0.iter() { 197 for t in substs.0.iter() {
167 t.walk(f); 198 t.walk(f);
168 } 199 }
@@ -199,32 +230,14 @@ impl Ty {
199 *ts = v.into(); 230 *ts = v.into();
200 } 231 }
201 Ty::FnPtr(sig) => { 232 Ty::FnPtr(sig) => {
202 let sig_mut = Arc::make_mut(sig); 233 sig.walk_mut(f);
203 for input in &mut sig_mut.input {
204 input.walk_mut(f);
205 }
206 sig_mut.output.walk_mut(f);
207 } 234 }
208 Ty::FnDef { substs, sig, .. } => { 235 Ty::FnDef { substs, sig, .. } => {
209 let sig_mut = Arc::make_mut(sig); 236 sig.walk_mut(f);
210 for input in &mut sig_mut.input { 237 substs.walk_mut(f);
211 input.walk_mut(f);
212 }
213 sig_mut.output.walk_mut(f);
214 // Without an Arc::make_mut_slice, we can't avoid the clone here:
215 let mut v: Vec<_> = substs.0.iter().cloned().collect();
216 for t in &mut v {
217 t.walk_mut(f);
218 }
219 substs.0 = v.into();
220 } 238 }
221 Ty::Adt { substs, .. } => { 239 Ty::Adt { substs, .. } => {
222 // Without an Arc::make_mut_slice, we can't avoid the clone here: 240 substs.walk_mut(f);
223 let mut v: Vec<_> = substs.0.iter().cloned().collect();
224 for t in &mut v {
225 t.walk_mut(f);
226 }
227 substs.0 = v.into();
228 } 241 }
229 Ty::Bool 242 Ty::Bool
230 | Ty::Char 243 | Ty::Char
@@ -328,8 +341,8 @@ impl HirDisplay for Ty {
328 } 341 }
329 Ty::FnPtr(sig) => { 342 Ty::FnPtr(sig) => {
330 write!(f, "fn(")?; 343 write!(f, "fn(")?;
331 f.write_joined(&sig.input, ", ")?; 344 f.write_joined(sig.params(), ", ")?;
332 write!(f, ") -> {}", sig.output.display(f.db))?; 345 write!(f, ") -> {}", sig.ret().display(f.db))?;
333 } 346 }
334 Ty::FnDef { def, substs, sig, .. } => { 347 Ty::FnDef { def, substs, sig, .. } => {
335 let name = match def { 348 let name = match def {
@@ -347,8 +360,8 @@ impl HirDisplay for Ty {
347 write!(f, ">")?; 360 write!(f, ">")?;
348 } 361 }
349 write!(f, "(")?; 362 write!(f, "(")?;
350 f.write_joined(&sig.input, ", ")?; 363 f.write_joined(sig.params(), ", ")?;
351 write!(f, ") -> {}", sig.output.display(f.db))?; 364 write!(f, ") -> {}", sig.ret().display(f.db))?;
352 } 365 }
353 Ty::Adt { def_id, substs, .. } => { 366 Ty::Adt { def_id, substs, .. } => {
354 let name = match def_id { 367 let name = match def_id {
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 268d2c110..2eb73726e 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -724,11 +724,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
724 Expr::Call { callee, args } => { 724 Expr::Call { callee, args } => {
725 let callee_ty = self.infer_expr(*callee, &Expectation::none()); 725 let callee_ty = self.infer_expr(*callee, &Expectation::none());
726 let (param_tys, ret_ty) = match &callee_ty { 726 let (param_tys, ret_ty) = match &callee_ty {
727 Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()), 727 Ty::FnPtr(sig) => (sig.params().to_vec(), sig.ret().clone()),
728 Ty::FnDef { substs, sig, .. } => { 728 Ty::FnDef { substs, sig, .. } => {
729 let ret_ty = sig.output.clone().subst(&substs); 729 let ret_ty = sig.ret().clone().subst(&substs);
730 let param_tys = 730 let param_tys =
731 sig.input.iter().map(|ty| ty.clone().subst(&substs)).collect(); 731 sig.params().iter().map(|ty| ty.clone().subst(&substs)).collect();
732 (param_tys, ret_ty) 732 (param_tys, ret_ty)
733 } 733 }
734 _ => { 734 _ => {
@@ -762,19 +762,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
762 let method_ty = self.insert_type_vars(method_ty); 762 let method_ty = self.insert_type_vars(method_ty);
763 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { 763 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty {
764 Ty::FnPtr(sig) => { 764 Ty::FnPtr(sig) => {
765 if !sig.input.is_empty() { 765 if !sig.params().is_empty() {
766 (sig.input[0].clone(), sig.input[1..].to_vec(), sig.output.clone()) 766 (sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone())
767 } else { 767 } else {
768 (Ty::Unknown, Vec::new(), sig.output.clone()) 768 (Ty::Unknown, Vec::new(), sig.ret().clone())
769 } 769 }
770 } 770 }
771 Ty::FnDef { substs, sig, .. } => { 771 Ty::FnDef { substs, sig, .. } => {
772 let ret_ty = sig.output.clone().subst(&substs); 772 let ret_ty = sig.ret().clone().subst(&substs);
773 773
774 if !sig.input.is_empty() { 774 if !sig.params().is_empty() {
775 let mut arg_iter = sig.input.iter().map(|ty| ty.clone().subst(&substs)); 775 let mut params_iter =
776 let receiver_ty = arg_iter.next().unwrap(); 776 sig.params().iter().map(|ty| ty.clone().subst(&substs));
777 (receiver_ty, arg_iter.collect(), ret_ty) 777 let receiver_ty = params_iter.next().unwrap();
778 (receiver_ty, params_iter.collect(), ret_ty)
778 } else { 779 } else {
779 (Ty::Unknown, Vec::new(), ret_ty) 780 (Ty::Unknown, Vec::new(), ret_ty)
780 } 781 }
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index ee4508bb2..7d065203a 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -51,12 +51,10 @@ impl Ty {
51 } 51 }
52 TypeRef::Placeholder => Ty::Unknown, 52 TypeRef::Placeholder => Ty::Unknown,
53 TypeRef::Fn(params) => { 53 TypeRef::Fn(params) => {
54 let mut inner_tys = 54 let inner_tys =
55 params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); 55 params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>();
56 let return_ty = 56 let sig = FnSig { params_and_return: inner_tys.into() };
57 inner_tys.pop().expect("TypeRef::Fn should always have at least return type"); 57 Ty::FnPtr(sig)
58 let sig = FnSig { input: inner_tys, output: return_ty };
59 Ty::FnPtr(Arc::new(sig))
60 } 58 }
61 TypeRef::Error => Ty::Unknown, 59 TypeRef::Error => Ty::Unknown,
62 } 60 }
@@ -226,16 +224,20 @@ pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty {
226 Ty::from_hir(db, &resolver, type_ref) 224 Ty::from_hir(db, &resolver, type_ref)
227} 225}
228 226
227fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig {
228 let signature = def.signature(db);
229 let resolver = def.resolver(db);
230 let params =
231 signature.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
232 let ret = Ty::from_hir(db, &resolver, signature.ret_type());
233 FnSig::from_params_and_return(params, ret)
234}
235
229/// Build the declared type of a function. This should not need to look at the 236/// Build the declared type of a function. This should not need to look at the
230/// function body. 237/// function body.
231fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { 238fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
232 let signature = def.signature(db); 239 let sig = fn_sig_for_fn(db, def);
233 let resolver = def.resolver(db);
234 let generics = def.generic_params(db); 240 let generics = def.generic_params(db);
235 let input =
236 signature.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
237 let output = Ty::from_hir(db, &resolver, signature.ret_type());
238 let sig = Arc::new(FnSig { input, output });
239 let substs = make_substs(&generics); 241 let substs = make_substs(&generics);
240 Ty::FnDef { def: def.into(), sig, substs } 242 Ty::FnDef { def: def.into(), sig, substs }
241} 243}
@@ -256,41 +258,59 @@ fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty {
256 Ty::from_hir(db, &resolver, signature.type_ref()) 258 Ty::from_hir(db, &resolver, signature.type_ref())
257} 259}
258 260
259/// Build the type of a tuple struct constructor. 261fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
260fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
261 let var_data = def.variant_data(db); 262 let var_data = def.variant_data(db);
262 let fields = match var_data.fields() { 263 let fields = match var_data.fields() {
263 Some(fields) => fields, 264 Some(fields) => fields,
264 None => return type_for_struct(db, def), // Unit struct 265 None => panic!("fn_sig_for_struct_constructor called on unit struct"),
265 }; 266 };
266 let resolver = def.resolver(db); 267 let resolver = def.resolver(db);
267 let generics = def.generic_params(db); 268 let params = fields
268 let input = fields
269 .iter() 269 .iter()
270 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) 270 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
271 .collect::<Vec<_>>(); 271 .collect::<Vec<_>>();
272 let output = type_for_struct(db, def); 272 let ret = type_for_struct(db, def);
273 let sig = Arc::new(FnSig { input, output }); 273 FnSig::from_params_and_return(params, ret)
274}
275
276/// Build the type of a tuple struct constructor.
277fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
278 let var_data = def.variant_data(db);
279 if var_data.fields().is_none() {
280 return type_for_struct(db, def); // Unit struct
281 }
282 let sig = fn_sig_for_struct_constructor(db, def);
283 let generics = def.generic_params(db);
274 let substs = make_substs(&generics); 284 let substs = make_substs(&generics);
275 Ty::FnDef { def: def.into(), sig, substs } 285 Ty::FnDef { def: def.into(), sig, substs }
276} 286}
277 287
278/// Build the type of a tuple enum variant constructor. 288fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig {
279fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty {
280 let var_data = def.variant_data(db); 289 let var_data = def.variant_data(db);
281 let fields = match var_data.fields() { 290 let fields = match var_data.fields() {
282 Some(fields) => fields, 291 Some(fields) => fields,
283 None => return type_for_enum(db, def.parent_enum(db)), // Unit variant 292 None => panic!("fn_sig_for_enum_variant_constructor called for unit variant"),
284 }; 293 };
285 let resolver = def.parent_enum(db).resolver(db); 294 let resolver = def.parent_enum(db).resolver(db);
286 let generics = def.parent_enum(db).generic_params(db); 295 let params = fields
287 let input = fields
288 .iter() 296 .iter()
289 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) 297 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
290 .collect::<Vec<_>>(); 298 .collect::<Vec<_>>();
299 let generics = def.parent_enum(db).generic_params(db);
300 let substs = make_substs(&generics);
301 let ret = type_for_enum(db, def.parent_enum(db)).subst(&substs);
302 FnSig::from_params_and_return(params, ret)
303}
304
305/// Build the type of a tuple enum variant constructor.
306fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty {
307 let var_data = def.variant_data(db);
308 if var_data.fields().is_none() {
309 return type_for_enum(db, def.parent_enum(db)); // Unit variant
310 }
311 let sig = fn_sig_for_enum_variant_constructor(db, def);
312 let generics = def.parent_enum(db).generic_params(db);
291 let substs = make_substs(&generics); 313 let substs = make_substs(&generics);
292 let output = type_for_enum(db, def.parent_enum(db)).subst(&substs);
293 let sig = Arc::new(FnSig { input, output });
294 Ty::FnDef { def: def.into(), sig, substs } 314 Ty::FnDef { def: def.into(), sig, substs }
295} 315}
296 316