diff options
Diffstat (limited to 'crates/hir_ty/src/lib.rs')
-rw-r--r-- | crates/hir_ty/src/lib.rs | 173 |
1 files changed, 125 insertions, 48 deletions
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 6f9c698e6..c927ed973 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -24,9 +24,10 @@ mod tests; | |||
24 | #[cfg(test)] | 24 | #[cfg(test)] |
25 | mod test_db; | 25 | mod test_db; |
26 | 26 | ||
27 | use std::{iter, mem, ops::Deref, sync::Arc}; | 27 | use std::{iter, mem, sync::Arc}; |
28 | 28 | ||
29 | use base_db::salsa; | 29 | use base_db::salsa; |
30 | use chalk_ir::cast::{CastTo, Caster}; | ||
30 | use hir_def::{ | 31 | use hir_def::{ |
31 | builtin_type::BuiltinType, expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, | 32 | builtin_type::BuiltinType, expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, |
32 | GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId, | 33 | GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId, |
@@ -109,7 +110,7 @@ impl ProjectionTy { | |||
109 | } | 110 | } |
110 | 111 | ||
111 | pub fn self_type_parameter(&self) -> &Ty { | 112 | pub fn self_type_parameter(&self) -> &Ty { |
112 | &self.substitution[0] | 113 | &self.substitution.interned(&Interner)[0].assert_ty_ref(&Interner) |
113 | } | 114 | } |
114 | 115 | ||
115 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { | 116 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { |
@@ -324,9 +325,72 @@ impl Ty { | |||
324 | } | 325 | } |
325 | } | 326 | } |
326 | 327 | ||
328 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
329 | pub struct GenericArg { | ||
330 | interned: GenericArgData, | ||
331 | } | ||
332 | |||
333 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
334 | pub enum GenericArgData { | ||
335 | Ty(Ty), | ||
336 | } | ||
337 | |||
338 | impl GenericArg { | ||
339 | /// Constructs a generic argument using `GenericArgData`. | ||
340 | pub fn new(_interner: &Interner, data: GenericArgData) -> Self { | ||
341 | GenericArg { interned: data } | ||
342 | } | ||
343 | |||
344 | /// Gets the interned value. | ||
345 | pub fn interned(&self) -> &GenericArgData { | ||
346 | &self.interned | ||
347 | } | ||
348 | |||
349 | /// Asserts that this is a type argument. | ||
350 | pub fn assert_ty_ref(&self, interner: &Interner) -> &Ty { | ||
351 | self.ty(interner).unwrap() | ||
352 | } | ||
353 | |||
354 | /// Checks whether the generic argument is a type. | ||
355 | pub fn is_ty(&self, _interner: &Interner) -> bool { | ||
356 | match self.interned() { | ||
357 | GenericArgData::Ty(_) => true, | ||
358 | } | ||
359 | } | ||
360 | |||
361 | /// Returns the type if it is one, `None` otherwise. | ||
362 | pub fn ty(&self, _interner: &Interner) -> Option<&Ty> { | ||
363 | match self.interned() { | ||
364 | GenericArgData::Ty(t) => Some(t), | ||
365 | } | ||
366 | } | ||
367 | } | ||
368 | |||
369 | impl TypeWalk for GenericArg { | ||
370 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
371 | match &self.interned { | ||
372 | GenericArgData::Ty(ty) => { | ||
373 | ty.walk(f); | ||
374 | } | ||
375 | } | ||
376 | } | ||
377 | |||
378 | fn walk_mut_binders( | ||
379 | &mut self, | ||
380 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
381 | binders: DebruijnIndex, | ||
382 | ) { | ||
383 | match &mut self.interned { | ||
384 | GenericArgData::Ty(ty) => { | ||
385 | ty.walk_mut_binders(f, binders); | ||
386 | } | ||
387 | } | ||
388 | } | ||
389 | } | ||
390 | |||
327 | /// A list of substitutions for generic parameters. | 391 | /// A list of substitutions for generic parameters. |
328 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 392 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
329 | pub struct Substitution(SmallVec<[Ty; 2]>); | 393 | pub struct Substitution(SmallVec<[GenericArg; 2]>); |
330 | 394 | ||
331 | impl TypeWalk for Substitution { | 395 | impl TypeWalk for Substitution { |
332 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | 396 | fn walk(&self, f: &mut impl FnMut(&Ty)) { |
@@ -347,18 +411,34 @@ impl TypeWalk for Substitution { | |||
347 | } | 411 | } |
348 | 412 | ||
349 | impl Substitution { | 413 | impl Substitution { |
350 | pub fn interned(&self, _: &Interner) -> &[Ty] { | 414 | pub fn interned(&self, _: &Interner) -> &[GenericArg] { |
351 | &self.0 | 415 | &self.0 |
352 | } | 416 | } |
353 | 417 | ||
354 | pub fn empty() -> Substitution { | 418 | pub fn len(&self, _: &Interner) -> usize { |
419 | self.0.len() | ||
420 | } | ||
421 | |||
422 | pub fn is_empty(&self, _: &Interner) -> bool { | ||
423 | self.0.is_empty() | ||
424 | } | ||
425 | |||
426 | pub fn at(&self, _: &Interner, i: usize) -> &GenericArg { | ||
427 | &self.0[i] | ||
428 | } | ||
429 | |||
430 | pub fn empty(_: &Interner) -> Substitution { | ||
355 | Substitution(SmallVec::new()) | 431 | Substitution(SmallVec::new()) |
356 | } | 432 | } |
357 | 433 | ||
434 | pub fn iter(&self, _: &Interner) -> std::slice::Iter<'_, GenericArg> { | ||
435 | self.0.iter() | ||
436 | } | ||
437 | |||
358 | pub fn single(ty: Ty) -> Substitution { | 438 | pub fn single(ty: Ty) -> Substitution { |
359 | Substitution({ | 439 | Substitution({ |
360 | let mut v = SmallVec::new(); | 440 | let mut v = SmallVec::new(); |
361 | v.push(ty); | 441 | v.push(ty.cast(&Interner)); |
362 | v | 442 | v |
363 | }) | 443 | }) |
364 | } | 444 | } |
@@ -371,15 +451,11 @@ impl Substitution { | |||
371 | Substitution(self.0[self.0.len() - std::cmp::min(self.0.len(), n)..].into()) | 451 | Substitution(self.0[self.0.len() - std::cmp::min(self.0.len(), n)..].into()) |
372 | } | 452 | } |
373 | 453 | ||
374 | pub fn as_single(&self) -> &Ty { | 454 | pub fn from_iter( |
375 | if self.0.len() != 1 { | 455 | interner: &Interner, |
376 | panic!("expected substs of len 1, got {:?}", self); | 456 | elements: impl IntoIterator<Item = impl CastTo<GenericArg>>, |
377 | } | 457 | ) -> Self { |
378 | &self.0[0] | 458 | Substitution(elements.into_iter().casted(interner).collect()) |
379 | } | ||
380 | |||
381 | pub fn from_iter(_interner: &Interner, elements: impl IntoIterator<Item = Ty>) -> Self { | ||
382 | Substitution(elements.into_iter().collect()) | ||
383 | } | 459 | } |
384 | 460 | ||
385 | /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). | 461 | /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). |
@@ -387,11 +463,11 @@ impl Substitution { | |||
387 | db: &dyn HirDatabase, | 463 | db: &dyn HirDatabase, |
388 | generic_params: &Generics, | 464 | generic_params: &Generics, |
389 | ) -> Substitution { | 465 | ) -> Substitution { |
390 | Substitution( | 466 | Substitution::from_iter( |
467 | &Interner, | ||
391 | generic_params | 468 | generic_params |
392 | .iter() | 469 | .iter() |
393 | .map(|(id, _)| TyKind::Placeholder(to_placeholder_idx(db, id)).intern(&Interner)) | 470 | .map(|(id, _)| TyKind::Placeholder(to_placeholder_idx(db, id)).intern(&Interner)), |
394 | .collect(), | ||
395 | ) | 471 | ) |
396 | } | 472 | } |
397 | 473 | ||
@@ -403,12 +479,12 @@ impl Substitution { | |||
403 | 479 | ||
404 | /// Return Substs that replace each parameter by a bound variable. | 480 | /// Return Substs that replace each parameter by a bound variable. |
405 | pub(crate) fn bound_vars(generic_params: &Generics, debruijn: DebruijnIndex) -> Substitution { | 481 | pub(crate) fn bound_vars(generic_params: &Generics, debruijn: DebruijnIndex) -> Substitution { |
406 | Substitution( | 482 | Substitution::from_iter( |
483 | &Interner, | ||
407 | generic_params | 484 | generic_params |
408 | .iter() | 485 | .iter() |
409 | .enumerate() | 486 | .enumerate() |
410 | .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)) | 487 | .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)), |
411 | .collect(), | ||
412 | ) | 488 | ) |
413 | } | 489 | } |
414 | 490 | ||
@@ -435,18 +511,18 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> { | |||
435 | 511 | ||
436 | #[derive(Debug, Clone)] | 512 | #[derive(Debug, Clone)] |
437 | pub struct SubstsBuilder { | 513 | pub struct SubstsBuilder { |
438 | vec: Vec<Ty>, | 514 | vec: Vec<GenericArg>, |
439 | param_count: usize, | 515 | param_count: usize, |
440 | } | 516 | } |
441 | 517 | ||
442 | impl SubstsBuilder { | 518 | impl SubstsBuilder { |
443 | pub fn build(self) -> Substitution { | 519 | pub fn build(self) -> Substitution { |
444 | assert_eq!(self.vec.len(), self.param_count); | 520 | assert_eq!(self.vec.len(), self.param_count); |
445 | Substitution(self.vec.into()) | 521 | Substitution::from_iter(&Interner, self.vec) |
446 | } | 522 | } |
447 | 523 | ||
448 | pub fn push(mut self, ty: Ty) -> Self { | 524 | pub fn push(mut self, ty: impl CastTo<GenericArg>) -> Self { |
449 | self.vec.push(ty); | 525 | self.vec.push(ty.cast(&Interner)); |
450 | self | 526 | self |
451 | } | 527 | } |
452 | 528 | ||
@@ -465,28 +541,20 @@ impl SubstsBuilder { | |||
465 | self.fill(iter::repeat(TyKind::Unknown.intern(&Interner))) | 541 | self.fill(iter::repeat(TyKind::Unknown.intern(&Interner))) |
466 | } | 542 | } |
467 | 543 | ||
468 | pub fn fill(mut self, filler: impl Iterator<Item = Ty>) -> Self { | 544 | pub fn fill(mut self, filler: impl Iterator<Item = impl CastTo<GenericArg>>) -> Self { |
469 | self.vec.extend(filler.take(self.remaining())); | 545 | self.vec.extend(filler.take(self.remaining()).casted(&Interner)); |
470 | assert_eq!(self.remaining(), 0); | 546 | assert_eq!(self.remaining(), 0); |
471 | self | 547 | self |
472 | } | 548 | } |
473 | 549 | ||
474 | pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self { | 550 | pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self { |
475 | assert!(self.vec.is_empty()); | 551 | assert!(self.vec.is_empty()); |
476 | assert!(parent_substs.len() <= self.param_count); | 552 | assert!(parent_substs.len(&Interner) <= self.param_count); |
477 | self.vec.extend(parent_substs.iter().cloned()); | 553 | self.vec.extend(parent_substs.iter(&Interner).cloned()); |
478 | self | 554 | self |
479 | } | 555 | } |
480 | } | 556 | } |
481 | 557 | ||
482 | impl Deref for Substitution { | ||
483 | type Target = [Ty]; | ||
484 | |||
485 | fn deref(&self) -> &[Ty] { | ||
486 | &self.0 | ||
487 | } | ||
488 | } | ||
489 | |||
490 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] | 558 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] |
491 | pub struct Binders<T> { | 559 | pub struct Binders<T> { |
492 | pub num_binders: usize, | 560 | pub num_binders: usize, |
@@ -535,7 +603,7 @@ impl<T: Clone> Binders<&T> { | |||
535 | impl<T: TypeWalk> Binders<T> { | 603 | impl<T: TypeWalk> Binders<T> { |
536 | /// Substitutes all variables. | 604 | /// Substitutes all variables. |
537 | pub fn subst(self, subst: &Substitution) -> T { | 605 | pub fn subst(self, subst: &Substitution) -> T { |
538 | assert_eq!(subst.len(), self.num_binders); | 606 | assert_eq!(subst.len(&Interner), self.num_binders); |
539 | self.value.subst_bound_vars(subst) | 607 | self.value.subst_bound_vars(subst) |
540 | } | 608 | } |
541 | } | 609 | } |
@@ -563,7 +631,7 @@ pub struct TraitRef { | |||
563 | 631 | ||
564 | impl TraitRef { | 632 | impl TraitRef { |
565 | pub fn self_type_parameter(&self) -> &Ty { | 633 | pub fn self_type_parameter(&self) -> &Ty { |
566 | &self.substitution[0] | 634 | &self.substitution.at(&Interner, 0).assert_ty_ref(&Interner) |
567 | } | 635 | } |
568 | 636 | ||
569 | pub fn hir_trait_id(&self) -> TraitId { | 637 | pub fn hir_trait_id(&self) -> TraitId { |
@@ -699,14 +767,20 @@ impl CallableSig { | |||
699 | .shift_bound_vars_out(DebruijnIndex::ONE) | 767 | .shift_bound_vars_out(DebruijnIndex::ONE) |
700 | .interned(&Interner) | 768 | .interned(&Interner) |
701 | .iter() | 769 | .iter() |
702 | .cloned() | 770 | .map(|arg| arg.assert_ty_ref(&Interner).clone()) |
703 | .collect(), | 771 | .collect(), |
704 | is_varargs: fn_ptr.sig.variadic, | 772 | is_varargs: fn_ptr.sig.variadic, |
705 | } | 773 | } |
706 | } | 774 | } |
707 | 775 | ||
708 | pub fn from_substs(substs: &Substitution) -> CallableSig { | 776 | pub fn from_substs(substs: &Substitution) -> CallableSig { |
709 | CallableSig { params_and_return: substs.iter().cloned().collect(), is_varargs: false } | 777 | CallableSig { |
778 | params_and_return: substs | ||
779 | .iter(&Interner) | ||
780 | .map(|arg| arg.assert_ty_ref(&Interner).clone()) | ||
781 | .collect(), | ||
782 | is_varargs: false, | ||
783 | } | ||
710 | } | 784 | } |
711 | 785 | ||
712 | pub fn params(&self) -> &[Ty] { | 786 | pub fn params(&self) -> &[Ty] { |
@@ -738,7 +812,7 @@ impl TypeWalk for CallableSig { | |||
738 | 812 | ||
739 | impl Ty { | 813 | impl Ty { |
740 | pub fn unit() -> Self { | 814 | pub fn unit() -> Self { |
741 | TyKind::Tuple(0, Substitution::empty()).intern(&Interner) | 815 | TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner) |
742 | } | 816 | } |
743 | 817 | ||
744 | pub fn adt_ty(adt: hir_def::AdtId, substs: Substitution) -> Ty { | 818 | pub fn adt_ty(adt: hir_def::AdtId, substs: Substitution) -> Ty { |
@@ -908,7 +982,7 @@ impl Ty { | |||
908 | Some(sig.subst(¶meters)) | 982 | Some(sig.subst(¶meters)) |
909 | } | 983 | } |
910 | TyKind::Closure(.., substs) => { | 984 | TyKind::Closure(.., substs) => { |
911 | let sig_param = &substs[0]; | 985 | let sig_param = substs.at(&Interner, 0).assert_ty_ref(&Interner); |
912 | sig_param.callable_sig(db) | 986 | sig_param.callable_sig(db) |
913 | } | 987 | } |
914 | _ => None, | 988 | _ => None, |
@@ -960,7 +1034,7 @@ impl Ty { | |||
960 | 0, | 1034 | 0, |
961 | WhereClause::Implemented(TraitRef { | 1035 | WhereClause::Implemented(TraitRef { |
962 | trait_id: to_chalk_trait_id(future_trait), | 1036 | trait_id: to_chalk_trait_id(future_trait), |
963 | substitution: Substitution::empty(), | 1037 | substitution: Substitution::empty(&Interner), |
964 | }), | 1038 | }), |
965 | ); | 1039 | ); |
966 | Some(vec![impl_bound]) | 1040 | Some(vec![impl_bound]) |
@@ -1109,7 +1183,10 @@ pub trait TypeWalk { | |||
1109 | &mut |ty, binders| { | 1183 | &mut |ty, binders| { |
1110 | if let &mut TyKind::BoundVar(bound) = ty.interned_mut() { | 1184 | if let &mut TyKind::BoundVar(bound) = ty.interned_mut() { |
1111 | if bound.debruijn >= binders { | 1185 | if bound.debruijn >= binders { |
1112 | *ty = substs.0[bound.index].clone().shift_bound_vars(binders); | 1186 | *ty = substs.0[bound.index] |
1187 | .assert_ty_ref(&Interner) | ||
1188 | .clone() | ||
1189 | .shift_bound_vars(binders); | ||
1113 | } | 1190 | } |
1114 | } | 1191 | } |
1115 | }, | 1192 | }, |
@@ -1156,12 +1233,12 @@ impl TypeWalk for Ty { | |||
1156 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | 1233 | fn walk(&self, f: &mut impl FnMut(&Ty)) { |
1157 | match self.interned(&Interner) { | 1234 | match self.interned(&Interner) { |
1158 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | 1235 | TyKind::Alias(AliasTy::Projection(p_ty)) => { |
1159 | for t in p_ty.substitution.iter() { | 1236 | for t in p_ty.substitution.iter(&Interner) { |
1160 | t.walk(f); | 1237 | t.walk(f); |
1161 | } | 1238 | } |
1162 | } | 1239 | } |
1163 | TyKind::Alias(AliasTy::Opaque(o_ty)) => { | 1240 | TyKind::Alias(AliasTy::Opaque(o_ty)) => { |
1164 | for t in o_ty.substitution.iter() { | 1241 | for t in o_ty.substitution.iter(&Interner) { |
1165 | t.walk(f); | 1242 | t.walk(f); |
1166 | } | 1243 | } |
1167 | } | 1244 | } |
@@ -1175,7 +1252,7 @@ impl TypeWalk for Ty { | |||
1175 | } | 1252 | } |
1176 | _ => { | 1253 | _ => { |
1177 | if let Some(substs) = self.substs() { | 1254 | if let Some(substs) = self.substs() { |
1178 | for t in substs.iter() { | 1255 | for t in substs.iter(&Interner) { |
1179 | t.walk(f); | 1256 | t.walk(f); |
1180 | } | 1257 | } |
1181 | } | 1258 | } |