diff options
Diffstat (limited to 'crates/hir_ty')
-rw-r--r-- | crates/hir_ty/src/autoderef.rs | 6 | ||||
-rw-r--r-- | crates/hir_ty/src/builder.rs | 4 | ||||
-rw-r--r-- | crates/hir_ty/src/db.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/display.rs | 20 | ||||
-rw-r--r-- | crates/hir_ty/src/infer.rs | 4 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/coerce.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 12 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/pat.rs | 4 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/path.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/lib.rs | 697 | ||||
-rw-r--r-- | crates/hir_ty/src/method_resolution.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/traits.rs | 88 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk/mapping.rs | 18 | ||||
-rw-r--r-- | crates/hir_ty/src/types.rs | 416 | ||||
-rw-r--r-- | crates/hir_ty/src/walk.rs | 381 |
16 files changed, 850 insertions, 810 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index 70c56cc45..7ca4af80e 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs | |||
@@ -12,10 +12,8 @@ use hir_expand::name::name; | |||
12 | use log::{info, warn}; | 12 | use log::{info, warn}; |
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | db::HirDatabase, | 15 | db::HirDatabase, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, |
16 | traits::{InEnvironment, Solution}, | 16 | InEnvironment, Interner, Solution, Ty, TyBuilder, TyKind, |
17 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, Ty, | ||
18 | TyBuilder, TyKind, | ||
19 | }; | 17 | }; |
20 | 18 | ||
21 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 19 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs index 4a9a8058f..0bac31e4c 100644 --- a/crates/hir_ty/src/builder.rs +++ b/crates/hir_ty/src/builder.rs | |||
@@ -33,7 +33,7 @@ impl<D> TyBuilder<D> { | |||
33 | fn build_internal(self) -> (D, Substitution) { | 33 | fn build_internal(self) -> (D, Substitution) { |
34 | assert_eq!(self.vec.len(), self.param_count); | 34 | assert_eq!(self.vec.len(), self.param_count); |
35 | // FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form | 35 | // FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form |
36 | let subst = Substitution(self.vec); | 36 | let subst = Substitution::intern(self.vec); |
37 | (self.data, subst) | 37 | (self.data, subst) |
38 | } | 38 | } |
39 | 39 | ||
@@ -138,7 +138,7 @@ impl TyBuilder<hir_def::AdtId> { | |||
138 | self.vec.push(fallback().cast(&Interner)); | 138 | self.vec.push(fallback().cast(&Interner)); |
139 | } else { | 139 | } else { |
140 | // each default can depend on the previous parameters | 140 | // each default can depend on the previous parameters |
141 | let subst_so_far = Substitution(self.vec.clone()); | 141 | let subst_so_far = Substitution::intern(self.vec.clone()); |
142 | self.vec.push(default_ty.clone().subst(&subst_so_far).cast(&Interner)); | 142 | self.vec.push(default_ty.clone().subst(&subst_so_far).cast(&Interner)); |
143 | } | 143 | } |
144 | } | 144 | } |
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index 58e4247c6..4300680d9 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs | |||
@@ -123,7 +123,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
123 | &self, | 123 | &self, |
124 | krate: CrateId, | 124 | krate: CrateId, |
125 | goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, | 125 | goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, |
126 | ) -> Option<crate::traits::Solution>; | 126 | ) -> Option<crate::Solution>; |
127 | 127 | ||
128 | #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] | 128 | #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] |
129 | fn program_clauses_for_chalk_env( | 129 | fn program_clauses_for_chalk_env( |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 385bd9405..148eb7506 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -260,7 +260,7 @@ impl HirDisplay for ProjectionTy { | |||
260 | write!(f, "<{} as {}", first_parameter, trait_.name)?; | 260 | write!(f, "<{} as {}", first_parameter, trait_.name)?; |
261 | if self.substitution.len(&Interner) > 1 { | 261 | if self.substitution.len(&Interner) > 1 { |
262 | write!(f, "<")?; | 262 | write!(f, "<")?; |
263 | f.write_joined(&self.substitution.interned(&Interner)[1..], ", ")?; | 263 | f.write_joined(&self.substitution.interned()[1..], ", ")?; |
264 | write!(f, ">")?; | 264 | write!(f, ">")?; |
265 | } | 265 | } |
266 | write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?; | 266 | write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?; |
@@ -387,7 +387,7 @@ impl HirDisplay for Ty { | |||
387 | write!(f, ",)")?; | 387 | write!(f, ",)")?; |
388 | } else { | 388 | } else { |
389 | write!(f, "(")?; | 389 | write!(f, "(")?; |
390 | f.write_joined(&*substs.0, ", ")?; | 390 | f.write_joined(&*substs.interned(), ", ")?; |
391 | write!(f, ")")?; | 391 | write!(f, ")")?; |
392 | } | 392 | } |
393 | } | 393 | } |
@@ -415,7 +415,7 @@ impl HirDisplay for Ty { | |||
415 | // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? | 415 | // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? |
416 | if total_len > 0 { | 416 | if total_len > 0 { |
417 | write!(f, "<")?; | 417 | write!(f, "<")?; |
418 | f.write_joined(¶meters.0[..total_len], ", ")?; | 418 | f.write_joined(¶meters.interned()[..total_len], ", ")?; |
419 | write!(f, ">")?; | 419 | write!(f, ">")?; |
420 | } | 420 | } |
421 | } | 421 | } |
@@ -468,7 +468,7 @@ impl HirDisplay for Ty { | |||
468 | .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) | 468 | .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) |
469 | .filter(|defaults| !defaults.is_empty()) | 469 | .filter(|defaults| !defaults.is_empty()) |
470 | { | 470 | { |
471 | None => parameters.0.as_ref(), | 471 | None => parameters.interned().as_ref(), |
472 | Some(default_parameters) => { | 472 | Some(default_parameters) => { |
473 | let mut default_from = 0; | 473 | let mut default_from = 0; |
474 | for (i, parameter) in parameters.iter(&Interner).enumerate() { | 474 | for (i, parameter) in parameters.iter(&Interner).enumerate() { |
@@ -490,11 +490,11 @@ impl HirDisplay for Ty { | |||
490 | } | 490 | } |
491 | } | 491 | } |
492 | } | 492 | } |
493 | ¶meters.0[0..default_from] | 493 | ¶meters.interned()[0..default_from] |
494 | } | 494 | } |
495 | } | 495 | } |
496 | } else { | 496 | } else { |
497 | parameters.0.as_ref() | 497 | parameters.interned().as_ref() |
498 | }; | 498 | }; |
499 | if !parameters_to_write.is_empty() { | 499 | if !parameters_to_write.is_empty() { |
500 | write!(f, "<")?; | 500 | write!(f, "<")?; |
@@ -517,7 +517,7 @@ impl HirDisplay for Ty { | |||
517 | write!(f, "{}::{}", trait_.name, type_alias_data.name)?; | 517 | write!(f, "{}::{}", trait_.name, type_alias_data.name)?; |
518 | if parameters.len(&Interner) > 0 { | 518 | if parameters.len(&Interner) > 0 { |
519 | write!(f, "<")?; | 519 | write!(f, "<")?; |
520 | f.write_joined(&*parameters.0, ", ")?; | 520 | f.write_joined(&*parameters.interned(), ", ")?; |
521 | write!(f, ">")?; | 521 | write!(f, ">")?; |
522 | } | 522 | } |
523 | } else { | 523 | } else { |
@@ -727,13 +727,13 @@ fn write_bounds_like_dyn_trait( | |||
727 | // existential) here, which is the only thing that's | 727 | // existential) here, which is the only thing that's |
728 | // possible in actual Rust, and hence don't print it | 728 | // possible in actual Rust, and hence don't print it |
729 | write!(f, "{}", f.db.trait_data(trait_).name)?; | 729 | write!(f, "{}", f.db.trait_data(trait_).name)?; |
730 | if let [_, params @ ..] = &*trait_ref.substitution.0 { | 730 | if let [_, params @ ..] = &*trait_ref.substitution.interned() { |
731 | if is_fn_trait { | 731 | if is_fn_trait { |
732 | if let Some(args) = | 732 | if let Some(args) = |
733 | params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple()) | 733 | params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple()) |
734 | { | 734 | { |
735 | write!(f, "(")?; | 735 | write!(f, "(")?; |
736 | f.write_joined(&*args.0, ", ")?; | 736 | f.write_joined(&*args.interned(), ", ")?; |
737 | write!(f, ")")?; | 737 | write!(f, ")")?; |
738 | } | 738 | } |
739 | } else if !params.is_empty() { | 739 | } else if !params.is_empty() { |
@@ -789,7 +789,7 @@ impl TraitRef { | |||
789 | write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?; | 789 | write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?; |
790 | if self.substitution.len(&Interner) > 1 { | 790 | if self.substitution.len(&Interner) > 1 { |
791 | write!(f, "<")?; | 791 | write!(f, "<")?; |
792 | f.write_joined(&self.substitution.interned(&Interner)[1..], ", ")?; | 792 | f.write_joined(&self.substitution.interned()[1..], ", ")?; |
793 | write!(f, ">")?; | 793 | write!(f, ">")?; |
794 | } | 794 | } |
795 | Ok(()) | 795 | Ok(()) |
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 1b1d4458c..bb885db35 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -37,8 +37,8 @@ use stdx::impl_from; | |||
37 | use syntax::SmolStr; | 37 | use syntax::SmolStr; |
38 | 38 | ||
39 | use super::{ | 39 | use super::{ |
40 | traits::{DomainGoal, Guidance, Solution}, | 40 | DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty, |
41 | InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeWalk, | 41 | TypeWalk, |
42 | }; | 42 | }; |
43 | use crate::{ | 43 | use crate::{ |
44 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, | 44 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, |
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 028a4d568..32c273afc 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -7,7 +7,7 @@ | |||
7 | use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; | 7 | use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; |
8 | use hir_def::lang_item::LangItemTarget; | 8 | use hir_def::lang_item::LangItemTarget; |
9 | 9 | ||
10 | use crate::{autoderef, traits::Solution, Interner, Ty, TyBuilder, TyKind}; | 10 | use crate::{autoderef, Interner, Solution, Ty, TyBuilder, TyKind}; |
11 | 11 | ||
12 | use super::{InEnvironment, InferenceContext}; | 12 | use super::{InEnvironment, InferenceContext}; |
13 | 13 | ||
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index c584a2c08..ccaae53e9 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -20,10 +20,10 @@ use crate::{ | |||
20 | method_resolution, op, | 20 | method_resolution, op, |
21 | primitive::{self, UintTy}, | 21 | primitive::{self, UintTy}, |
22 | to_chalk_trait_id, | 22 | to_chalk_trait_id, |
23 | traits::{chalk::from_chalk, FnTrait, InEnvironment}, | 23 | traits::{chalk::from_chalk, FnTrait}, |
24 | utils::{generics, variant_data, Generics}, | 24 | utils::{generics, variant_data, Generics}, |
25 | AdtId, Binders, CallableDefId, FnPointer, FnSig, Interner, Rawness, Scalar, Substitution, | 25 | AdtId, Binders, CallableDefId, FnPointer, FnSig, InEnvironment, Interner, Rawness, Scalar, |
26 | TraitRef, Ty, TyBuilder, TyKind, | 26 | Substitution, TraitRef, Ty, TyBuilder, TyKind, |
27 | }; | 27 | }; |
28 | 28 | ||
29 | use super::{ | 29 | use super::{ |
@@ -452,11 +452,7 @@ impl<'a> InferenceContext<'a> { | |||
452 | }; | 452 | }; |
453 | match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) { | 453 | match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) { |
454 | TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| { | 454 | TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| { |
455 | substs | 455 | substs.interned().get(idx).map(|a| a.assert_ty_ref(&Interner)).cloned() |
456 | .interned(&Interner) | ||
457 | .get(idx) | ||
458 | .map(|a| a.assert_ty_ref(&Interner)) | ||
459 | .cloned() | ||
460 | }), | 456 | }), |
461 | TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { | 457 | TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { |
462 | let local_id = self.db.struct_data(*s).variant_data.field(name)?; | 458 | let local_id = self.db.struct_data(*s).variant_data.field(name)?; |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index 5b70d5e5a..469f37dd9 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -123,7 +123,7 @@ impl<'a> InferenceContext<'a> { | |||
123 | let ty = match &body[pat] { | 123 | let ty = match &body[pat] { |
124 | &Pat::Tuple { ref args, ellipsis } => { | 124 | &Pat::Tuple { ref args, ellipsis } => { |
125 | let expectations = match expected.as_tuple() { | 125 | let expectations = match expected.as_tuple() { |
126 | Some(parameters) => &*parameters.0, | 126 | Some(parameters) => &*parameters.interned(), |
127 | _ => &[], | 127 | _ => &[], |
128 | }; | 128 | }; |
129 | 129 | ||
@@ -239,7 +239,7 @@ impl<'a> InferenceContext<'a> { | |||
239 | let (inner_ty, alloc_ty) = match expected.as_adt() { | 239 | let (inner_ty, alloc_ty) = match expected.as_adt() { |
240 | Some((adt, subst)) if adt == box_adt => ( | 240 | Some((adt, subst)) if adt == box_adt => ( |
241 | subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(), | 241 | subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(), |
242 | subst.interned(&Interner).get(1).and_then(|a| a.ty(&Interner).cloned()), | 242 | subst.interned().get(1).and_then(|a| a.ty(&Interner).cloned()), |
243 | ), | 243 | ), |
244 | _ => (self.result.standard_types.unknown.clone(), None), | 244 | _ => (self.result.standard_types.unknown.clone(), None), |
245 | }; | 245 | }; |
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index 671ea355f..637341b53 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs | |||
@@ -98,7 +98,7 @@ impl<'a> InferenceContext<'a> { | |||
98 | let substs = ctx.substs_from_path(path, typable, true); | 98 | let substs = ctx.substs_from_path(path, typable, true); |
99 | let ty = TyBuilder::value_ty(self.db, typable) | 99 | let ty = TyBuilder::value_ty(self.db, typable) |
100 | .use_parent_substs(&parent_substs) | 100 | .use_parent_substs(&parent_substs) |
101 | .fill(substs.interned(&Interner)[parent_substs.len(&Interner)..].iter().cloned()) | 101 | .fill(substs.interned()[parent_substs.len(&Interner)..].iter().cloned()) |
102 | .build(); | 102 | .build(); |
103 | Some(ty) | 103 | Some(ty) |
104 | } | 104 | } |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index a04b935ef..b7bc48569 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -284,7 +284,7 @@ impl InferenceTable { | |||
284 | substs2: &Substitution, | 284 | substs2: &Substitution, |
285 | depth: usize, | 285 | depth: usize, |
286 | ) -> bool { | 286 | ) -> bool { |
287 | substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| { | 287 | substs1.iter(&Interner).zip(substs2.iter(&Interner)).all(|(t1, t2)| { |
288 | self.unify_inner(t1.assert_ty_ref(&Interner), t2.assert_ty_ref(&Interner), depth) | 288 | self.unify_inner(t1.assert_ty_ref(&Interner), t2.assert_ty_ref(&Interner), depth) |
289 | }) | 289 | }) |
290 | } | 290 | } |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index a8c87eadf..76609e2df 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -16,6 +16,8 @@ pub(crate) mod utils; | |||
16 | mod chalk_cast; | 16 | mod chalk_cast; |
17 | mod chalk_ext; | 17 | mod chalk_ext; |
18 | mod builder; | 18 | mod builder; |
19 | mod walk; | ||
20 | mod types; | ||
19 | 21 | ||
20 | pub mod display; | 22 | pub mod display; |
21 | pub mod db; | 23 | pub mod db; |
@@ -26,23 +28,18 @@ mod tests; | |||
26 | #[cfg(test)] | 28 | #[cfg(test)] |
27 | mod test_db; | 29 | mod test_db; |
28 | 30 | ||
29 | use std::{mem, sync::Arc}; | 31 | use std::sync::Arc; |
30 | 32 | ||
31 | use chalk_ir::cast::{CastTo, Caster}; | ||
32 | use itertools::Itertools; | 33 | use itertools::Itertools; |
33 | use smallvec::SmallVec; | 34 | use smallvec::SmallVec; |
34 | 35 | ||
35 | use base_db::salsa; | 36 | use base_db::salsa; |
36 | use hir_def::{ | 37 | use hir_def::{ |
37 | expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, | 38 | expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, Lookup, |
38 | LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId, | 39 | TraitId, TypeAliasId, TypeParamId, |
39 | }; | 40 | }; |
40 | 41 | ||
41 | use crate::{ | 42 | use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; |
42 | db::HirDatabase, | ||
43 | display::HirDisplay, | ||
44 | utils::{generics, make_mut_slice}, | ||
45 | }; | ||
46 | 43 | ||
47 | pub use autoderef::autoderef; | 44 | pub use autoderef::autoderef; |
48 | pub use builder::TyBuilder; | 45 | pub use builder::TyBuilder; |
@@ -52,7 +49,9 @@ pub use lower::{ | |||
52 | associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, | 49 | associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, |
53 | TyDefId, TyLoweringContext, ValueTyDefId, | 50 | TyDefId, TyLoweringContext, ValueTyDefId, |
54 | }; | 51 | }; |
55 | pub use traits::{AliasEq, DomainGoal, InEnvironment, TraitEnvironment}; | 52 | pub use traits::TraitEnvironment; |
53 | pub use types::*; | ||
54 | pub use walk::TypeWalk; | ||
56 | 55 | ||
57 | pub use chalk_ir::{ | 56 | pub use chalk_ir::{ |
58 | cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, | 57 | cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, |
@@ -71,41 +70,6 @@ pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>; | |||
71 | 70 | ||
72 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; | 71 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; |
73 | 72 | ||
74 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
75 | pub enum Lifetime { | ||
76 | Parameter(LifetimeParamId), | ||
77 | Static, | ||
78 | } | ||
79 | |||
80 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
81 | pub struct OpaqueTy { | ||
82 | pub opaque_ty_id: OpaqueTyId, | ||
83 | pub substitution: Substitution, | ||
84 | } | ||
85 | |||
86 | impl TypeWalk for OpaqueTy { | ||
87 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
88 | self.substitution.walk(f); | ||
89 | } | ||
90 | |||
91 | fn walk_mut_binders( | ||
92 | &mut self, | ||
93 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
94 | binders: DebruijnIndex, | ||
95 | ) { | ||
96 | self.substitution.walk_mut_binders(f, binders); | ||
97 | } | ||
98 | } | ||
99 | |||
100 | /// A "projection" type corresponds to an (unnormalized) | ||
101 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the | ||
102 | /// trait and all its parameters are fully known. | ||
103 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
104 | pub struct ProjectionTy { | ||
105 | pub associated_ty_id: AssocTypeId, | ||
106 | pub substitution: Substitution, | ||
107 | } | ||
108 | |||
109 | impl ProjectionTy { | 73 | impl ProjectionTy { |
110 | pub fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef { | 74 | pub fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef { |
111 | TraitRef { | 75 | TraitRef { |
@@ -115,7 +79,7 @@ impl ProjectionTy { | |||
115 | } | 79 | } |
116 | 80 | ||
117 | pub fn self_type_parameter(&self) -> &Ty { | 81 | pub fn self_type_parameter(&self) -> &Ty { |
118 | &self.substitution.interned(&Interner)[0].assert_ty_ref(&Interner) | 82 | &self.substitution.interned()[0].assert_ty_ref(&Interner) |
119 | } | 83 | } |
120 | 84 | ||
121 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { | 85 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { |
@@ -126,322 +90,11 @@ impl ProjectionTy { | |||
126 | } | 90 | } |
127 | } | 91 | } |
128 | 92 | ||
129 | impl TypeWalk for ProjectionTy { | ||
130 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
131 | self.substitution.walk(f); | ||
132 | } | ||
133 | |||
134 | fn walk_mut_binders( | ||
135 | &mut self, | ||
136 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
137 | binders: DebruijnIndex, | ||
138 | ) { | ||
139 | self.substitution.walk_mut_binders(f, binders); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
144 | pub struct DynTy { | ||
145 | /// The unknown self type. | ||
146 | pub bounds: Binders<QuantifiedWhereClauses>, | ||
147 | } | ||
148 | |||
149 | pub type FnSig = chalk_ir::FnSig<Interner>; | 93 | pub type FnSig = chalk_ir::FnSig<Interner>; |
150 | 94 | ||
151 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
152 | pub struct FnPointer { | ||
153 | pub num_args: usize, | ||
154 | pub sig: FnSig, | ||
155 | pub substs: Substitution, | ||
156 | } | ||
157 | |||
158 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
159 | pub enum AliasTy { | ||
160 | /// A "projection" type corresponds to an (unnormalized) | ||
161 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the | ||
162 | /// trait and all its parameters are fully known. | ||
163 | Projection(ProjectionTy), | ||
164 | /// An opaque type (`impl Trait`). | ||
165 | /// | ||
166 | /// This is currently only used for return type impl trait; each instance of | ||
167 | /// `impl Trait` in a return type gets its own ID. | ||
168 | Opaque(OpaqueTy), | ||
169 | } | ||
170 | |||
171 | impl TypeWalk for AliasTy { | ||
172 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
173 | match self { | ||
174 | AliasTy::Projection(it) => it.walk(f), | ||
175 | AliasTy::Opaque(it) => it.walk(f), | ||
176 | } | ||
177 | } | ||
178 | |||
179 | fn walk_mut_binders( | ||
180 | &mut self, | ||
181 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
182 | binders: DebruijnIndex, | ||
183 | ) { | ||
184 | match self { | ||
185 | AliasTy::Projection(it) => it.walk_mut_binders(f, binders), | ||
186 | AliasTy::Opaque(it) => it.walk_mut_binders(f, binders), | ||
187 | } | ||
188 | } | ||
189 | } | ||
190 | /// A type. | ||
191 | /// | ||
192 | /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents | ||
193 | /// the same thing (but in a different way). | ||
194 | /// | ||
195 | /// This should be cheap to clone. | ||
196 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
197 | pub enum TyKind { | ||
198 | /// Structures, enumerations and unions. | ||
199 | Adt(AdtId<Interner>, Substitution), | ||
200 | |||
201 | /// Represents an associated item like `Iterator::Item`. This is used | ||
202 | /// when we have tried to normalize a projection like `T::Item` but | ||
203 | /// couldn't find a better representation. In that case, we generate | ||
204 | /// an **application type** like `(Iterator::Item)<T>`. | ||
205 | AssociatedType(AssocTypeId, Substitution), | ||
206 | |||
207 | /// a scalar type like `bool` or `u32` | ||
208 | Scalar(Scalar), | ||
209 | |||
210 | /// A tuple type. For example, `(i32, bool)`. | ||
211 | Tuple(usize, Substitution), | ||
212 | |||
213 | /// An array with the given length. Written as `[T; n]`. | ||
214 | Array(Ty), | ||
215 | |||
216 | /// The pointee of an array slice. Written as `[T]`. | ||
217 | Slice(Ty), | ||
218 | |||
219 | /// A raw pointer. Written as `*mut T` or `*const T` | ||
220 | Raw(Mutability, Ty), | ||
221 | |||
222 | /// A reference; a pointer with an associated lifetime. Written as | ||
223 | /// `&'a mut T` or `&'a T`. | ||
224 | Ref(Mutability, Ty), | ||
225 | |||
226 | /// This represents a placeholder for an opaque type in situations where we | ||
227 | /// don't know the hidden type (i.e. currently almost always). This is | ||
228 | /// analogous to the `AssociatedType` type constructor. | ||
229 | /// It is also used as the type of async block, with one type parameter | ||
230 | /// representing the Future::Output type. | ||
231 | OpaqueType(OpaqueTyId, Substitution), | ||
232 | |||
233 | /// The anonymous type of a function declaration/definition. Each | ||
234 | /// function has a unique type, which is output (for a function | ||
235 | /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. | ||
236 | /// | ||
237 | /// This includes tuple struct / enum variant constructors as well. | ||
238 | /// | ||
239 | /// For example the type of `bar` here: | ||
240 | /// | ||
241 | /// ``` | ||
242 | /// fn foo() -> i32 { 1 } | ||
243 | /// let bar = foo; // bar: fn() -> i32 {foo} | ||
244 | /// ``` | ||
245 | FnDef(FnDefId, Substitution), | ||
246 | |||
247 | /// The pointee of a string slice. Written as `str`. | ||
248 | Str, | ||
249 | |||
250 | /// The never type `!`. | ||
251 | Never, | ||
252 | |||
253 | /// The type of a specific closure. | ||
254 | /// | ||
255 | /// The closure signature is stored in a `FnPtr` type in the first type | ||
256 | /// parameter. | ||
257 | Closure(ClosureId, Substitution), | ||
258 | |||
259 | /// Represents a foreign type declared in external blocks. | ||
260 | ForeignType(ForeignDefId), | ||
261 | |||
262 | /// A pointer to a function. Written as `fn() -> i32`. | ||
263 | /// | ||
264 | /// For example the type of `bar` here: | ||
265 | /// | ||
266 | /// ``` | ||
267 | /// fn foo() -> i32 { 1 } | ||
268 | /// let bar: fn() -> i32 = foo; | ||
269 | /// ``` | ||
270 | Function(FnPointer), | ||
271 | |||
272 | /// An "alias" type represents some form of type alias, such as: | ||
273 | /// - An associated type projection like `<T as Iterator>::Item` | ||
274 | /// - `impl Trait` types | ||
275 | /// - Named type aliases like `type Foo<X> = Vec<X>` | ||
276 | Alias(AliasTy), | ||
277 | |||
278 | /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T) | ||
279 | /// {}` when we're type-checking the body of that function. In this | ||
280 | /// situation, we know this stands for *some* type, but don't know the exact | ||
281 | /// type. | ||
282 | Placeholder(PlaceholderIndex), | ||
283 | |||
284 | /// A bound type variable. This is used in various places: when representing | ||
285 | /// some polymorphic type like the type of function `fn f<T>`, the type | ||
286 | /// parameters get turned into variables; during trait resolution, inference | ||
287 | /// variables get turned into bound variables and back; and in `Dyn` the | ||
288 | /// `Self` type is represented with a bound variable as well. | ||
289 | BoundVar(BoundVar), | ||
290 | |||
291 | /// A type variable used during type checking. | ||
292 | InferenceVar(InferenceVar, TyVariableKind), | ||
293 | |||
294 | /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust). | ||
295 | /// | ||
296 | /// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)` | ||
297 | /// represents the `Self` type inside the bounds. This is currently | ||
298 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it | ||
299 | /// didn't seem worth the overhead yet. | ||
300 | Dyn(DynTy), | ||
301 | |||
302 | /// A placeholder for a type which could not be computed; this is propagated | ||
303 | /// to avoid useless error messages. Doubles as a placeholder where type | ||
304 | /// variables are inserted before type checking, since we want to try to | ||
305 | /// infer a better type here anyway -- for the IDE use case, we want to try | ||
306 | /// to infer as much as possible even in the presence of type errors. | ||
307 | Unknown, | ||
308 | } | ||
309 | |||
310 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
311 | pub struct Ty(Arc<TyKind>); | ||
312 | |||
313 | impl TyKind { | ||
314 | pub fn intern(self, _interner: &Interner) -> Ty { | ||
315 | Ty(Arc::new(self)) | ||
316 | } | ||
317 | } | ||
318 | |||
319 | impl Ty { | ||
320 | pub fn kind(&self, _interner: &Interner) -> &TyKind { | ||
321 | &self.0 | ||
322 | } | ||
323 | |||
324 | pub fn interned_mut(&mut self) -> &mut TyKind { | ||
325 | Arc::make_mut(&mut self.0) | ||
326 | } | ||
327 | |||
328 | pub fn into_inner(self) -> TyKind { | ||
329 | Arc::try_unwrap(self.0).unwrap_or_else(|a| (*a).clone()) | ||
330 | } | ||
331 | } | ||
332 | |||
333 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
334 | pub struct GenericArg { | ||
335 | interned: GenericArgData, | ||
336 | } | ||
337 | |||
338 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
339 | pub enum GenericArgData { | ||
340 | Ty(Ty), | ||
341 | } | ||
342 | |||
343 | impl GenericArg { | ||
344 | /// Constructs a generic argument using `GenericArgData`. | ||
345 | pub fn new(_interner: &Interner, data: GenericArgData) -> Self { | ||
346 | GenericArg { interned: data } | ||
347 | } | ||
348 | |||
349 | /// Gets the interned value. | ||
350 | pub fn interned(&self) -> &GenericArgData { | ||
351 | &self.interned | ||
352 | } | ||
353 | |||
354 | /// Asserts that this is a type argument. | ||
355 | pub fn assert_ty_ref(&self, interner: &Interner) -> &Ty { | ||
356 | self.ty(interner).unwrap() | ||
357 | } | ||
358 | |||
359 | /// Checks whether the generic argument is a type. | ||
360 | pub fn is_ty(&self, _interner: &Interner) -> bool { | ||
361 | match self.interned() { | ||
362 | GenericArgData::Ty(_) => true, | ||
363 | } | ||
364 | } | ||
365 | |||
366 | /// Returns the type if it is one, `None` otherwise. | ||
367 | pub fn ty(&self, _interner: &Interner) -> Option<&Ty> { | ||
368 | match self.interned() { | ||
369 | GenericArgData::Ty(t) => Some(t), | ||
370 | } | ||
371 | } | ||
372 | } | ||
373 | |||
374 | impl TypeWalk for GenericArg { | ||
375 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
376 | match &self.interned { | ||
377 | GenericArgData::Ty(ty) => { | ||
378 | ty.walk(f); | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | |||
383 | fn walk_mut_binders( | ||
384 | &mut self, | ||
385 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
386 | binders: DebruijnIndex, | ||
387 | ) { | ||
388 | match &mut self.interned { | ||
389 | GenericArgData::Ty(ty) => { | ||
390 | ty.walk_mut_binders(f, binders); | ||
391 | } | ||
392 | } | ||
393 | } | ||
394 | } | ||
395 | |||
396 | /// A list of substitutions for generic parameters. | ||
397 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
398 | pub struct Substitution(SmallVec<[GenericArg; 2]>); | ||
399 | |||
400 | impl TypeWalk for Substitution { | ||
401 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
402 | for t in self.0.iter() { | ||
403 | t.walk(f); | ||
404 | } | ||
405 | } | ||
406 | |||
407 | fn walk_mut_binders( | ||
408 | &mut self, | ||
409 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
410 | binders: DebruijnIndex, | ||
411 | ) { | ||
412 | for t in &mut self.0 { | ||
413 | t.walk_mut_binders(f, binders); | ||
414 | } | ||
415 | } | ||
416 | } | ||
417 | |||
418 | impl Substitution { | 95 | impl Substitution { |
419 | pub fn interned(&self, _: &Interner) -> &[GenericArg] { | ||
420 | &self.0 | ||
421 | } | ||
422 | |||
423 | pub fn len(&self, _: &Interner) -> usize { | ||
424 | self.0.len() | ||
425 | } | ||
426 | |||
427 | pub fn is_empty(&self, _: &Interner) -> bool { | ||
428 | self.0.is_empty() | ||
429 | } | ||
430 | |||
431 | pub fn at(&self, _: &Interner, i: usize) -> &GenericArg { | ||
432 | &self.0[i] | ||
433 | } | ||
434 | |||
435 | pub fn empty(_: &Interner) -> Substitution { | ||
436 | Substitution(SmallVec::new()) | ||
437 | } | ||
438 | |||
439 | pub fn iter(&self, _: &Interner) -> std::slice::Iter<'_, GenericArg> { | ||
440 | self.0.iter() | ||
441 | } | ||
442 | |||
443 | pub fn single(ty: Ty) -> Substitution { | 96 | pub fn single(ty: Ty) -> Substitution { |
444 | Substitution({ | 97 | Substitution::intern({ |
445 | let mut v = SmallVec::new(); | 98 | let mut v = SmallVec::new(); |
446 | v.push(ty.cast(&Interner)); | 99 | v.push(ty.cast(&Interner)); |
447 | v | 100 | v |
@@ -449,18 +102,13 @@ impl Substitution { | |||
449 | } | 102 | } |
450 | 103 | ||
451 | pub fn prefix(&self, n: usize) -> Substitution { | 104 | pub fn prefix(&self, n: usize) -> Substitution { |
452 | Substitution(self.0[..std::cmp::min(self.0.len(), n)].into()) | 105 | Substitution::intern(self.interned()[..std::cmp::min(self.len(&Interner), n)].into()) |
453 | } | 106 | } |
454 | 107 | ||
455 | pub fn suffix(&self, n: usize) -> Substitution { | 108 | pub fn suffix(&self, n: usize) -> Substitution { |
456 | Substitution(self.0[self.0.len() - std::cmp::min(self.0.len(), n)..].into()) | 109 | Substitution::intern( |
457 | } | 110 | self.interned()[self.len(&Interner) - std::cmp::min(self.len(&Interner), n)..].into(), |
458 | 111 | ) | |
459 | pub fn from_iter( | ||
460 | interner: &Interner, | ||
461 | elements: impl IntoIterator<Item = impl CastTo<GenericArg>>, | ||
462 | ) -> Self { | ||
463 | Substitution(elements.into_iter().casted(interner).collect()) | ||
464 | } | 112 | } |
465 | } | 113 | } |
466 | 114 | ||
@@ -469,12 +117,6 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> { | |||
469 | generics(db.upcast(), id.parent).param_idx(id) | 117 | generics(db.upcast(), id.parent).param_idx(id) |
470 | } | 118 | } |
471 | 119 | ||
472 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] | ||
473 | pub struct Binders<T> { | ||
474 | pub num_binders: usize, | ||
475 | pub value: T, | ||
476 | } | ||
477 | |||
478 | impl<T> Binders<T> { | 120 | impl<T> Binders<T> { |
479 | pub fn new(num_binders: usize, value: T) -> Self { | 121 | pub fn new(num_binders: usize, value: T) -> Self { |
480 | Self { num_binders, value } | 122 | Self { num_binders, value } |
@@ -522,27 +164,6 @@ impl<T: TypeWalk> Binders<T> { | |||
522 | } | 164 | } |
523 | } | 165 | } |
524 | 166 | ||
525 | impl<T: TypeWalk> TypeWalk for Binders<T> { | ||
526 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
527 | self.value.walk(f); | ||
528 | } | ||
529 | |||
530 | fn walk_mut_binders( | ||
531 | &mut self, | ||
532 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
533 | binders: DebruijnIndex, | ||
534 | ) { | ||
535 | self.value.walk_mut_binders(f, binders.shifted_in()) | ||
536 | } | ||
537 | } | ||
538 | |||
539 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. | ||
540 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
541 | pub struct TraitRef { | ||
542 | pub trait_id: ChalkTraitId, | ||
543 | pub substitution: Substitution, | ||
544 | } | ||
545 | |||
546 | impl TraitRef { | 167 | impl TraitRef { |
547 | pub fn self_type_parameter(&self) -> &Ty { | 168 | pub fn self_type_parameter(&self) -> &Ty { |
548 | &self.substitution.at(&Interner, 0).assert_ty_ref(&Interner) | 169 | &self.substitution.at(&Interner, 0).assert_ty_ref(&Interner) |
@@ -553,30 +174,6 @@ impl TraitRef { | |||
553 | } | 174 | } |
554 | } | 175 | } |
555 | 176 | ||
556 | impl TypeWalk for TraitRef { | ||
557 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
558 | self.substitution.walk(f); | ||
559 | } | ||
560 | |||
561 | fn walk_mut_binders( | ||
562 | &mut self, | ||
563 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
564 | binders: DebruijnIndex, | ||
565 | ) { | ||
566 | self.substitution.walk_mut_binders(f, binders); | ||
567 | } | ||
568 | } | ||
569 | |||
570 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the | ||
571 | /// parameters of a generic item. | ||
572 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
573 | pub enum WhereClause { | ||
574 | /// The given trait needs to be implemented for its type parameters. | ||
575 | Implemented(TraitRef), | ||
576 | /// An associated type bindings like in `Iterator<Item = T>`. | ||
577 | AliasEq(AliasEq), | ||
578 | } | ||
579 | |||
580 | impl WhereClause { | 177 | impl WhereClause { |
581 | pub fn is_implemented(&self) -> bool { | 178 | pub fn is_implemented(&self) -> bool { |
582 | matches!(self, WhereClause::Implemented(_)) | 179 | matches!(self, WhereClause::Implemented(_)) |
@@ -593,56 +190,6 @@ impl WhereClause { | |||
593 | } | 190 | } |
594 | } | 191 | } |
595 | 192 | ||
596 | impl TypeWalk for WhereClause { | ||
597 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
598 | match self { | ||
599 | WhereClause::Implemented(trait_ref) => trait_ref.walk(f), | ||
600 | WhereClause::AliasEq(alias_eq) => alias_eq.walk(f), | ||
601 | } | ||
602 | } | ||
603 | |||
604 | fn walk_mut_binders( | ||
605 | &mut self, | ||
606 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
607 | binders: DebruijnIndex, | ||
608 | ) { | ||
609 | match self { | ||
610 | WhereClause::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders), | ||
611 | WhereClause::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders), | ||
612 | } | ||
613 | } | ||
614 | } | ||
615 | |||
616 | pub type QuantifiedWhereClause = Binders<WhereClause>; | ||
617 | |||
618 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
619 | pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>); | ||
620 | |||
621 | impl QuantifiedWhereClauses { | ||
622 | pub fn from_iter( | ||
623 | _interner: &Interner, | ||
624 | elements: impl IntoIterator<Item = QuantifiedWhereClause>, | ||
625 | ) -> Self { | ||
626 | QuantifiedWhereClauses(elements.into_iter().collect()) | ||
627 | } | ||
628 | |||
629 | pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> { | ||
630 | &self.0 | ||
631 | } | ||
632 | } | ||
633 | |||
634 | /// Basically a claim (currently not validated / checked) that the contained | ||
635 | /// type / trait ref contains no inference variables; any inference variables it | ||
636 | /// contained have been replaced by bound variables, and `kinds` tells us how | ||
637 | /// many there are and whether they were normal or float/int variables. This is | ||
638 | /// used to erase irrelevant differences between types before using them in | ||
639 | /// queries. | ||
640 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
641 | pub struct Canonical<T> { | ||
642 | pub value: T, | ||
643 | pub binders: CanonicalVarKinds, | ||
644 | } | ||
645 | |||
646 | impl<T> Canonical<T> { | 193 | impl<T> Canonical<T> { |
647 | pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self { | 194 | pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self { |
648 | let kinds = kinds.into_iter().map(|tk| { | 195 | let kinds = kinds.into_iter().map(|tk| { |
@@ -679,7 +226,7 @@ impl CallableSig { | |||
679 | .substs | 226 | .substs |
680 | .clone() | 227 | .clone() |
681 | .shift_bound_vars_out(DebruijnIndex::ONE) | 228 | .shift_bound_vars_out(DebruijnIndex::ONE) |
682 | .interned(&Interner) | 229 | .interned() |
683 | .iter() | 230 | .iter() |
684 | .map(|arg| arg.assert_ty_ref(&Interner).clone()) | 231 | .map(|arg| arg.assert_ty_ref(&Interner).clone()) |
685 | .collect(), | 232 | .collect(), |
@@ -696,24 +243,6 @@ impl CallableSig { | |||
696 | } | 243 | } |
697 | } | 244 | } |
698 | 245 | ||
699 | impl TypeWalk for CallableSig { | ||
700 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
701 | for t in self.params_and_return.iter() { | ||
702 | t.walk(f); | ||
703 | } | ||
704 | } | ||
705 | |||
706 | fn walk_mut_binders( | ||
707 | &mut self, | ||
708 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
709 | binders: DebruijnIndex, | ||
710 | ) { | ||
711 | for t in make_mut_slice(&mut self.params_and_return) { | ||
712 | t.walk_mut_binders(f, binders); | ||
713 | } | ||
714 | } | ||
715 | } | ||
716 | |||
717 | impl Ty { | 246 | impl Ty { |
718 | pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { | 247 | pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { |
719 | match self.kind(&Interner) { | 248 | match self.kind(&Interner) { |
@@ -984,200 +513,6 @@ impl Ty { | |||
984 | } | 513 | } |
985 | } | 514 | } |
986 | 515 | ||
987 | /// This allows walking structures that contain types to do something with those | ||
988 | /// types, similar to Chalk's `Fold` trait. | ||
989 | pub trait TypeWalk { | ||
990 | fn walk(&self, f: &mut impl FnMut(&Ty)); | ||
991 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
992 | self.walk_mut_binders(&mut |ty, _binders| f(ty), DebruijnIndex::INNERMOST); | ||
993 | } | ||
994 | /// Walk the type, counting entered binders. | ||
995 | /// | ||
996 | /// `TyKind::Bound` variables use DeBruijn indexing, which means that 0 refers | ||
997 | /// to the innermost binder, 1 to the next, etc.. So when we want to | ||
998 | /// substitute a certain bound variable, we can't just walk the whole type | ||
999 | /// and blindly replace each instance of a certain index; when we 'enter' | ||
1000 | /// things that introduce new bound variables, we have to keep track of | ||
1001 | /// that. Currently, the only thing that introduces bound variables on our | ||
1002 | /// side are `TyKind::Dyn` and `TyKind::Opaque`, which each introduce a bound | ||
1003 | /// variable for the self type. | ||
1004 | fn walk_mut_binders( | ||
1005 | &mut self, | ||
1006 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
1007 | binders: DebruijnIndex, | ||
1008 | ); | ||
1009 | |||
1010 | fn fold_binders( | ||
1011 | mut self, | ||
1012 | f: &mut impl FnMut(Ty, DebruijnIndex) -> Ty, | ||
1013 | binders: DebruijnIndex, | ||
1014 | ) -> Self | ||
1015 | where | ||
1016 | Self: Sized, | ||
1017 | { | ||
1018 | self.walk_mut_binders( | ||
1019 | &mut |ty_mut, binders| { | ||
1020 | let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner)); | ||
1021 | *ty_mut = f(ty, binders); | ||
1022 | }, | ||
1023 | binders, | ||
1024 | ); | ||
1025 | self | ||
1026 | } | ||
1027 | |||
1028 | fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self | ||
1029 | where | ||
1030 | Self: Sized, | ||
1031 | { | ||
1032 | self.walk_mut(&mut |ty_mut| { | ||
1033 | let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner)); | ||
1034 | *ty_mut = f(ty); | ||
1035 | }); | ||
1036 | self | ||
1037 | } | ||
1038 | |||
1039 | /// Substitutes `TyKind::Bound` vars with the given substitution. | ||
1040 | fn subst_bound_vars(self, substs: &Substitution) -> Self | ||
1041 | where | ||
1042 | Self: Sized, | ||
1043 | { | ||
1044 | self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST) | ||
1045 | } | ||
1046 | |||
1047 | /// Substitutes `TyKind::Bound` vars with the given substitution. | ||
1048 | fn subst_bound_vars_at_depth(mut self, substs: &Substitution, depth: DebruijnIndex) -> Self | ||
1049 | where | ||
1050 | Self: Sized, | ||
1051 | { | ||
1052 | self.walk_mut_binders( | ||
1053 | &mut |ty, binders| { | ||
1054 | if let &mut TyKind::BoundVar(bound) = ty.interned_mut() { | ||
1055 | if bound.debruijn >= binders { | ||
1056 | *ty = substs.0[bound.index] | ||
1057 | .assert_ty_ref(&Interner) | ||
1058 | .clone() | ||
1059 | .shift_bound_vars(binders); | ||
1060 | } | ||
1061 | } | ||
1062 | }, | ||
1063 | depth, | ||
1064 | ); | ||
1065 | self | ||
1066 | } | ||
1067 | |||
1068 | /// Shifts up debruijn indices of `TyKind::Bound` vars by `n`. | ||
1069 | fn shift_bound_vars(self, n: DebruijnIndex) -> Self | ||
1070 | where | ||
1071 | Self: Sized, | ||
1072 | { | ||
1073 | self.fold_binders( | ||
1074 | &mut |ty, binders| match ty.kind(&Interner) { | ||
1075 | TyKind::BoundVar(bound) if bound.debruijn >= binders => { | ||
1076 | TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner) | ||
1077 | } | ||
1078 | _ => ty, | ||
1079 | }, | ||
1080 | DebruijnIndex::INNERMOST, | ||
1081 | ) | ||
1082 | } | ||
1083 | |||
1084 | /// Shifts debruijn indices of `TyKind::Bound` vars out (down) by `n`. | ||
1085 | fn shift_bound_vars_out(self, n: DebruijnIndex) -> Self | ||
1086 | where | ||
1087 | Self: Sized + std::fmt::Debug, | ||
1088 | { | ||
1089 | self.fold_binders( | ||
1090 | &mut |ty, binders| match ty.kind(&Interner) { | ||
1091 | TyKind::BoundVar(bound) if bound.debruijn >= binders => { | ||
1092 | TyKind::BoundVar(bound.shifted_out_to(n).unwrap_or(bound.clone())) | ||
1093 | .intern(&Interner) | ||
1094 | } | ||
1095 | _ => ty, | ||
1096 | }, | ||
1097 | DebruijnIndex::INNERMOST, | ||
1098 | ) | ||
1099 | } | ||
1100 | } | ||
1101 | |||
1102 | impl TypeWalk for Ty { | ||
1103 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
1104 | match self.kind(&Interner) { | ||
1105 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | ||
1106 | for t in p_ty.substitution.iter(&Interner) { | ||
1107 | t.walk(f); | ||
1108 | } | ||
1109 | } | ||
1110 | TyKind::Alias(AliasTy::Opaque(o_ty)) => { | ||
1111 | for t in o_ty.substitution.iter(&Interner) { | ||
1112 | t.walk(f); | ||
1113 | } | ||
1114 | } | ||
1115 | TyKind::Dyn(dyn_ty) => { | ||
1116 | for p in dyn_ty.bounds.value.interned().iter() { | ||
1117 | p.walk(f); | ||
1118 | } | ||
1119 | } | ||
1120 | TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => { | ||
1121 | ty.walk(f); | ||
1122 | } | ||
1123 | _ => { | ||
1124 | if let Some(substs) = self.substs() { | ||
1125 | for t in substs.iter(&Interner) { | ||
1126 | t.walk(f); | ||
1127 | } | ||
1128 | } | ||
1129 | } | ||
1130 | } | ||
1131 | f(self); | ||
1132 | } | ||
1133 | |||
1134 | fn walk_mut_binders( | ||
1135 | &mut self, | ||
1136 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
1137 | binders: DebruijnIndex, | ||
1138 | ) { | ||
1139 | match self.interned_mut() { | ||
1140 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | ||
1141 | p_ty.substitution.walk_mut_binders(f, binders); | ||
1142 | } | ||
1143 | TyKind::Dyn(dyn_ty) => { | ||
1144 | for p in make_mut_slice(&mut dyn_ty.bounds.value.0) { | ||
1145 | p.walk_mut_binders(f, binders.shifted_in()); | ||
1146 | } | ||
1147 | } | ||
1148 | TyKind::Alias(AliasTy::Opaque(o_ty)) => { | ||
1149 | o_ty.substitution.walk_mut_binders(f, binders); | ||
1150 | } | ||
1151 | TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => { | ||
1152 | ty.walk_mut_binders(f, binders); | ||
1153 | } | ||
1154 | _ => { | ||
1155 | if let Some(substs) = self.substs_mut() { | ||
1156 | substs.walk_mut_binders(f, binders); | ||
1157 | } | ||
1158 | } | ||
1159 | } | ||
1160 | f(self, binders); | ||
1161 | } | ||
1162 | } | ||
1163 | |||
1164 | impl<T: TypeWalk> TypeWalk for Vec<T> { | ||
1165 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
1166 | for t in self { | ||
1167 | t.walk(f); | ||
1168 | } | ||
1169 | } | ||
1170 | fn walk_mut_binders( | ||
1171 | &mut self, | ||
1172 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
1173 | binders: DebruijnIndex, | ||
1174 | ) { | ||
1175 | for t in self { | ||
1176 | t.walk_mut_binders(f, binders); | ||
1177 | } | ||
1178 | } | ||
1179 | } | ||
1180 | |||
1181 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] | 516 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] |
1182 | pub enum ImplTraitId { | 517 | pub enum ImplTraitId { |
1183 | ReturnTypeImplTrait(hir_def::FunctionId, u16), | 518 | ReturnTypeImplTrait(hir_def::FunctionId, u16), |
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index a76586f0c..0e4a620b6 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -800,7 +800,7 @@ pub fn implements_trait_unique( | |||
800 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); | 800 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); |
801 | let solution = db.trait_solve(krate, goal); | 801 | let solution = db.trait_solve(krate, goal); |
802 | 802 | ||
803 | matches!(solution, Some(crate::traits::Solution::Unique(_))) | 803 | matches!(solution, Some(crate::Solution::Unique(_))) |
804 | } | 804 | } |
805 | 805 | ||
806 | /// This creates Substs for a trait with the given Self type and type variables | 806 | /// This creates Substs for a trait with the given Self type and type variables |
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index e5e8cff33..66d600bfc 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs | |||
@@ -8,8 +8,8 @@ use hir_def::{lang_item::LangItemTarget, TraitId}; | |||
8 | use stdx::panic_context; | 8 | use stdx::panic_context; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | db::HirDatabase, AliasTy, Canonical, DebruijnIndex, HirDisplay, Substitution, Ty, TyKind, | 11 | db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Guidance, HirDisplay, InEnvironment, |
12 | TypeWalk, WhereClause, | 12 | Solution, SolutionVariables, Ty, TyKind, WhereClause, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | use self::chalk::{from_chalk, Interner, ToChalk}; | 15 | use self::chalk::{from_chalk, Interner, ToChalk}; |
@@ -70,55 +70,6 @@ impl Default for TraitEnvironment { | |||
70 | } | 70 | } |
71 | } | 71 | } |
72 | 72 | ||
73 | /// Something (usually a goal), along with an environment. | ||
74 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
75 | pub struct InEnvironment<T> { | ||
76 | pub environment: chalk_ir::Environment<Interner>, | ||
77 | pub goal: T, | ||
78 | } | ||
79 | |||
80 | impl<T> InEnvironment<T> { | ||
81 | pub fn new(environment: chalk_ir::Environment<Interner>, value: T) -> InEnvironment<T> { | ||
82 | InEnvironment { environment, goal: value } | ||
83 | } | ||
84 | } | ||
85 | |||
86 | /// Something that needs to be proven (by Chalk) during type checking, e.g. that | ||
87 | /// a certain type implements a certain trait. Proving the Obligation might | ||
88 | /// result in additional information about inference variables. | ||
89 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
90 | pub enum DomainGoal { | ||
91 | Holds(WhereClause), | ||
92 | } | ||
93 | |||
94 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
95 | pub struct AliasEq { | ||
96 | pub alias: AliasTy, | ||
97 | pub ty: Ty, | ||
98 | } | ||
99 | |||
100 | impl TypeWalk for AliasEq { | ||
101 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
102 | self.ty.walk(f); | ||
103 | match &self.alias { | ||
104 | AliasTy::Projection(projection_ty) => projection_ty.walk(f), | ||
105 | AliasTy::Opaque(opaque) => opaque.walk(f), | ||
106 | } | ||
107 | } | ||
108 | |||
109 | fn walk_mut_binders( | ||
110 | &mut self, | ||
111 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
112 | binders: DebruijnIndex, | ||
113 | ) { | ||
114 | self.ty.walk_mut_binders(f, binders); | ||
115 | match &mut self.alias { | ||
116 | AliasTy::Projection(projection_ty) => projection_ty.walk_mut_binders(f, binders), | ||
117 | AliasTy::Opaque(opaque) => opaque.walk_mut_binders(f, binders), | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | |||
122 | /// Solve a trait goal using Chalk. | 73 | /// Solve a trait goal using Chalk. |
123 | pub(crate) fn trait_solve_query( | 74 | pub(crate) fn trait_solve_query( |
124 | db: &dyn HirDatabase, | 75 | db: &dyn HirDatabase, |
@@ -246,41 +197,6 @@ fn solution_from_chalk( | |||
246 | } | 197 | } |
247 | } | 198 | } |
248 | 199 | ||
249 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
250 | pub struct SolutionVariables(pub Canonical<Substitution>); | ||
251 | |||
252 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
253 | /// A (possible) solution for a proposed goal. | ||
254 | pub enum Solution { | ||
255 | /// The goal indeed holds, and there is a unique value for all existential | ||
256 | /// variables. | ||
257 | Unique(SolutionVariables), | ||
258 | |||
259 | /// The goal may be provable in multiple ways, but regardless we may have some guidance | ||
260 | /// for type inference. In this case, we don't return any lifetime | ||
261 | /// constraints, since we have not "committed" to any particular solution | ||
262 | /// yet. | ||
263 | Ambig(Guidance), | ||
264 | } | ||
265 | |||
266 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
267 | /// When a goal holds ambiguously (e.g., because there are multiple possible | ||
268 | /// solutions), we issue a set of *guidance* back to type inference. | ||
269 | pub enum Guidance { | ||
270 | /// The existential variables *must* have the given values if the goal is | ||
271 | /// ever to hold, but that alone isn't enough to guarantee the goal will | ||
272 | /// actually hold. | ||
273 | Definite(SolutionVariables), | ||
274 | |||
275 | /// There are multiple plausible values for the existentials, but the ones | ||
276 | /// here are suggested as the preferred choice heuristically. These should | ||
277 | /// be used for inference fallback only. | ||
278 | Suggested(SolutionVariables), | ||
279 | |||
280 | /// There's no useful information to feed back to type inference | ||
281 | Unknown, | ||
282 | } | ||
283 | |||
284 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 200 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
285 | pub enum FnTrait { | 201 | pub enum FnTrait { |
286 | FnOnce, | 202 | FnOnce, |
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 452b357e8..5e4f97a46 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs | |||
@@ -10,11 +10,9 @@ use base_db::salsa::InternKey; | |||
10 | use hir_def::{GenericDefId, TypeAliasId}; | 10 | use hir_def::{GenericDefId, TypeAliasId}; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | db::HirDatabase, | 13 | db::HirDatabase, primitive::UintTy, AliasTy, CallableDefId, Canonical, DomainGoal, FnPointer, |
14 | primitive::UintTy, | 14 | GenericArg, InEnvironment, OpaqueTy, ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, |
15 | traits::{Canonical, DomainGoal}, | 15 | TraitRef, Ty, TypeWalk, WhereClause, |
16 | AliasTy, CallableDefId, FnPointer, GenericArg, InEnvironment, OpaqueTy, ProjectionTy, | ||
17 | QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TypeWalk, WhereClause, | ||
18 | }; | 16 | }; |
19 | 17 | ||
20 | use super::interner::*; | 18 | use super::interner::*; |
@@ -220,8 +218,8 @@ impl ToChalk for GenericArg { | |||
220 | type Chalk = chalk_ir::GenericArg<Interner>; | 218 | type Chalk = chalk_ir::GenericArg<Interner>; |
221 | 219 | ||
222 | fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk { | 220 | fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk { |
223 | match self.interned { | 221 | match self.interned() { |
224 | crate::GenericArgData::Ty(ty) => ty.to_chalk(db).cast(&Interner), | 222 | crate::GenericArgData::Ty(ty) => ty.clone().to_chalk(db).cast(&Interner), |
225 | } | 223 | } |
226 | } | 224 | } |
227 | 225 | ||
@@ -249,7 +247,7 @@ impl ToChalk for Substitution { | |||
249 | parameters: chalk_ir::Substitution<Interner>, | 247 | parameters: chalk_ir::Substitution<Interner>, |
250 | ) -> Substitution { | 248 | ) -> Substitution { |
251 | let tys = parameters.iter(&Interner).map(|p| from_chalk(db, p.clone())).collect(); | 249 | let tys = parameters.iter(&Interner).map(|p| from_chalk(db, p.clone())).collect(); |
252 | Substitution(tys) | 250 | Substitution::intern(tys) |
253 | } | 251 | } |
254 | } | 252 | } |
255 | 253 | ||
@@ -546,7 +544,7 @@ pub(super) fn generic_predicate_to_inline_bound( | |||
546 | // have the expected self type | 544 | // have the expected self type |
547 | return None; | 545 | return None; |
548 | } | 546 | } |
549 | let args_no_self = trait_ref.substitution.interned(&Interner)[1..] | 547 | let args_no_self = trait_ref.substitution.interned()[1..] |
550 | .iter() | 548 | .iter() |
551 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | 549 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) |
552 | .collect(); | 550 | .collect(); |
@@ -558,7 +556,7 @@ pub(super) fn generic_predicate_to_inline_bound( | |||
558 | return None; | 556 | return None; |
559 | } | 557 | } |
560 | let trait_ = projection_ty.trait_(db); | 558 | let trait_ = projection_ty.trait_(db); |
561 | let args_no_self = projection_ty.substitution.interned(&Interner)[1..] | 559 | let args_no_self = projection_ty.substitution.interned()[1..] |
562 | .iter() | 560 | .iter() |
563 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | 561 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) |
564 | .collect(); | 562 | .collect(); |
diff --git a/crates/hir_ty/src/types.rs b/crates/hir_ty/src/types.rs new file mode 100644 index 000000000..53662fcdc --- /dev/null +++ b/crates/hir_ty/src/types.rs | |||
@@ -0,0 +1,416 @@ | |||
1 | //! This is the home of `Ty` etc. until they get replaced by their chalk_ir | ||
2 | //! equivalents. | ||
3 | |||
4 | use std::sync::Arc; | ||
5 | |||
6 | use chalk_ir::{ | ||
7 | cast::{CastTo, Caster}, | ||
8 | BoundVar, Mutability, Scalar, TyVariableKind, | ||
9 | }; | ||
10 | use hir_def::LifetimeParamId; | ||
11 | use smallvec::SmallVec; | ||
12 | |||
13 | use crate::{ | ||
14 | AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, FnDefId, FnSig, ForeignDefId, | ||
15 | InferenceVar, Interner, OpaqueTyId, PlaceholderIndex, | ||
16 | }; | ||
17 | |||
18 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
19 | pub enum Lifetime { | ||
20 | Parameter(LifetimeParamId), | ||
21 | Static, | ||
22 | } | ||
23 | |||
24 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
25 | pub struct OpaqueTy { | ||
26 | pub opaque_ty_id: OpaqueTyId, | ||
27 | pub substitution: Substitution, | ||
28 | } | ||
29 | |||
30 | /// A "projection" type corresponds to an (unnormalized) | ||
31 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the | ||
32 | /// trait and all its parameters are fully known. | ||
33 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
34 | pub struct ProjectionTy { | ||
35 | pub associated_ty_id: AssocTypeId, | ||
36 | pub substitution: Substitution, | ||
37 | } | ||
38 | |||
39 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
40 | pub struct DynTy { | ||
41 | /// The unknown self type. | ||
42 | pub bounds: Binders<QuantifiedWhereClauses>, | ||
43 | } | ||
44 | |||
45 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
46 | pub struct FnPointer { | ||
47 | pub num_args: usize, | ||
48 | pub sig: FnSig, | ||
49 | pub substs: Substitution, | ||
50 | } | ||
51 | |||
52 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
53 | pub enum AliasTy { | ||
54 | /// A "projection" type corresponds to an (unnormalized) | ||
55 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the | ||
56 | /// trait and all its parameters are fully known. | ||
57 | Projection(ProjectionTy), | ||
58 | /// An opaque type (`impl Trait`). | ||
59 | /// | ||
60 | /// This is currently only used for return type impl trait; each instance of | ||
61 | /// `impl Trait` in a return type gets its own ID. | ||
62 | Opaque(OpaqueTy), | ||
63 | } | ||
64 | |||
65 | /// A type. | ||
66 | /// | ||
67 | /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents | ||
68 | /// the same thing (but in a different way). | ||
69 | /// | ||
70 | /// This should be cheap to clone. | ||
71 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
72 | pub enum TyKind { | ||
73 | /// Structures, enumerations and unions. | ||
74 | Adt(chalk_ir::AdtId<Interner>, Substitution), | ||
75 | |||
76 | /// Represents an associated item like `Iterator::Item`. This is used | ||
77 | /// when we have tried to normalize a projection like `T::Item` but | ||
78 | /// couldn't find a better representation. In that case, we generate | ||
79 | /// an **application type** like `(Iterator::Item)<T>`. | ||
80 | AssociatedType(AssocTypeId, Substitution), | ||
81 | |||
82 | /// a scalar type like `bool` or `u32` | ||
83 | Scalar(Scalar), | ||
84 | |||
85 | /// A tuple type. For example, `(i32, bool)`. | ||
86 | Tuple(usize, Substitution), | ||
87 | |||
88 | /// An array with the given length. Written as `[T; n]`. | ||
89 | Array(Ty), | ||
90 | |||
91 | /// The pointee of an array slice. Written as `[T]`. | ||
92 | Slice(Ty), | ||
93 | |||
94 | /// A raw pointer. Written as `*mut T` or `*const T` | ||
95 | Raw(Mutability, Ty), | ||
96 | |||
97 | /// A reference; a pointer with an associated lifetime. Written as | ||
98 | /// `&'a mut T` or `&'a T`. | ||
99 | Ref(Mutability, Ty), | ||
100 | |||
101 | /// This represents a placeholder for an opaque type in situations where we | ||
102 | /// don't know the hidden type (i.e. currently almost always). This is | ||
103 | /// analogous to the `AssociatedType` type constructor. | ||
104 | /// It is also used as the type of async block, with one type parameter | ||
105 | /// representing the Future::Output type. | ||
106 | OpaqueType(OpaqueTyId, Substitution), | ||
107 | |||
108 | /// The anonymous type of a function declaration/definition. Each | ||
109 | /// function has a unique type, which is output (for a function | ||
110 | /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. | ||
111 | /// | ||
112 | /// This includes tuple struct / enum variant constructors as well. | ||
113 | /// | ||
114 | /// For example the type of `bar` here: | ||
115 | /// | ||
116 | /// ``` | ||
117 | /// fn foo() -> i32 { 1 } | ||
118 | /// let bar = foo; // bar: fn() -> i32 {foo} | ||
119 | /// ``` | ||
120 | FnDef(FnDefId, Substitution), | ||
121 | |||
122 | /// The pointee of a string slice. Written as `str`. | ||
123 | Str, | ||
124 | |||
125 | /// The never type `!`. | ||
126 | Never, | ||
127 | |||
128 | /// The type of a specific closure. | ||
129 | /// | ||
130 | /// The closure signature is stored in a `FnPtr` type in the first type | ||
131 | /// parameter. | ||
132 | Closure(ClosureId, Substitution), | ||
133 | |||
134 | /// Represents a foreign type declared in external blocks. | ||
135 | ForeignType(ForeignDefId), | ||
136 | |||
137 | /// A pointer to a function. Written as `fn() -> i32`. | ||
138 | /// | ||
139 | /// For example the type of `bar` here: | ||
140 | /// | ||
141 | /// ``` | ||
142 | /// fn foo() -> i32 { 1 } | ||
143 | /// let bar: fn() -> i32 = foo; | ||
144 | /// ``` | ||
145 | Function(FnPointer), | ||
146 | |||
147 | /// An "alias" type represents some form of type alias, such as: | ||
148 | /// - An associated type projection like `<T as Iterator>::Item` | ||
149 | /// - `impl Trait` types | ||
150 | /// - Named type aliases like `type Foo<X> = Vec<X>` | ||
151 | Alias(AliasTy), | ||
152 | |||
153 | /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T) | ||
154 | /// {}` when we're type-checking the body of that function. In this | ||
155 | /// situation, we know this stands for *some* type, but don't know the exact | ||
156 | /// type. | ||
157 | Placeholder(PlaceholderIndex), | ||
158 | |||
159 | /// A bound type variable. This is used in various places: when representing | ||
160 | /// some polymorphic type like the type of function `fn f<T>`, the type | ||
161 | /// parameters get turned into variables; during trait resolution, inference | ||
162 | /// variables get turned into bound variables and back; and in `Dyn` the | ||
163 | /// `Self` type is represented with a bound variable as well. | ||
164 | BoundVar(BoundVar), | ||
165 | |||
166 | /// A type variable used during type checking. | ||
167 | InferenceVar(InferenceVar, TyVariableKind), | ||
168 | |||
169 | /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust). | ||
170 | /// | ||
171 | /// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)` | ||
172 | /// represents the `Self` type inside the bounds. This is currently | ||
173 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it | ||
174 | /// didn't seem worth the overhead yet. | ||
175 | Dyn(DynTy), | ||
176 | |||
177 | /// A placeholder for a type which could not be computed; this is propagated | ||
178 | /// to avoid useless error messages. Doubles as a placeholder where type | ||
179 | /// variables are inserted before type checking, since we want to try to | ||
180 | /// infer a better type here anyway -- for the IDE use case, we want to try | ||
181 | /// to infer as much as possible even in the presence of type errors. | ||
182 | Unknown, | ||
183 | } | ||
184 | |||
185 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
186 | pub struct Ty(Arc<TyKind>); | ||
187 | |||
188 | impl TyKind { | ||
189 | pub fn intern(self, _interner: &Interner) -> Ty { | ||
190 | Ty(Arc::new(self)) | ||
191 | } | ||
192 | } | ||
193 | |||
194 | impl Ty { | ||
195 | pub fn kind(&self, _interner: &Interner) -> &TyKind { | ||
196 | &self.0 | ||
197 | } | ||
198 | |||
199 | pub fn interned_mut(&mut self) -> &mut TyKind { | ||
200 | Arc::make_mut(&mut self.0) | ||
201 | } | ||
202 | |||
203 | pub fn into_inner(self) -> TyKind { | ||
204 | Arc::try_unwrap(self.0).unwrap_or_else(|a| (*a).clone()) | ||
205 | } | ||
206 | } | ||
207 | |||
208 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
209 | pub struct GenericArg { | ||
210 | interned: GenericArgData, | ||
211 | } | ||
212 | |||
213 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
214 | pub enum GenericArgData { | ||
215 | Ty(Ty), | ||
216 | } | ||
217 | |||
218 | impl GenericArg { | ||
219 | /// Constructs a generic argument using `GenericArgData`. | ||
220 | pub fn new(_interner: &Interner, data: GenericArgData) -> Self { | ||
221 | GenericArg { interned: data } | ||
222 | } | ||
223 | |||
224 | /// Gets the interned value. | ||
225 | pub fn interned(&self) -> &GenericArgData { | ||
226 | &self.interned | ||
227 | } | ||
228 | |||
229 | /// Asserts that this is a type argument. | ||
230 | pub fn assert_ty_ref(&self, interner: &Interner) -> &Ty { | ||
231 | self.ty(interner).unwrap() | ||
232 | } | ||
233 | |||
234 | /// Checks whether the generic argument is a type. | ||
235 | pub fn is_ty(&self, _interner: &Interner) -> bool { | ||
236 | match self.interned() { | ||
237 | GenericArgData::Ty(_) => true, | ||
238 | } | ||
239 | } | ||
240 | |||
241 | /// Returns the type if it is one, `None` otherwise. | ||
242 | pub fn ty(&self, _interner: &Interner) -> Option<&Ty> { | ||
243 | match self.interned() { | ||
244 | GenericArgData::Ty(t) => Some(t), | ||
245 | } | ||
246 | } | ||
247 | |||
248 | pub fn interned_mut(&mut self) -> &mut GenericArgData { | ||
249 | &mut self.interned | ||
250 | } | ||
251 | } | ||
252 | |||
253 | /// A list of substitutions for generic parameters. | ||
254 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
255 | pub struct Substitution(SmallVec<[GenericArg; 2]>); | ||
256 | |||
257 | impl Substitution { | ||
258 | pub fn interned(&self) -> &[GenericArg] { | ||
259 | &self.0 | ||
260 | } | ||
261 | |||
262 | pub fn len(&self, _: &Interner) -> usize { | ||
263 | self.0.len() | ||
264 | } | ||
265 | |||
266 | pub fn is_empty(&self, _: &Interner) -> bool { | ||
267 | self.0.is_empty() | ||
268 | } | ||
269 | |||
270 | pub fn at(&self, _: &Interner, i: usize) -> &GenericArg { | ||
271 | &self.0[i] | ||
272 | } | ||
273 | |||
274 | pub fn empty(_: &Interner) -> Substitution { | ||
275 | Substitution(SmallVec::new()) | ||
276 | } | ||
277 | |||
278 | pub fn iter(&self, _: &Interner) -> std::slice::Iter<'_, GenericArg> { | ||
279 | self.0.iter() | ||
280 | } | ||
281 | |||
282 | pub fn from_iter( | ||
283 | interner: &Interner, | ||
284 | elements: impl IntoIterator<Item = impl CastTo<GenericArg>>, | ||
285 | ) -> Self { | ||
286 | Substitution(elements.into_iter().casted(interner).collect()) | ||
287 | } | ||
288 | |||
289 | // We can hopefully add this to Chalk | ||
290 | pub fn intern(interned: SmallVec<[GenericArg; 2]>) -> Substitution { | ||
291 | Substitution(interned) | ||
292 | } | ||
293 | |||
294 | pub fn interned_mut(&mut self) -> &mut SmallVec<[GenericArg; 2]> { | ||
295 | &mut self.0 | ||
296 | } | ||
297 | } | ||
298 | |||
299 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] | ||
300 | pub struct Binders<T> { | ||
301 | pub num_binders: usize, | ||
302 | pub value: T, | ||
303 | } | ||
304 | |||
305 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. | ||
306 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
307 | pub struct TraitRef { | ||
308 | pub trait_id: ChalkTraitId, | ||
309 | pub substitution: Substitution, | ||
310 | } | ||
311 | |||
312 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the | ||
313 | /// parameters of a generic item. | ||
314 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
315 | pub enum WhereClause { | ||
316 | /// The given trait needs to be implemented for its type parameters. | ||
317 | Implemented(TraitRef), | ||
318 | /// An associated type bindings like in `Iterator<Item = T>`. | ||
319 | AliasEq(AliasEq), | ||
320 | } | ||
321 | |||
322 | pub type QuantifiedWhereClause = Binders<WhereClause>; | ||
323 | |||
324 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
325 | pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>); | ||
326 | |||
327 | impl QuantifiedWhereClauses { | ||
328 | pub fn from_iter( | ||
329 | _interner: &Interner, | ||
330 | elements: impl IntoIterator<Item = QuantifiedWhereClause>, | ||
331 | ) -> Self { | ||
332 | QuantifiedWhereClauses(elements.into_iter().collect()) | ||
333 | } | ||
334 | |||
335 | pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> { | ||
336 | &self.0 | ||
337 | } | ||
338 | |||
339 | pub fn interned_mut(&mut self) -> &mut Arc<[QuantifiedWhereClause]> { | ||
340 | &mut self.0 | ||
341 | } | ||
342 | } | ||
343 | |||
344 | /// Basically a claim (currently not validated / checked) that the contained | ||
345 | /// type / trait ref contains no inference variables; any inference variables it | ||
346 | /// contained have been replaced by bound variables, and `kinds` tells us how | ||
347 | /// many there are and whether they were normal or float/int variables. This is | ||
348 | /// used to erase irrelevant differences between types before using them in | ||
349 | /// queries. | ||
350 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
351 | pub struct Canonical<T> { | ||
352 | pub value: T, | ||
353 | pub binders: CanonicalVarKinds, | ||
354 | } | ||
355 | |||
356 | /// Something (usually a goal), along with an environment. | ||
357 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
358 | pub struct InEnvironment<T> { | ||
359 | pub environment: chalk_ir::Environment<Interner>, | ||
360 | pub goal: T, | ||
361 | } | ||
362 | |||
363 | impl<T> InEnvironment<T> { | ||
364 | pub fn new(environment: chalk_ir::Environment<Interner>, value: T) -> InEnvironment<T> { | ||
365 | InEnvironment { environment, goal: value } | ||
366 | } | ||
367 | } | ||
368 | |||
369 | /// Something that needs to be proven (by Chalk) during type checking, e.g. that | ||
370 | /// a certain type implements a certain trait. Proving the Obligation might | ||
371 | /// result in additional information about inference variables. | ||
372 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
373 | pub enum DomainGoal { | ||
374 | Holds(WhereClause), | ||
375 | } | ||
376 | |||
377 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
378 | pub struct AliasEq { | ||
379 | pub alias: AliasTy, | ||
380 | pub ty: Ty, | ||
381 | } | ||
382 | |||
383 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
384 | pub struct SolutionVariables(pub Canonical<Substitution>); | ||
385 | |||
386 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
387 | /// A (possible) solution for a proposed goal. | ||
388 | pub enum Solution { | ||
389 | /// The goal indeed holds, and there is a unique value for all existential | ||
390 | /// variables. | ||
391 | Unique(SolutionVariables), | ||
392 | |||
393 | /// The goal may be provable in multiple ways, but regardless we may have some guidance | ||
394 | /// for type inference. In this case, we don't return any lifetime | ||
395 | /// constraints, since we have not "committed" to any particular solution | ||
396 | /// yet. | ||
397 | Ambig(Guidance), | ||
398 | } | ||
399 | |||
400 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
401 | /// When a goal holds ambiguously (e.g., because there are multiple possible | ||
402 | /// solutions), we issue a set of *guidance* back to type inference. | ||
403 | pub enum Guidance { | ||
404 | /// The existential variables *must* have the given values if the goal is | ||
405 | /// ever to hold, but that alone isn't enough to guarantee the goal will | ||
406 | /// actually hold. | ||
407 | Definite(SolutionVariables), | ||
408 | |||
409 | /// There are multiple plausible values for the existentials, but the ones | ||
410 | /// here are suggested as the preferred choice heuristically. These should | ||
411 | /// be used for inference fallback only. | ||
412 | Suggested(SolutionVariables), | ||
413 | |||
414 | /// There's no useful information to feed back to type inference | ||
415 | Unknown, | ||
416 | } | ||
diff --git a/crates/hir_ty/src/walk.rs b/crates/hir_ty/src/walk.rs new file mode 100644 index 000000000..bfb3f1041 --- /dev/null +++ b/crates/hir_ty/src/walk.rs | |||
@@ -0,0 +1,381 @@ | |||
1 | //! The `TypeWalk` trait (probably to be replaced by Chalk's `Fold` and | ||
2 | //! `Visit`). | ||
3 | |||
4 | use std::mem; | ||
5 | |||
6 | use chalk_ir::DebruijnIndex; | ||
7 | |||
8 | use crate::{ | ||
9 | utils::make_mut_slice, AliasEq, AliasTy, Binders, CallableSig, GenericArg, GenericArgData, | ||
10 | Interner, OpaqueTy, ProjectionTy, Substitution, TraitRef, Ty, TyKind, WhereClause, | ||
11 | }; | ||
12 | |||
13 | /// This allows walking structures that contain types to do something with those | ||
14 | /// types, similar to Chalk's `Fold` trait. | ||
15 | pub trait TypeWalk { | ||
16 | fn walk(&self, f: &mut impl FnMut(&Ty)); | ||
17 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
18 | self.walk_mut_binders(&mut |ty, _binders| f(ty), DebruijnIndex::INNERMOST); | ||
19 | } | ||
20 | /// Walk the type, counting entered binders. | ||
21 | /// | ||
22 | /// `TyKind::Bound` variables use DeBruijn indexing, which means that 0 refers | ||
23 | /// to the innermost binder, 1 to the next, etc.. So when we want to | ||
24 | /// substitute a certain bound variable, we can't just walk the whole type | ||
25 | /// and blindly replace each instance of a certain index; when we 'enter' | ||
26 | /// things that introduce new bound variables, we have to keep track of | ||
27 | /// that. Currently, the only thing that introduces bound variables on our | ||
28 | /// side are `TyKind::Dyn` and `TyKind::Opaque`, which each introduce a bound | ||
29 | /// variable for the self type. | ||
30 | fn walk_mut_binders( | ||
31 | &mut self, | ||
32 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
33 | binders: DebruijnIndex, | ||
34 | ); | ||
35 | |||
36 | fn fold_binders( | ||
37 | mut self, | ||
38 | f: &mut impl FnMut(Ty, DebruijnIndex) -> Ty, | ||
39 | binders: DebruijnIndex, | ||
40 | ) -> Self | ||
41 | where | ||
42 | Self: Sized, | ||
43 | { | ||
44 | self.walk_mut_binders( | ||
45 | &mut |ty_mut, binders| { | ||
46 | let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner)); | ||
47 | *ty_mut = f(ty, binders); | ||
48 | }, | ||
49 | binders, | ||
50 | ); | ||
51 | self | ||
52 | } | ||
53 | |||
54 | fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self | ||
55 | where | ||
56 | Self: Sized, | ||
57 | { | ||
58 | self.walk_mut(&mut |ty_mut| { | ||
59 | let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner)); | ||
60 | *ty_mut = f(ty); | ||
61 | }); | ||
62 | self | ||
63 | } | ||
64 | |||
65 | /// Substitutes `TyKind::Bound` vars with the given substitution. | ||
66 | fn subst_bound_vars(self, substs: &Substitution) -> Self | ||
67 | where | ||
68 | Self: Sized, | ||
69 | { | ||
70 | self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST) | ||
71 | } | ||
72 | |||
73 | /// Substitutes `TyKind::Bound` vars with the given substitution. | ||
74 | fn subst_bound_vars_at_depth(mut self, substs: &Substitution, depth: DebruijnIndex) -> Self | ||
75 | where | ||
76 | Self: Sized, | ||
77 | { | ||
78 | self.walk_mut_binders( | ||
79 | &mut |ty, binders| { | ||
80 | if let &mut TyKind::BoundVar(bound) = ty.interned_mut() { | ||
81 | if bound.debruijn >= binders { | ||
82 | *ty = substs.interned()[bound.index] | ||
83 | .assert_ty_ref(&Interner) | ||
84 | .clone() | ||
85 | .shift_bound_vars(binders); | ||
86 | } | ||
87 | } | ||
88 | }, | ||
89 | depth, | ||
90 | ); | ||
91 | self | ||
92 | } | ||
93 | |||
94 | /// Shifts up debruijn indices of `TyKind::Bound` vars by `n`. | ||
95 | fn shift_bound_vars(self, n: DebruijnIndex) -> Self | ||
96 | where | ||
97 | Self: Sized, | ||
98 | { | ||
99 | self.fold_binders( | ||
100 | &mut |ty, binders| match ty.kind(&Interner) { | ||
101 | TyKind::BoundVar(bound) if bound.debruijn >= binders => { | ||
102 | TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner) | ||
103 | } | ||
104 | _ => ty, | ||
105 | }, | ||
106 | DebruijnIndex::INNERMOST, | ||
107 | ) | ||
108 | } | ||
109 | |||
110 | /// Shifts debruijn indices of `TyKind::Bound` vars out (down) by `n`. | ||
111 | fn shift_bound_vars_out(self, n: DebruijnIndex) -> Self | ||
112 | where | ||
113 | Self: Sized + std::fmt::Debug, | ||
114 | { | ||
115 | self.fold_binders( | ||
116 | &mut |ty, binders| match ty.kind(&Interner) { | ||
117 | TyKind::BoundVar(bound) if bound.debruijn >= binders => { | ||
118 | TyKind::BoundVar(bound.shifted_out_to(n).unwrap_or(bound.clone())) | ||
119 | .intern(&Interner) | ||
120 | } | ||
121 | _ => ty, | ||
122 | }, | ||
123 | DebruijnIndex::INNERMOST, | ||
124 | ) | ||
125 | } | ||
126 | } | ||
127 | |||
128 | impl TypeWalk for Ty { | ||
129 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
130 | match self.kind(&Interner) { | ||
131 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | ||
132 | for t in p_ty.substitution.iter(&Interner) { | ||
133 | t.walk(f); | ||
134 | } | ||
135 | } | ||
136 | TyKind::Alias(AliasTy::Opaque(o_ty)) => { | ||
137 | for t in o_ty.substitution.iter(&Interner) { | ||
138 | t.walk(f); | ||
139 | } | ||
140 | } | ||
141 | TyKind::Dyn(dyn_ty) => { | ||
142 | for p in dyn_ty.bounds.value.interned().iter() { | ||
143 | p.walk(f); | ||
144 | } | ||
145 | } | ||
146 | TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => { | ||
147 | ty.walk(f); | ||
148 | } | ||
149 | _ => { | ||
150 | if let Some(substs) = self.substs() { | ||
151 | for t in substs.iter(&Interner) { | ||
152 | t.walk(f); | ||
153 | } | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | f(self); | ||
158 | } | ||
159 | |||
160 | fn walk_mut_binders( | ||
161 | &mut self, | ||
162 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
163 | binders: DebruijnIndex, | ||
164 | ) { | ||
165 | match self.interned_mut() { | ||
166 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | ||
167 | p_ty.substitution.walk_mut_binders(f, binders); | ||
168 | } | ||
169 | TyKind::Dyn(dyn_ty) => { | ||
170 | for p in make_mut_slice(dyn_ty.bounds.value.interned_mut()) { | ||
171 | p.walk_mut_binders(f, binders.shifted_in()); | ||
172 | } | ||
173 | } | ||
174 | TyKind::Alias(AliasTy::Opaque(o_ty)) => { | ||
175 | o_ty.substitution.walk_mut_binders(f, binders); | ||
176 | } | ||
177 | TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => { | ||
178 | ty.walk_mut_binders(f, binders); | ||
179 | } | ||
180 | _ => { | ||
181 | if let Some(substs) = self.substs_mut() { | ||
182 | substs.walk_mut_binders(f, binders); | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | f(self, binders); | ||
187 | } | ||
188 | } | ||
189 | |||
190 | impl<T: TypeWalk> TypeWalk for Vec<T> { | ||
191 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
192 | for t in self { | ||
193 | t.walk(f); | ||
194 | } | ||
195 | } | ||
196 | fn walk_mut_binders( | ||
197 | &mut self, | ||
198 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
199 | binders: DebruijnIndex, | ||
200 | ) { | ||
201 | for t in self { | ||
202 | t.walk_mut_binders(f, binders); | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | |||
207 | impl TypeWalk for OpaqueTy { | ||
208 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
209 | self.substitution.walk(f); | ||
210 | } | ||
211 | |||
212 | fn walk_mut_binders( | ||
213 | &mut self, | ||
214 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
215 | binders: DebruijnIndex, | ||
216 | ) { | ||
217 | self.substitution.walk_mut_binders(f, binders); | ||
218 | } | ||
219 | } | ||
220 | |||
221 | impl TypeWalk for ProjectionTy { | ||
222 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
223 | self.substitution.walk(f); | ||
224 | } | ||
225 | |||
226 | fn walk_mut_binders( | ||
227 | &mut self, | ||
228 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
229 | binders: DebruijnIndex, | ||
230 | ) { | ||
231 | self.substitution.walk_mut_binders(f, binders); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | impl TypeWalk for AliasTy { | ||
236 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
237 | match self { | ||
238 | AliasTy::Projection(it) => it.walk(f), | ||
239 | AliasTy::Opaque(it) => it.walk(f), | ||
240 | } | ||
241 | } | ||
242 | |||
243 | fn walk_mut_binders( | ||
244 | &mut self, | ||
245 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
246 | binders: DebruijnIndex, | ||
247 | ) { | ||
248 | match self { | ||
249 | AliasTy::Projection(it) => it.walk_mut_binders(f, binders), | ||
250 | AliasTy::Opaque(it) => it.walk_mut_binders(f, binders), | ||
251 | } | ||
252 | } | ||
253 | } | ||
254 | |||
255 | impl TypeWalk for GenericArg { | ||
256 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
257 | match &self.interned() { | ||
258 | GenericArgData::Ty(ty) => { | ||
259 | ty.walk(f); | ||
260 | } | ||
261 | } | ||
262 | } | ||
263 | |||
264 | fn walk_mut_binders( | ||
265 | &mut self, | ||
266 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
267 | binders: DebruijnIndex, | ||
268 | ) { | ||
269 | match self.interned_mut() { | ||
270 | GenericArgData::Ty(ty) => { | ||
271 | ty.walk_mut_binders(f, binders); | ||
272 | } | ||
273 | } | ||
274 | } | ||
275 | } | ||
276 | |||
277 | impl TypeWalk for Substitution { | ||
278 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
279 | for t in self.iter(&Interner) { | ||
280 | t.walk(f); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | fn walk_mut_binders( | ||
285 | &mut self, | ||
286 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
287 | binders: DebruijnIndex, | ||
288 | ) { | ||
289 | for t in self.interned_mut() { | ||
290 | t.walk_mut_binders(f, binders); | ||
291 | } | ||
292 | } | ||
293 | } | ||
294 | |||
295 | impl<T: TypeWalk> TypeWalk for Binders<T> { | ||
296 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
297 | self.value.walk(f); | ||
298 | } | ||
299 | |||
300 | fn walk_mut_binders( | ||
301 | &mut self, | ||
302 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
303 | binders: DebruijnIndex, | ||
304 | ) { | ||
305 | self.value.walk_mut_binders(f, binders.shifted_in()) | ||
306 | } | ||
307 | } | ||
308 | |||
309 | impl TypeWalk for TraitRef { | ||
310 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
311 | self.substitution.walk(f); | ||
312 | } | ||
313 | |||
314 | fn walk_mut_binders( | ||
315 | &mut self, | ||
316 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
317 | binders: DebruijnIndex, | ||
318 | ) { | ||
319 | self.substitution.walk_mut_binders(f, binders); | ||
320 | } | ||
321 | } | ||
322 | |||
323 | impl TypeWalk for WhereClause { | ||
324 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
325 | match self { | ||
326 | WhereClause::Implemented(trait_ref) => trait_ref.walk(f), | ||
327 | WhereClause::AliasEq(alias_eq) => alias_eq.walk(f), | ||
328 | } | ||
329 | } | ||
330 | |||
331 | fn walk_mut_binders( | ||
332 | &mut self, | ||
333 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
334 | binders: DebruijnIndex, | ||
335 | ) { | ||
336 | match self { | ||
337 | WhereClause::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders), | ||
338 | WhereClause::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders), | ||
339 | } | ||
340 | } | ||
341 | } | ||
342 | |||
343 | impl TypeWalk for CallableSig { | ||
344 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
345 | for t in self.params_and_return.iter() { | ||
346 | t.walk(f); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | fn walk_mut_binders( | ||
351 | &mut self, | ||
352 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
353 | binders: DebruijnIndex, | ||
354 | ) { | ||
355 | for t in make_mut_slice(&mut self.params_and_return) { | ||
356 | t.walk_mut_binders(f, binders); | ||
357 | } | ||
358 | } | ||
359 | } | ||
360 | |||
361 | impl TypeWalk for AliasEq { | ||
362 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
363 | self.ty.walk(f); | ||
364 | match &self.alias { | ||
365 | AliasTy::Projection(projection_ty) => projection_ty.walk(f), | ||
366 | AliasTy::Opaque(opaque) => opaque.walk(f), | ||
367 | } | ||
368 | } | ||
369 | |||
370 | fn walk_mut_binders( | ||
371 | &mut self, | ||
372 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
373 | binders: DebruijnIndex, | ||
374 | ) { | ||
375 | self.ty.walk_mut_binders(f, binders); | ||
376 | match &mut self.alias { | ||
377 | AliasTy::Projection(projection_ty) => projection_ty.walk_mut_binders(f, binders), | ||
378 | AliasTy::Opaque(opaque) => opaque.walk_mut_binders(f, binders), | ||
379 | } | ||
380 | } | ||
381 | } | ||