diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 81 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 70 |
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)] |
135 | pub struct FnSig { | 144 | pub struct FnSig { |
136 | input: Vec<Ty>, | 145 | params_and_return: Arc<[Ty]>, |
137 | output: Ty, | 146 | } |
147 | |||
148 | impl 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 | ||
140 | impl Ty { | 171 | impl 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 | ||
227 | fn 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. |
231 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { | 238 | fn 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. | 261 | fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { |
260 | fn 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. | ||
277 | fn 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. | 288 | fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig { |
279 | fn 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. | ||
306 | fn 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 | ||