aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-01-12 20:27:35 +0000
committerFlorian Diebold <[email protected]>2019-01-19 15:02:06 +0000
commit688a45e00b53412a7a16360c6d678a5d91a95789 (patch)
treed3f3481bbad9889d22867729e9efcde184e45671 /crates/ra_hir/src/ty.rs
parent415cdc52108807126f0339fbf812856582f01c18 (diff)
Implement beginnings of generics
- add HIR for generic params - resolve generic params in type paths - add substitions for ADTs - insert type variables for substitutions
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r--crates/ra_hir/src/ty.rs180
1 files changed, 147 insertions, 33 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 8d6493887..b9a48929d 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -37,6 +37,7 @@ use crate::{
37 type_ref::{TypeRef, Mutability}, 37 type_ref::{TypeRef, Mutability},
38 name::KnownName, 38 name::KnownName,
39 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat}, 39 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat},
40 generics::Generics,
40}; 41};
41 42
42/// The ID of a type variable. 43/// The ID of a type variable.
@@ -151,10 +152,14 @@ impl Expectation {
151 } 152 }
152} 153}
153 154
155/// A list of substitutions for generic parameters.
156#[derive(Clone, PartialEq, Eq, Debug)]
157pub struct Substs(Arc<[Ty]>);
158
154/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). 159/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs).
155/// 160///
156/// This should be cheap to clone. 161/// This should be cheap to clone.
157#[derive(Clone, PartialEq, Eq, Hash, Debug)] 162#[derive(Clone, PartialEq, Eq, Debug)]
158pub enum Ty { 163pub enum Ty {
159 /// The primitive boolean type. Written as `bool`. 164 /// The primitive boolean type. Written as `bool`.
160 Bool, 165 Bool,
@@ -175,7 +180,8 @@ pub enum Ty {
175 def_id: DefId, 180 def_id: DefId,
176 /// The name, for displaying. 181 /// The name, for displaying.
177 name: Name, 182 name: Name,
178 // later we'll need generic substitutions here 183 /// Substitutions for the generic parameters of the type.
184 substs: Substs,
179 }, 185 },
180 186
181 /// The pointee of a string slice. Written as `str`. 187 /// The pointee of a string slice. Written as `str`.
@@ -234,9 +240,14 @@ pub enum Ty {
234 240
235 // Opaque (`impl Trait`) type found in a return type. 241 // Opaque (`impl Trait`) type found in a return type.
236 // Opaque(DefId, Substs), 242 // Opaque(DefId, Substs),
243 /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
244 Param {
245 /// The index of the parameter.
246 idx: u32,
247 /// The name of the parameter, for displaying.
248 name: Name,
249 },
237 250
238 // A type parameter; for example, `T` in `fn f<T>(x: T) {}
239 // Param(ParamTy),
240 /// A type variable used during type checking. Not to be confused with a 251 /// A type variable used during type checking. Not to be confused with a
241 /// type parameter. 252 /// type parameter.
242 Infer(InferTy), 253 Infer(InferTy),
@@ -250,7 +261,7 @@ pub enum Ty {
250} 261}
251 262
252/// A function signature. 263/// A function signature.
253#[derive(Clone, PartialEq, Eq, Hash, Debug)] 264#[derive(Clone, PartialEq, Eq, Debug)]
254pub struct FnSig { 265pub struct FnSig {
255 input: Vec<Ty>, 266 input: Vec<Ty>,
256 output: Ty, 267 output: Ty,
@@ -261,6 +272,7 @@ impl Ty {
261 db: &impl HirDatabase, 272 db: &impl HirDatabase,
262 module: &Module, 273 module: &Module,
263 impl_block: Option<&ImplBlock>, 274 impl_block: Option<&ImplBlock>,
275 generics: &Generics,
264 type_ref: &TypeRef, 276 type_ref: &TypeRef,
265 ) -> Self { 277 ) -> Self {
266 match type_ref { 278 match type_ref {
@@ -268,32 +280,32 @@ impl Ty {
268 TypeRef::Tuple(inner) => { 280 TypeRef::Tuple(inner) => {
269 let inner_tys = inner 281 let inner_tys = inner
270 .iter() 282 .iter()
271 .map(|tr| Ty::from_hir(db, module, impl_block, tr)) 283 .map(|tr| Ty::from_hir(db, module, impl_block, generics, tr))
272 .collect::<Vec<_>>(); 284 .collect::<Vec<_>>();
273 Ty::Tuple(inner_tys.into()) 285 Ty::Tuple(inner_tys.into())
274 } 286 }
275 TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, path), 287 TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, generics, path),
276 TypeRef::RawPtr(inner, mutability) => { 288 TypeRef::RawPtr(inner, mutability) => {
277 let inner_ty = Ty::from_hir(db, module, impl_block, inner); 289 let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner);
278 Ty::RawPtr(Arc::new(inner_ty), *mutability) 290 Ty::RawPtr(Arc::new(inner_ty), *mutability)
279 } 291 }
280 TypeRef::Array(inner) => { 292 TypeRef::Array(inner) => {
281 let inner_ty = Ty::from_hir(db, module, impl_block, inner); 293 let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner);
282 Ty::Array(Arc::new(inner_ty)) 294 Ty::Array(Arc::new(inner_ty))
283 } 295 }
284 TypeRef::Slice(inner) => { 296 TypeRef::Slice(inner) => {
285 let inner_ty = Ty::from_hir(db, module, impl_block, inner); 297 let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner);
286 Ty::Slice(Arc::new(inner_ty)) 298 Ty::Slice(Arc::new(inner_ty))
287 } 299 }
288 TypeRef::Reference(inner, mutability) => { 300 TypeRef::Reference(inner, mutability) => {
289 let inner_ty = Ty::from_hir(db, module, impl_block, inner); 301 let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner);
290 Ty::Ref(Arc::new(inner_ty), *mutability) 302 Ty::Ref(Arc::new(inner_ty), *mutability)
291 } 303 }
292 TypeRef::Placeholder => Ty::Unknown, 304 TypeRef::Placeholder => Ty::Unknown,
293 TypeRef::Fn(params) => { 305 TypeRef::Fn(params) => {
294 let mut inner_tys = params 306 let mut inner_tys = params
295 .iter() 307 .iter()
296 .map(|tr| Ty::from_hir(db, module, impl_block, tr)) 308 .map(|tr| Ty::from_hir(db, module, impl_block, generics, tr))
297 .collect::<Vec<_>>(); 309 .collect::<Vec<_>>();
298 let return_ty = inner_tys 310 let return_ty = inner_tys
299 .pop() 311 .pop()
@@ -312,15 +324,19 @@ impl Ty {
312 db: &impl HirDatabase, 324 db: &impl HirDatabase,
313 module: &Module, 325 module: &Module,
314 impl_block: Option<&ImplBlock>, 326 impl_block: Option<&ImplBlock>,
327 generics: &Generics,
315 type_ref: Option<&TypeRef>, 328 type_ref: Option<&TypeRef>,
316 ) -> Self { 329 ) -> Self {
317 type_ref.map_or(Ty::Unknown, |t| Ty::from_hir(db, module, impl_block, t)) 330 type_ref.map_or(Ty::Unknown, |t| {
331 Ty::from_hir(db, module, impl_block, generics, t)
332 })
318 } 333 }
319 334
320 pub(crate) fn from_hir_path( 335 pub(crate) fn from_hir_path(
321 db: &impl HirDatabase, 336 db: &impl HirDatabase,
322 module: &Module, 337 module: &Module,
323 impl_block: Option<&ImplBlock>, 338 impl_block: Option<&ImplBlock>,
339 generics: &Generics,
324 path: &Path, 340 path: &Path,
325 ) -> Self { 341 ) -> Self {
326 if let Some(name) = path.as_ident() { 342 if let Some(name) = path.as_ident() {
@@ -329,7 +345,15 @@ impl Ty {
329 } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) { 345 } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) {
330 return Ty::Float(float_ty); 346 return Ty::Float(float_ty);
331 } else if name.as_known_name() == Some(KnownName::SelfType) { 347 } else if name.as_known_name() == Some(KnownName::SelfType) {
332 return Ty::from_hir_opt(db, module, None, impl_block.map(|i| i.target_type())); 348 // TODO pass the impl block's generics?
349 let generics = &Generics::default();
350 return Ty::from_hir_opt(
351 db,
352 module,
353 None,
354 generics,
355 impl_block.map(|i| i.target_type()),
356 );
333 } else if let Some(known) = name.as_known_name() { 357 } else if let Some(known) = name.as_known_name() {
334 match known { 358 match known {
335 KnownName::Bool => return Ty::Bool, 359 KnownName::Bool => return Ty::Bool,
@@ -337,6 +361,11 @@ impl Ty {
337 KnownName::Str => return Ty::Str, 361 KnownName::Str => return Ty::Str,
338 _ => {} 362 _ => {}
339 } 363 }
364 } else if let Some(generic_param) = generics.find_by_name(&name) {
365 return Ty::Param {
366 idx: generic_param.idx,
367 name: generic_param.name.clone(),
368 };
340 } 369 }
341 } 370 }
342 371
@@ -374,7 +403,14 @@ impl Ty {
374 } 403 }
375 sig_mut.output.walk_mut(f); 404 sig_mut.output.walk_mut(f);
376 } 405 }
377 Ty::Adt { .. } => {} // need to walk type parameters later 406 Ty::Adt { substs, .. } => {
407 // Without an Arc::make_mut_slice, we can't avoid the clone here:
408 let mut v: Vec<_> = substs.0.iter().cloned().collect();
409 for t in &mut v {
410 t.walk_mut(f);
411 }
412 substs.0 = v.into();
413 }
378 _ => {} 414 _ => {}
379 } 415 }
380 } 416 }
@@ -394,6 +430,32 @@ impl Ty {
394 _ => None, 430 _ => None,
395 } 431 }
396 } 432 }
433
434 /// Replaces type parameters in this type using the given `Substs`. (So e.g.
435 /// if `self` is `&[T]`, where type parameter T has index 0, and the
436 /// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.)
437 pub fn subst(self, substs: &Substs) -> Ty {
438 self.fold(&mut |ty| match ty {
439 Ty::Param { idx, name } => {
440 if (idx as usize) < substs.0.len() {
441 substs.0[idx as usize].clone()
442 } else {
443 // TODO it's yet unclear to me whether we need to shift the indices here
444 Ty::Param { idx, name }
445 }
446 }
447 ty => ty,
448 })
449 }
450
451 /// Returns the type parameters of this type if it has some (i.e. is an ADT
452 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
453 fn substs(&self) -> Option<Substs> {
454 match self {
455 Ty::Adt { substs, .. } => Some(substs.clone()),
456 _ => None,
457 }
458 }
397} 459}
398 460
399impl fmt::Display for Ty { 461impl fmt::Display for Ty {
@@ -425,7 +487,17 @@ impl fmt::Display for Ty {
425 .to_fmt(f)?; 487 .to_fmt(f)?;
426 write!(f, " -> {}", sig.output) 488 write!(f, " -> {}", sig.output)
427 } 489 }
428 Ty::Adt { name, .. } => write!(f, "{}", name), 490 Ty::Adt { name, substs, .. } => {
491 write!(f, "{}", name)?;
492 if substs.0.len() > 0 {
493 join(substs.0.iter())
494 .surround_with("<", ">")
495 .separator(", ")
496 .to_fmt(f)?;
497 }
498 Ok(())
499 }
500 Ty::Param { name, .. } => write!(f, "{}", name),
429 Ty::Unknown => write!(f, "[unknown]"), 501 Ty::Unknown => write!(f, "[unknown]"),
430 Ty::Infer(..) => write!(f, "_"), 502 Ty::Infer(..) => write!(f, "_"),
431 } 503 }
@@ -440,28 +512,49 @@ fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty {
440 let signature = f.signature(db); 512 let signature = f.signature(db);
441 let module = f.module(db); 513 let module = f.module(db);
442 let impl_block = f.impl_block(db); 514 let impl_block = f.impl_block(db);
443 // TODO we ignore type parameters for now 515 let generics = f.generics(db);
444 let input = signature 516 let input = signature
445 .params() 517 .params()
446 .iter() 518 .iter()
447 .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), tr)) 519 .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), &generics, tr))
448 .collect::<Vec<_>>(); 520 .collect::<Vec<_>>();
449 let output = Ty::from_hir(db, &module, impl_block.as_ref(), signature.ret_type()); 521 let output = Ty::from_hir(
522 db,
523 &module,
524 impl_block.as_ref(),
525 &generics,
526 signature.ret_type(),
527 );
450 let sig = FnSig { input, output }; 528 let sig = FnSig { input, output };
451 Ty::FnPtr(Arc::new(sig)) 529 Ty::FnPtr(Arc::new(sig))
452} 530}
453 531
532fn make_substs(generics: &Generics) -> Substs {
533 Substs(
534 generics
535 .params
536 .iter()
537 .map(|_p| Ty::Unknown)
538 .collect::<Vec<_>>()
539 .into(),
540 )
541}
542
454fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { 543fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
544 let generics = s.generics(db);
455 Ty::Adt { 545 Ty::Adt {
456 def_id: s.def_id(), 546 def_id: s.def_id(),
457 name: s.name(db).unwrap_or_else(Name::missing), 547 name: s.name(db).unwrap_or_else(Name::missing),
548 substs: make_substs(&generics),
458 } 549 }
459} 550}
460 551
461pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { 552pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
553 let generics = s.generics(db);
462 Ty::Adt { 554 Ty::Adt {
463 def_id: s.def_id(), 555 def_id: s.def_id(),
464 name: s.name(db).unwrap_or_else(Name::missing), 556 name: s.name(db).unwrap_or_else(Name::missing),
557 substs: make_substs(&generics),
465 } 558 }
466} 559}
467 560
@@ -506,8 +599,15 @@ pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name)
506 }; 599 };
507 let module = def_id.module(db); 600 let module = def_id.module(db);
508 let impl_block = def_id.impl_block(db); 601 let impl_block = def_id.impl_block(db);
602 let generics = db.generics(def_id);
509 let type_ref = variant_data.get_field_type_ref(&field)?; 603 let type_ref = variant_data.get_field_type_ref(&field)?;
510 Some(Ty::from_hir(db, &module, impl_block.as_ref(), &type_ref)) 604 Some(Ty::from_hir(
605 db,
606 &module,
607 impl_block.as_ref(),
608 &generics,
609 &type_ref,
610 ))
511} 611}
512 612
513/// The result of type inference: A mapping from expressions and patterns to types. 613/// The result of type inference: A mapping from expressions and patterns to types.
@@ -684,8 +784,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
684 self.type_of_pat.insert(pat, ty); 784 self.type_of_pat.insert(pat, ty);
685 } 785 }
686 786
687 fn make_ty(&self, type_ref: &TypeRef) -> Ty { 787 fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
688 Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref) 788 // TODO provide generics of function
789 let generics = Generics::default();
790 let ty = Ty::from_hir(
791 self.db,
792 &self.module,
793 self.impl_block.as_ref(),
794 &generics,
795 type_ref,
796 );
797 let ty = self.insert_type_vars(ty);
798 ty
689 } 799 }
690 800
691 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { 801 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
@@ -848,7 +958,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
848 Some(ty) 958 Some(ty)
849 } 959 }
850 960
851 fn resolve_variant(&self, path: Option<&Path>) -> (Ty, Option<DefId>) { 961 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<DefId>) {
852 let path = if let Some(path) = path { 962 let path = if let Some(path) = path {
853 path 963 path
854 } else { 964 } else {
@@ -862,10 +972,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
862 match def_id.resolve(self.db) { 972 match def_id.resolve(self.db) {
863 Def::Struct(s) => { 973 Def::Struct(s) => {
864 let ty = type_for_struct(self.db, s); 974 let ty = type_for_struct(self.db, s);
975 let ty = self.insert_type_vars(ty);
865 (ty, Some(def_id)) 976 (ty, Some(def_id))
866 } 977 }
867 Def::EnumVariant(ev) => { 978 Def::EnumVariant(ev) => {
868 let ty = type_for_enum_variant(self.db, ev); 979 let ty = type_for_enum_variant(self.db, ev);
980 let ty = self.insert_type_vars(ty);
869 (ty, Some(def_id)) 981 (ty, Some(def_id))
870 } 982 }
871 _ => (Ty::Unknown, None), 983 _ => (Ty::Unknown, None),
@@ -1155,11 +1267,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1155 spread, 1267 spread,
1156 } => { 1268 } => {
1157 let (ty, def_id) = self.resolve_variant(path.as_ref()); 1269 let (ty, def_id) = self.resolve_variant(path.as_ref());
1270 let substs = ty.substs().expect("adt should have substs");
1158 for field in fields { 1271 for field in fields {
1159 let field_ty = if let Some(def_id) = def_id { 1272 let field_ty = if let Some(def_id) = def_id {
1160 self.db 1273 self.db
1161 .type_for_field(def_id, field.name.clone()) 1274 .type_for_field(def_id, field.name.clone())
1162 .unwrap_or(Ty::Unknown) 1275 .unwrap_or(Ty::Unknown)
1276 .subst(&substs)
1163 } else { 1277 } else {
1164 Ty::Unknown 1278 Ty::Unknown
1165 }; 1279 };
@@ -1180,7 +1294,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1180 let i = name.to_string().parse::<usize>().ok(); 1294 let i = name.to_string().parse::<usize>().ok();
1181 i.and_then(|i| fields.get(i).cloned()) 1295 i.and_then(|i| fields.get(i).cloned())
1182 } 1296 }
1183 Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, name.clone()), 1297 Ty::Adt {
1298 def_id, ref substs, ..
1299 } => self
1300 .db
1301 .type_for_field(def_id, name.clone())
1302 .map(|ty| ty.subst(substs)),
1184 _ => None, 1303 _ => None,
1185 }) 1304 })
1186 .unwrap_or(Ty::Unknown); 1305 .unwrap_or(Ty::Unknown);
@@ -1193,7 +1312,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1193 Expr::Cast { expr, type_ref } => { 1312 Expr::Cast { expr, type_ref } => {
1194 let _inner_ty = self.infer_expr(*expr, &Expectation::none()); 1313 let _inner_ty = self.infer_expr(*expr, &Expectation::none());
1195 let cast_ty = self.make_ty(type_ref); 1314 let cast_ty = self.make_ty(type_ref);
1196 let cast_ty = self.insert_type_vars(cast_ty);
1197 // TODO check the cast... 1315 // TODO check the cast...
1198 cast_ty 1316 cast_ty
1199 } 1317 }
@@ -1305,12 +1423,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1305 type_ref, 1423 type_ref,
1306 initializer, 1424 initializer,
1307 } => { 1425 } => {
1308 let decl_ty = Ty::from_hir_opt( 1426 let decl_ty = type_ref
1309 self.db, 1427 .as_ref()
1310 &self.module, 1428 .map(|tr| self.make_ty(tr))
1311 self.impl_block.as_ref(), 1429 .unwrap_or(Ty::Unknown);
1312 type_ref.as_ref(),
1313 );
1314 let decl_ty = self.insert_type_vars(decl_ty); 1430 let decl_ty = self.insert_type_vars(decl_ty);
1315 let ty = if let Some(expr) = initializer { 1431 let ty = if let Some(expr) = initializer {
1316 let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty)); 1432 let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty));
@@ -1338,13 +1454,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1338 let body = Arc::clone(&self.body); // avoid borrow checker problem 1454 let body = Arc::clone(&self.body); // avoid borrow checker problem
1339 for (type_ref, pat) in signature.params().iter().zip(body.params()) { 1455 for (type_ref, pat) in signature.params().iter().zip(body.params()) {
1340 let ty = self.make_ty(type_ref); 1456 let ty = self.make_ty(type_ref);
1341 let ty = self.insert_type_vars(ty);
1342 1457
1343 self.infer_pat(*pat, &ty); 1458 self.infer_pat(*pat, &ty);
1344 } 1459 }
1345 self.return_ty = { 1460 self.return_ty = {
1346 let ty = self.make_ty(signature.ret_type()); 1461 let ty = self.make_ty(signature.ret_type());
1347 let ty = self.insert_type_vars(ty);
1348 ty 1462 ty
1349 }; 1463 };
1350 } 1464 }