diff options
Diffstat (limited to 'crates/ra_hir_ty/src')
22 files changed, 1931 insertions, 907 deletions
diff --git a/crates/ra_hir_ty/src/_match.rs b/crates/ra_hir_ty/src/_match.rs index 149f65042..3e6e1e333 100644 --- a/crates/ra_hir_ty/src/_match.rs +++ b/crates/ra_hir_ty/src/_match.rs | |||
@@ -1946,6 +1946,23 @@ mod tests { | |||
1946 | 1946 | ||
1947 | check_no_diagnostic(content); | 1947 | check_no_diagnostic(content); |
1948 | } | 1948 | } |
1949 | |||
1950 | #[test] | ||
1951 | fn expr_diverges_missing_arm() { | ||
1952 | let content = r" | ||
1953 | enum Either { | ||
1954 | A, | ||
1955 | B, | ||
1956 | } | ||
1957 | fn test_fn() { | ||
1958 | match loop {} { | ||
1959 | Either::A => (), | ||
1960 | } | ||
1961 | } | ||
1962 | "; | ||
1963 | |||
1964 | check_no_diagnostic(content); | ||
1965 | } | ||
1949 | } | 1966 | } |
1950 | 1967 | ||
1951 | #[cfg(test)] | 1968 | #[cfg(test)] |
@@ -1998,26 +2015,6 @@ mod false_negatives { | |||
1998 | } | 2015 | } |
1999 | 2016 | ||
2000 | #[test] | 2017 | #[test] |
2001 | fn expr_diverges_missing_arm() { | ||
2002 | let content = r" | ||
2003 | enum Either { | ||
2004 | A, | ||
2005 | B, | ||
2006 | } | ||
2007 | fn test_fn() { | ||
2008 | match loop {} { | ||
2009 | Either::A => (), | ||
2010 | } | ||
2011 | } | ||
2012 | "; | ||
2013 | |||
2014 | // This is a false negative. | ||
2015 | // Even though the match expression diverges, rustc fails | ||
2016 | // to compile here since `Either::B` is missing. | ||
2017 | check_no_diagnostic(content); | ||
2018 | } | ||
2019 | |||
2020 | #[test] | ||
2021 | fn expr_loop_missing_arm() { | 2018 | fn expr_loop_missing_arm() { |
2022 | let content = r" | 2019 | let content = r" |
2023 | enum Either { | 2020 | enum Either { |
@@ -2035,7 +2032,7 @@ mod false_negatives { | |||
2035 | // We currently infer the type of `loop { break Foo::A }` to `!`, which | 2032 | // We currently infer the type of `loop { break Foo::A }` to `!`, which |
2036 | // causes us to skip the diagnostic since `Either::A` doesn't type check | 2033 | // causes us to skip the diagnostic since `Either::A` doesn't type check |
2037 | // with `!`. | 2034 | // with `!`. |
2038 | check_no_diagnostic(content); | 2035 | check_diagnostic(content); |
2039 | } | 2036 | } |
2040 | 2037 | ||
2041 | #[test] | 2038 | #[test] |
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index fdb49560b..0a8bb24ac 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs | |||
@@ -76,6 +76,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
76 | #[salsa::interned] | 76 | #[salsa::interned] |
77 | fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId; | 77 | fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId; |
78 | #[salsa::interned] | 78 | #[salsa::interned] |
79 | fn intern_callable_def(&self, callable_def: CallableDef) -> crate::CallableDefId; | ||
80 | #[salsa::interned] | ||
79 | fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId; | 81 | fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId; |
80 | #[salsa::interned] | 82 | #[salsa::interned] |
81 | fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId; | 83 | fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId; |
@@ -89,11 +91,14 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
89 | fn trait_datum(&self, krate: CrateId, trait_id: chalk::TraitId) -> Arc<chalk::TraitDatum>; | 91 | fn trait_datum(&self, krate: CrateId, trait_id: chalk::TraitId) -> Arc<chalk::TraitDatum>; |
90 | 92 | ||
91 | #[salsa::invoke(chalk::struct_datum_query)] | 93 | #[salsa::invoke(chalk::struct_datum_query)] |
92 | fn struct_datum(&self, krate: CrateId, struct_id: chalk::StructId) -> Arc<chalk::StructDatum>; | 94 | fn struct_datum(&self, krate: CrateId, struct_id: chalk::AdtId) -> Arc<chalk::StructDatum>; |
93 | 95 | ||
94 | #[salsa::invoke(crate::traits::chalk::impl_datum_query)] | 96 | #[salsa::invoke(crate::traits::chalk::impl_datum_query)] |
95 | fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc<chalk::ImplDatum>; | 97 | fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc<chalk::ImplDatum>; |
96 | 98 | ||
99 | #[salsa::invoke(crate::traits::chalk::fn_def_datum_query)] | ||
100 | fn fn_def_datum(&self, krate: CrateId, fn_def_id: chalk::FnDefId) -> Arc<chalk::FnDefDatum>; | ||
101 | |||
97 | #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)] | 102 | #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)] |
98 | fn associated_ty_value( | 103 | fn associated_ty_value( |
99 | &self, | 104 | &self, |
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index fb7c6cd8c..957d6e0b5 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs | |||
@@ -28,7 +28,8 @@ use hir_def::{ | |||
28 | path::{path, Path}, | 28 | path::{path, Path}, |
29 | resolver::{HasResolver, Resolver, TypeNs}, | 29 | resolver::{HasResolver, Resolver, TypeNs}, |
30 | type_ref::{Mutability, TypeRef}, | 30 | type_ref::{Mutability, TypeRef}, |
31 | AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, TraitId, TypeAliasId, VariantId, | 31 | AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, TraitId, TypeAliasId, |
32 | VariantId, | ||
32 | }; | 33 | }; |
33 | use hir_expand::{diagnostics::DiagnosticSink, name::name}; | 34 | use hir_expand::{diagnostics::DiagnosticSink, name::name}; |
34 | use ra_arena::map::ArenaMap; | 35 | use ra_arena::map::ArenaMap; |
@@ -217,6 +218,7 @@ struct InferenceContext<'a> { | |||
217 | #[derive(Clone, Debug)] | 218 | #[derive(Clone, Debug)] |
218 | struct BreakableContext { | 219 | struct BreakableContext { |
219 | pub may_break: bool, | 220 | pub may_break: bool, |
221 | pub break_ty: Ty, | ||
220 | } | 222 | } |
221 | 223 | ||
222 | impl<'a> InferenceContext<'a> { | 224 | impl<'a> InferenceContext<'a> { |
@@ -438,43 +440,95 @@ impl<'a> InferenceContext<'a> { | |||
438 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); | 440 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); |
439 | // FIXME: this should resolve assoc items as well, see this example: | 441 | // FIXME: this should resolve assoc items as well, see this example: |
440 | // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 | 442 | // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 |
441 | return match resolver.resolve_path_in_type_ns_fully(self.db.upcast(), path.mod_path()) { | 443 | let (resolution, unresolved) = |
442 | Some(TypeNs::AdtId(AdtId::StructId(strukt))) => { | 444 | match resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) { |
445 | Some(it) => it, | ||
446 | None => return (Ty::Unknown, None), | ||
447 | }; | ||
448 | return match resolution { | ||
449 | TypeNs::AdtId(AdtId::StructId(strukt)) => { | ||
443 | let substs = Ty::substs_from_path(&ctx, path, strukt.into()); | 450 | let substs = Ty::substs_from_path(&ctx, path, strukt.into()); |
444 | let ty = self.db.ty(strukt.into()); | 451 | let ty = self.db.ty(strukt.into()); |
445 | let ty = self.insert_type_vars(ty.subst(&substs)); | 452 | let ty = self.insert_type_vars(ty.subst(&substs)); |
446 | (ty, Some(strukt.into())) | 453 | forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) |
447 | } | 454 | } |
448 | Some(TypeNs::EnumVariantId(var)) => { | 455 | TypeNs::EnumVariantId(var) => { |
449 | let substs = Ty::substs_from_path(&ctx, path, var.into()); | 456 | let substs = Ty::substs_from_path(&ctx, path, var.into()); |
450 | let ty = self.db.ty(var.parent.into()); | 457 | let ty = self.db.ty(var.parent.into()); |
451 | let ty = self.insert_type_vars(ty.subst(&substs)); | 458 | let ty = self.insert_type_vars(ty.subst(&substs)); |
452 | (ty, Some(var.into())) | 459 | forbid_unresolved_segments((ty, Some(var.into())), unresolved) |
453 | } | 460 | } |
454 | Some(TypeNs::SelfType(impl_id)) => { | 461 | TypeNs::SelfType(impl_id) => { |
455 | let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); | 462 | let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); |
456 | let substs = Substs::type_params_for_generics(&generics); | 463 | let substs = Substs::type_params_for_generics(&generics); |
457 | let ty = self.db.impl_self_ty(impl_id).subst(&substs); | 464 | let ty = self.db.impl_self_ty(impl_id).subst(&substs); |
458 | let variant = ty_variant(&ty); | 465 | match unresolved { |
459 | (ty, variant) | 466 | None => { |
467 | let variant = ty_variant(&ty); | ||
468 | (ty, variant) | ||
469 | } | ||
470 | Some(1) => { | ||
471 | let segment = path.mod_path().segments.last().unwrap(); | ||
472 | // this could be an enum variant or associated type | ||
473 | if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() { | ||
474 | let enum_data = self.db.enum_data(enum_id); | ||
475 | if let Some(local_id) = enum_data.variant(segment) { | ||
476 | let variant = EnumVariantId { parent: enum_id, local_id }; | ||
477 | return (ty, Some(variant.into())); | ||
478 | } | ||
479 | } | ||
480 | // FIXME potentially resolve assoc type | ||
481 | (Ty::Unknown, None) | ||
482 | } | ||
483 | Some(_) => { | ||
484 | // FIXME diagnostic | ||
485 | (Ty::Unknown, None) | ||
486 | } | ||
487 | } | ||
460 | } | 488 | } |
461 | Some(TypeNs::TypeAliasId(it)) => { | 489 | TypeNs::TypeAliasId(it) => { |
462 | let substs = Substs::build_for_def(self.db, it) | 490 | let substs = Substs::build_for_def(self.db, it) |
463 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) | 491 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) |
464 | .build(); | 492 | .build(); |
465 | let ty = self.db.ty(it.into()).subst(&substs); | 493 | let ty = self.db.ty(it.into()).subst(&substs); |
466 | let variant = ty_variant(&ty); | 494 | let variant = ty_variant(&ty); |
467 | (ty, variant) | 495 | forbid_unresolved_segments((ty, variant), unresolved) |
496 | } | ||
497 | TypeNs::AdtSelfType(_) => { | ||
498 | // FIXME this could happen in array size expressions, once we're checking them | ||
499 | (Ty::Unknown, None) | ||
500 | } | ||
501 | TypeNs::GenericParam(_) => { | ||
502 | // FIXME potentially resolve assoc type | ||
503 | (Ty::Unknown, None) | ||
504 | } | ||
505 | TypeNs::AdtId(AdtId::EnumId(_)) | ||
506 | | TypeNs::AdtId(AdtId::UnionId(_)) | ||
507 | | TypeNs::BuiltinType(_) | ||
508 | | TypeNs::TraitId(_) => { | ||
509 | // FIXME diagnostic | ||
510 | (Ty::Unknown, None) | ||
468 | } | 511 | } |
469 | Some(_) | None => (Ty::Unknown, None), | ||
470 | }; | 512 | }; |
471 | 513 | ||
514 | fn forbid_unresolved_segments( | ||
515 | result: (Ty, Option<VariantId>), | ||
516 | unresolved: Option<usize>, | ||
517 | ) -> (Ty, Option<VariantId>) { | ||
518 | if unresolved.is_none() { | ||
519 | result | ||
520 | } else { | ||
521 | // FIXME diagnostic | ||
522 | (Ty::Unknown, None) | ||
523 | } | ||
524 | } | ||
525 | |||
472 | fn ty_variant(ty: &Ty) -> Option<VariantId> { | 526 | fn ty_variant(ty: &Ty) -> Option<VariantId> { |
473 | ty.as_adt().and_then(|(adt_id, _)| match adt_id { | 527 | ty.as_adt().and_then(|(adt_id, _)| match adt_id { |
474 | AdtId::StructId(s) => Some(VariantId::StructId(s)), | 528 | AdtId::StructId(s) => Some(VariantId::StructId(s)), |
475 | AdtId::UnionId(u) => Some(VariantId::UnionId(u)), | 529 | AdtId::UnionId(u) => Some(VariantId::UnionId(u)), |
476 | AdtId::EnumId(_) => { | 530 | AdtId::EnumId(_) => { |
477 | // Error E0071, expected struct, variant or union type, found enum `Foo` | 531 | // FIXME Error E0071, expected struct, variant or union type, found enum `Foo` |
478 | None | 532 | None |
479 | } | 533 | } |
480 | }) | 534 | }) |
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs index 173ec59ed..2ee9adb16 100644 --- a/crates/ra_hir_ty/src/infer/coerce.rs +++ b/crates/ra_hir_ty/src/infer/coerce.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html | 5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html |
6 | 6 | ||
7 | use hir_def::{lang_item::LangItemTarget, type_ref::Mutability}; | 7 | use hir_def::{lang_item::LangItemTarget, type_ref::Mutability}; |
8 | use test_utils::tested_by; | 8 | use test_utils::mark; |
9 | 9 | ||
10 | use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty, TypeCtor}; | 10 | use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty, TypeCtor}; |
11 | 11 | ||
@@ -34,7 +34,7 @@ impl<'a> InferenceContext<'a> { | |||
34 | ty1.clone() | 34 | ty1.clone() |
35 | } else { | 35 | } else { |
36 | if let (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnDef(_))) = (ty1, ty2) { | 36 | if let (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnDef(_))) = (ty1, ty2) { |
37 | tested_by!(coerce_fn_reification); | 37 | mark::hit!(coerce_fn_reification); |
38 | // Special case: two function types. Try to coerce both to | 38 | // Special case: two function types. Try to coerce both to |
39 | // pointers to have a chance at getting a match. See | 39 | // pointers to have a chance at getting a match. See |
40 | // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916 | 40 | // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916 |
@@ -44,7 +44,7 @@ impl<'a> InferenceContext<'a> { | |||
44 | let ptr_ty2 = Ty::fn_ptr(sig2); | 44 | let ptr_ty2 = Ty::fn_ptr(sig2); |
45 | self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) | 45 | self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) |
46 | } else { | 46 | } else { |
47 | tested_by!(coerce_merge_fail_fallback); | 47 | mark::hit!(coerce_merge_fail_fallback); |
48 | // For incompatible types, we use the latter one as result | 48 | // For incompatible types, we use the latter one as result |
49 | // to be better recovery for `if` without `else`. | 49 | // to be better recovery for `if` without `else`. |
50 | ty2.clone() | 50 | ty2.clone() |
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 0b67d216a..b28724f0e 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -93,22 +93,25 @@ impl<'a> InferenceContext<'a> { | |||
93 | Ty::Unknown | 93 | Ty::Unknown |
94 | } | 94 | } |
95 | Expr::Loop { body } => { | 95 | Expr::Loop { body } => { |
96 | self.breakables.push(BreakableContext { may_break: false }); | 96 | self.breakables.push(BreakableContext { |
97 | may_break: false, | ||
98 | break_ty: self.table.new_type_var(), | ||
99 | }); | ||
97 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 100 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); |
98 | 101 | ||
99 | let ctxt = self.breakables.pop().expect("breakable stack broken"); | 102 | let ctxt = self.breakables.pop().expect("breakable stack broken"); |
100 | if ctxt.may_break { | 103 | if ctxt.may_break { |
101 | self.diverges = Diverges::Maybe; | 104 | self.diverges = Diverges::Maybe; |
102 | } | 105 | } |
103 | // FIXME handle break with value | 106 | |
104 | if ctxt.may_break { | 107 | if ctxt.may_break { |
105 | Ty::unit() | 108 | ctxt.break_ty |
106 | } else { | 109 | } else { |
107 | Ty::simple(TypeCtor::Never) | 110 | Ty::simple(TypeCtor::Never) |
108 | } | 111 | } |
109 | } | 112 | } |
110 | Expr::While { condition, body } => { | 113 | Expr::While { condition, body } => { |
111 | self.breakables.push(BreakableContext { may_break: false }); | 114 | self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown }); |
112 | // while let is desugared to a match loop, so this is always simple while | 115 | // while let is desugared to a match loop, so this is always simple while |
113 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); | 116 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); |
114 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 117 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); |
@@ -120,7 +123,7 @@ impl<'a> InferenceContext<'a> { | |||
120 | Expr::For { iterable, body, pat } => { | 123 | Expr::For { iterable, body, pat } => { |
121 | let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); | 124 | let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); |
122 | 125 | ||
123 | self.breakables.push(BreakableContext { may_break: false }); | 126 | self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown }); |
124 | let pat_ty = | 127 | let pat_ty = |
125 | self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); | 128 | self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); |
126 | 129 | ||
@@ -229,17 +232,29 @@ impl<'a> InferenceContext<'a> { | |||
229 | } | 232 | } |
230 | Expr::Continue => Ty::simple(TypeCtor::Never), | 233 | Expr::Continue => Ty::simple(TypeCtor::Never), |
231 | Expr::Break { expr } => { | 234 | Expr::Break { expr } => { |
232 | if let Some(expr) = expr { | 235 | let val_ty = if let Some(expr) = expr { |
233 | // FIXME handle break with value | 236 | self.infer_expr(*expr, &Expectation::none()) |
234 | self.infer_expr(*expr, &Expectation::none()); | 237 | } else { |
235 | } | 238 | Ty::unit() |
239 | }; | ||
240 | |||
241 | let last_ty = if let Some(ctxt) = self.breakables.last() { | ||
242 | ctxt.break_ty.clone() | ||
243 | } else { | ||
244 | Ty::Unknown | ||
245 | }; | ||
246 | |||
247 | let merged_type = self.coerce_merge_branch(&last_ty, &val_ty); | ||
248 | |||
236 | if let Some(ctxt) = self.breakables.last_mut() { | 249 | if let Some(ctxt) = self.breakables.last_mut() { |
250 | ctxt.break_ty = merged_type; | ||
237 | ctxt.may_break = true; | 251 | ctxt.may_break = true; |
238 | } else { | 252 | } else { |
239 | self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop { | 253 | self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop { |
240 | expr: tgt_expr, | 254 | expr: tgt_expr, |
241 | }); | 255 | }); |
242 | } | 256 | } |
257 | |||
243 | Ty::simple(TypeCtor::Never) | 258 | Ty::simple(TypeCtor::Never) |
244 | } | 259 | } |
245 | Expr::Return { expr } => { | 260 | Expr::Return { expr } => { |
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs index 54ec870df..4006f595d 100644 --- a/crates/ra_hir_ty/src/infer/pat.rs +++ b/crates/ra_hir_ty/src/infer/pat.rs | |||
@@ -10,7 +10,7 @@ use hir_def::{ | |||
10 | FieldId, | 10 | FieldId, |
11 | }; | 11 | }; |
12 | use hir_expand::name::Name; | 12 | use hir_expand::name::Name; |
13 | use test_utils::tested_by; | 13 | use test_utils::mark; |
14 | 14 | ||
15 | use super::{BindingMode, Expectation, InferenceContext}; | 15 | use super::{BindingMode, Expectation, InferenceContext}; |
16 | use crate::{utils::variant_data, Substs, Ty, TypeCtor}; | 16 | use crate::{utils::variant_data, Substs, Ty, TypeCtor}; |
@@ -111,7 +111,7 @@ impl<'a> InferenceContext<'a> { | |||
111 | } | 111 | } |
112 | } | 112 | } |
113 | } else if let Pat::Ref { .. } = &body[pat] { | 113 | } else if let Pat::Ref { .. } = &body[pat] { |
114 | tested_by!(match_ergonomics_ref); | 114 | mark::hit!(match_ergonomics_ref); |
115 | // When you encounter a `&pat` pattern, reset to Move. | 115 | // When you encounter a `&pat` pattern, reset to Move. |
116 | // This is so that `w` is by value: `let (_, &w) = &(1, &2);` | 116 | // This is so that `w` is by value: `let (_, &w) = &(1, &2);` |
117 | default_bm = BindingMode::Move; | 117 | default_bm = BindingMode::Move; |
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index 2b6bc0f79..1c2e56fb0 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs | |||
@@ -5,7 +5,7 @@ use std::iter; | |||
5 | use hir_def::{ | 5 | use hir_def::{ |
6 | path::{Path, PathSegment}, | 6 | path::{Path, PathSegment}, |
7 | resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, | 7 | resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, |
8 | AssocContainerId, AssocItemId, Lookup, | 8 | AdtId, AssocContainerId, AssocItemId, EnumVariantId, Lookup, |
9 | }; | 9 | }; |
10 | use hir_expand::name::Name; | 10 | use hir_expand::name::Name; |
11 | 11 | ||
@@ -77,6 +77,18 @@ impl<'a> InferenceContext<'a> { | |||
77 | 77 | ||
78 | it.into() | 78 | it.into() |
79 | } | 79 | } |
80 | ValueNs::ImplSelf(impl_id) => { | ||
81 | let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); | ||
82 | let substs = Substs::type_params_for_generics(&generics); | ||
83 | let ty = self.db.impl_self_ty(impl_id).subst(&substs); | ||
84 | if let Some((AdtId::StructId(struct_id), _)) = ty.as_adt() { | ||
85 | let ty = self.db.value_ty(struct_id.into()).subst(&substs); | ||
86 | return Some(ty); | ||
87 | } else { | ||
88 | // FIXME: diagnostic, invalid Self reference | ||
89 | return None; | ||
90 | } | ||
91 | } | ||
80 | }; | 92 | }; |
81 | 93 | ||
82 | let ty = self.db.value_ty(typable); | 94 | let ty = self.db.value_ty(typable); |
@@ -199,6 +211,10 @@ impl<'a> InferenceContext<'a> { | |||
199 | return None; | 211 | return None; |
200 | } | 212 | } |
201 | 213 | ||
214 | if let Some(result) = self.resolve_enum_variant_on_ty(&ty, name, id) { | ||
215 | return Some(result); | ||
216 | } | ||
217 | |||
202 | let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone()); | 218 | let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone()); |
203 | let krate = self.resolver.krate()?; | 219 | let krate = self.resolver.krate()?; |
204 | let traits_in_scope = self.resolver.traits_in_scope(self.db.upcast()); | 220 | let traits_in_scope = self.resolver.traits_in_scope(self.db.upcast()); |
@@ -250,4 +266,21 @@ impl<'a> InferenceContext<'a> { | |||
250 | }, | 266 | }, |
251 | ) | 267 | ) |
252 | } | 268 | } |
269 | |||
270 | fn resolve_enum_variant_on_ty( | ||
271 | &mut self, | ||
272 | ty: &Ty, | ||
273 | name: &Name, | ||
274 | id: ExprOrPatId, | ||
275 | ) -> Option<(ValueNs, Option<Substs>)> { | ||
276 | let (enum_id, subst) = match ty.as_adt() { | ||
277 | Some((AdtId::EnumId(e), subst)) => (e, subst), | ||
278 | _ => return None, | ||
279 | }; | ||
280 | let enum_data = self.db.enum_data(enum_id); | ||
281 | let local_id = enum_data.variant(name)?; | ||
282 | let variant = EnumVariantId { parent: enum_id, local_id }; | ||
283 | self.write_variant_resolution(id, variant.into()); | ||
284 | Some((ValueNs::EnumVariantId(variant), Some(subst.clone()))) | ||
285 | } | ||
253 | } | 286 | } |
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs index ab0bc8b70..269495ca0 100644 --- a/crates/ra_hir_ty/src/infer/unify.rs +++ b/crates/ra_hir_ty/src/infer/unify.rs | |||
@@ -4,7 +4,7 @@ use std::borrow::Cow; | |||
4 | 4 | ||
5 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; | 5 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; |
6 | 6 | ||
7 | use test_utils::tested_by; | 7 | use test_utils::mark; |
8 | 8 | ||
9 | use super::{InferenceContext, Obligation}; | 9 | use super::{InferenceContext, Obligation}; |
10 | use crate::{ | 10 | use crate::{ |
@@ -313,7 +313,7 @@ impl InferenceTable { | |||
313 | // more than once | 313 | // more than once |
314 | for i in 0..3 { | 314 | for i in 0..3 { |
315 | if i > 0 { | 315 | if i > 0 { |
316 | tested_by!(type_var_resolves_to_int_var); | 316 | mark::hit!(type_var_resolves_to_int_var); |
317 | } | 317 | } |
318 | match &*ty { | 318 | match &*ty { |
319 | Ty::Infer(tv) => { | 319 | Ty::Infer(tv) => { |
@@ -342,7 +342,7 @@ impl InferenceTable { | |||
342 | Ty::Infer(tv) => { | 342 | Ty::Infer(tv) => { |
343 | let inner = tv.to_inner(); | 343 | let inner = tv.to_inner(); |
344 | if tv_stack.contains(&inner) { | 344 | if tv_stack.contains(&inner) { |
345 | tested_by!(type_var_cycles_resolve_as_possible); | 345 | mark::hit!(type_var_cycles_resolve_as_possible); |
346 | // recursive type | 346 | // recursive type |
347 | return tv.fallback_value(); | 347 | return tv.fallback_value(); |
348 | } | 348 | } |
@@ -369,7 +369,7 @@ impl InferenceTable { | |||
369 | Ty::Infer(tv) => { | 369 | Ty::Infer(tv) => { |
370 | let inner = tv.to_inner(); | 370 | let inner = tv.to_inner(); |
371 | if tv_stack.contains(&inner) { | 371 | if tv_stack.contains(&inner) { |
372 | tested_by!(type_var_cycles_resolve_completely); | 372 | mark::hit!(type_var_cycles_resolve_completely); |
373 | // recursive type | 373 | // recursive type |
374 | return tv.fallback_value(); | 374 | return tv.fallback_value(); |
375 | } | 375 | } |
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index e8f3482fe..93cb45a64 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -42,7 +42,6 @@ pub mod expr; | |||
42 | mod tests; | 42 | mod tests; |
43 | #[cfg(test)] | 43 | #[cfg(test)] |
44 | mod test_db; | 44 | mod test_db; |
45 | mod marks; | ||
46 | mod _match; | 45 | mod _match; |
47 | 46 | ||
48 | use std::ops::Deref; | 47 | use std::ops::Deref; |
@@ -156,10 +155,16 @@ pub enum TypeCtor { | |||
156 | /// This exists just for Chalk, because Chalk just has a single `StructId` where | 155 | /// This exists just for Chalk, because Chalk just has a single `StructId` where |
157 | /// we have different kinds of ADTs, primitive types and special type | 156 | /// we have different kinds of ADTs, primitive types and special type |
158 | /// constructors like tuples and function pointers. | 157 | /// constructors like tuples and function pointers. |
159 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 158 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] |
160 | pub struct TypeCtorId(salsa::InternId); | 159 | pub struct TypeCtorId(salsa::InternId); |
161 | impl_intern_key!(TypeCtorId); | 160 | impl_intern_key!(TypeCtorId); |
162 | 161 | ||
162 | /// This exists just for Chalk, because Chalk just has a single `FnDefId` where | ||
163 | /// we have different IDs for struct and enum variant constructors. | ||
164 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] | ||
165 | pub struct CallableDefId(salsa::InternId); | ||
166 | impl_intern_key!(CallableDefId); | ||
167 | |||
163 | impl TypeCtor { | 168 | impl TypeCtor { |
164 | pub fn num_ty_params(self, db: &dyn HirDatabase) -> usize { | 169 | pub fn num_ty_params(self, db: &dyn HirDatabase) -> usize { |
165 | match self { | 170 | match self { |
@@ -427,6 +432,11 @@ impl Substs { | |||
427 | } | 432 | } |
428 | } | 433 | } |
429 | 434 | ||
435 | /// Return an index of a parameter in the generic type parameter list by it's id. | ||
436 | pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> { | ||
437 | generics(db.upcast(), id.parent).param_idx(id) | ||
438 | } | ||
439 | |||
430 | #[derive(Debug, Clone)] | 440 | #[derive(Debug, Clone)] |
431 | pub struct SubstsBuilder { | 441 | pub struct SubstsBuilder { |
432 | vec: Vec<Ty>, | 442 | vec: Vec<Ty>, |
@@ -803,15 +813,13 @@ impl Ty { | |||
803 | } | 813 | } |
804 | } | 814 | } |
805 | 815 | ||
806 | /// If this is an `impl Trait` or `dyn Trait`, returns that trait. | 816 | /// If this is a `dyn Trait`, returns that trait. |
807 | pub fn inherent_trait(&self) -> Option<TraitId> { | 817 | pub fn dyn_trait(&self) -> Option<TraitId> { |
808 | match self { | 818 | match self { |
809 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | 819 | Ty::Dyn(predicates) => predicates.iter().find_map(|pred| match pred { |
810 | predicates.iter().find_map(|pred| match pred { | 820 | GenericPredicate::Implemented(tr) => Some(tr.trait_), |
811 | GenericPredicate::Implemented(tr) => Some(tr.trait_), | 821 | _ => None, |
812 | _ => None, | 822 | }), |
813 | }) | ||
814 | } | ||
815 | _ => None, | 823 | _ => None, |
816 | } | 824 | } |
817 | } | 825 | } |
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 9ad6dbe07..35ac86a46 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -812,7 +812,7 @@ impl TraitEnvironment { | |||
812 | // add `Self: Trait<T1, T2, ...>` to the environment in trait | 812 | // add `Self: Trait<T1, T2, ...>` to the environment in trait |
813 | // function default implementations (and hypothetical code | 813 | // function default implementations (and hypothetical code |
814 | // inside consts or type aliases) | 814 | // inside consts or type aliases) |
815 | test_utils::tested_by!(trait_self_implements_self); | 815 | test_utils::mark::hit!(trait_self_implements_self); |
816 | let substs = Substs::type_params(db, trait_id); | 816 | let substs = Substs::type_params(db, trait_id); |
817 | let trait_ref = TraitRef { trait_: trait_id, substs }; | 817 | let trait_ref = TraitRef { trait_: trait_id, substs }; |
818 | let pred = GenericPredicate::Implemented(trait_ref); | 818 | let pred = GenericPredicate::Implemented(trait_ref); |
diff --git a/crates/ra_hir_ty/src/marks.rs b/crates/ra_hir_ty/src/marks.rs deleted file mode 100644 index a39740143..000000000 --- a/crates/ra_hir_ty/src/marks.rs +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | //! See test_utils/src/marks.rs | ||
2 | |||
3 | test_utils::marks!( | ||
4 | type_var_cycles_resolve_completely | ||
5 | type_var_cycles_resolve_as_possible | ||
6 | type_var_resolves_to_int_var | ||
7 | impl_self_type_match_without_receiver | ||
8 | match_ergonomics_ref | ||
9 | coerce_merge_fail_fallback | ||
10 | coerce_fn_reification | ||
11 | trait_self_implements_self | ||
12 | ); | ||
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 657284fd0..e19628fdf 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -408,8 +408,9 @@ fn iterate_trait_method_candidates<T>( | |||
408 | receiver_ty: Option<&Canonical<Ty>>, | 408 | receiver_ty: Option<&Canonical<Ty>>, |
409 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 409 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
410 | ) -> Option<T> { | 410 | ) -> Option<T> { |
411 | // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope | 411 | // if ty is `dyn Trait`, the trait doesn't need to be in scope |
412 | let inherent_trait = self_ty.value.inherent_trait().into_iter(); | 412 | let inherent_trait = |
413 | self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); | ||
413 | let env_traits = if let Ty::Placeholder(_) = self_ty.value { | 414 | let env_traits = if let Ty::Placeholder(_) = self_ty.value { |
414 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope | 415 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope |
415 | env.trait_predicates_for_self_ty(&self_ty.value) | 416 | env.trait_predicates_for_self_ty(&self_ty.value) |
@@ -468,7 +469,7 @@ fn iterate_inherent_methods<T>( | |||
468 | // already happens in `is_valid_candidate` above; if not, we | 469 | // already happens in `is_valid_candidate` above; if not, we |
469 | // check it here | 470 | // check it here |
470 | if receiver_ty.is_none() && inherent_impl_substs(db, impl_def, self_ty).is_none() { | 471 | if receiver_ty.is_none() && inherent_impl_substs(db, impl_def, self_ty).is_none() { |
471 | test_utils::tested_by!(impl_self_type_match_without_receiver); | 472 | test_utils::mark::hit!(impl_self_type_match_without_receiver); |
472 | continue; | 473 | continue; |
473 | } | 474 | } |
474 | if let Some(result) = callback(&self_ty.value, item) { | 475 | if let Some(result) = callback(&self_ty.value, item) { |
@@ -601,11 +602,6 @@ pub fn implements_trait( | |||
601 | krate: CrateId, | 602 | krate: CrateId, |
602 | trait_: TraitId, | 603 | trait_: TraitId, |
603 | ) -> bool { | 604 | ) -> bool { |
604 | if ty.value.inherent_trait() == Some(trait_) { | ||
605 | // FIXME this is a bit of a hack, since Chalk should say the same thing | ||
606 | // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet | ||
607 | return true; | ||
608 | } | ||
609 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); | 605 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); |
610 | let solution = db.trait_solve(krate, goal); | 606 | let solution = db.trait_solve(krate, goal); |
611 | 607 | ||
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs index 6dc4b2cd1..2cc4f4bf9 100644 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ b/crates/ra_hir_ty/src/tests/coercion.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use super::infer_with_mismatches; | 1 | use super::infer_with_mismatches; |
2 | use insta::assert_snapshot; | 2 | use insta::assert_snapshot; |
3 | use test_utils::covers; | 3 | use test_utils::mark; |
4 | 4 | ||
5 | // Infer with some common definitions and impls. | 5 | // Infer with some common definitions and impls. |
6 | fn infer(source: &str) -> String { | 6 | fn infer(source: &str) -> String { |
@@ -339,7 +339,7 @@ fn test(i: i32) { | |||
339 | 339 | ||
340 | #[test] | 340 | #[test] |
341 | fn coerce_merge_one_by_one1() { | 341 | fn coerce_merge_one_by_one1() { |
342 | covers!(coerce_merge_fail_fallback); | 342 | mark::check!(coerce_merge_fail_fallback); |
343 | 343 | ||
344 | assert_snapshot!( | 344 | assert_snapshot!( |
345 | infer(r#" | 345 | infer(r#" |
@@ -547,7 +547,7 @@ fn test() { | |||
547 | 547 | ||
548 | #[test] | 548 | #[test] |
549 | fn coerce_fn_items_in_match_arms() { | 549 | fn coerce_fn_items_in_match_arms() { |
550 | covers!(coerce_fn_reification); | 550 | mark::check!(coerce_fn_reification); |
551 | assert_snapshot!( | 551 | assert_snapshot!( |
552 | infer_with_mismatches(r#" | 552 | infer_with_mismatches(r#" |
553 | fn foo1(x: u32) -> isize { 1 } | 553 | fn foo1(x: u32) -> isize { 1 } |
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs index 67f964ab5..558a70022 100644 --- a/crates/ra_hir_ty/src/tests/method_resolution.rs +++ b/crates/ra_hir_ty/src/tests/method_resolution.rs | |||
@@ -984,7 +984,7 @@ fn test() { S2.into()<|>; } | |||
984 | 984 | ||
985 | #[test] | 985 | #[test] |
986 | fn method_resolution_overloaded_method() { | 986 | fn method_resolution_overloaded_method() { |
987 | test_utils::covers!(impl_self_type_match_without_receiver); | 987 | test_utils::mark::check!(impl_self_type_match_without_receiver); |
988 | let t = type_at( | 988 | let t = type_at( |
989 | r#" | 989 | r#" |
990 | //- main.rs | 990 | //- main.rs |
@@ -1096,3 +1096,34 @@ fn test() { (S {}).method()<|>; } | |||
1096 | ); | 1096 | ); |
1097 | assert_eq!(t, "()"); | 1097 | assert_eq!(t, "()"); |
1098 | } | 1098 | } |
1099 | |||
1100 | #[test] | ||
1101 | fn dyn_trait_super_trait_not_in_scope() { | ||
1102 | assert_snapshot!( | ||
1103 | infer(r#" | ||
1104 | mod m { | ||
1105 | pub trait SuperTrait { | ||
1106 | fn foo(&self) -> u32 { 0 } | ||
1107 | } | ||
1108 | } | ||
1109 | trait Trait: m::SuperTrait {} | ||
1110 | |||
1111 | struct S; | ||
1112 | impl m::SuperTrait for S {} | ||
1113 | impl Trait for S {} | ||
1114 | |||
1115 | fn test(d: &dyn Trait) { | ||
1116 | d.foo(); | ||
1117 | } | ||
1118 | "#), | ||
1119 | @r###" | ||
1120 | 52..56 'self': &Self | ||
1121 | 65..70 '{ 0 }': u32 | ||
1122 | 67..68 '0': u32 | ||
1123 | 177..178 'd': &dyn Trait | ||
1124 | 192..208 '{ ...o(); }': () | ||
1125 | 198..199 'd': &dyn Trait | ||
1126 | 198..205 'd.foo()': u32 | ||
1127 | "### | ||
1128 | ); | ||
1129 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs index af291092d..0c5f972a2 100644 --- a/crates/ra_hir_ty/src/tests/patterns.rs +++ b/crates/ra_hir_ty/src/tests/patterns.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use insta::assert_snapshot; | 1 | use insta::assert_snapshot; |
2 | use test_utils::covers; | 2 | use test_utils::mark; |
3 | 3 | ||
4 | use super::{infer, infer_with_mismatches}; | 4 | use super::{infer, infer_with_mismatches}; |
5 | 5 | ||
@@ -197,7 +197,7 @@ fn test() { | |||
197 | 197 | ||
198 | #[test] | 198 | #[test] |
199 | fn infer_pattern_match_ergonomics_ref() { | 199 | fn infer_pattern_match_ergonomics_ref() { |
200 | covers!(match_ergonomics_ref); | 200 | mark::check!(match_ergonomics_ref); |
201 | assert_snapshot!( | 201 | assert_snapshot!( |
202 | infer(r#" | 202 | infer(r#" |
203 | fn test() { | 203 | fn test() { |
@@ -369,6 +369,45 @@ fn test() { | |||
369 | } | 369 | } |
370 | 370 | ||
371 | #[test] | 371 | #[test] |
372 | fn enum_variant_through_self_in_pattern() { | ||
373 | assert_snapshot!( | ||
374 | infer(r#" | ||
375 | enum E { | ||
376 | A { x: usize }, | ||
377 | B(usize), | ||
378 | C | ||
379 | } | ||
380 | |||
381 | impl E { | ||
382 | fn test() { | ||
383 | match (loop {}) { | ||
384 | Self::A { x } => { x; }, | ||
385 | Self::B(x) => { x; }, | ||
386 | Self::C => {}, | ||
387 | }; | ||
388 | } | ||
389 | } | ||
390 | "#), | ||
391 | @r###" | ||
392 | 76..218 '{ ... }': () | ||
393 | 86..211 'match ... }': () | ||
394 | 93..100 'loop {}': ! | ||
395 | 98..100 '{}': () | ||
396 | 116..129 'Self::A { x }': E | ||
397 | 126..127 'x': usize | ||
398 | 133..139 '{ x; }': () | ||
399 | 135..136 'x': usize | ||
400 | 153..163 'Self::B(x)': E | ||
401 | 161..162 'x': usize | ||
402 | 167..173 '{ x; }': () | ||
403 | 169..170 'x': usize | ||
404 | 187..194 'Self::C': E | ||
405 | 198..200 '{}': () | ||
406 | "### | ||
407 | ); | ||
408 | } | ||
409 | |||
410 | #[test] | ||
372 | fn infer_generics_in_patterns() { | 411 | fn infer_generics_in_patterns() { |
373 | assert_snapshot!( | 412 | assert_snapshot!( |
374 | infer(r#" | 413 | infer(r#" |
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs index 115ad8328..1f004bd63 100644 --- a/crates/ra_hir_ty/src/tests/regression.rs +++ b/crates/ra_hir_ty/src/tests/regression.rs | |||
@@ -1,9 +1,10 @@ | |||
1 | use insta::assert_snapshot; | 1 | use insta::assert_snapshot; |
2 | use test_utils::covers; | 2 | use ra_db::fixture::WithFixture; |
3 | use test_utils::mark; | ||
3 | 4 | ||
4 | use super::infer; | ||
5 | use crate::test_db::TestDB; | 5 | use crate::test_db::TestDB; |
6 | use ra_db::fixture::WithFixture; | 6 | |
7 | use super::infer; | ||
7 | 8 | ||
8 | #[test] | 9 | #[test] |
9 | fn bug_484() { | 10 | fn bug_484() { |
@@ -89,8 +90,8 @@ fn quux() { | |||
89 | 90 | ||
90 | #[test] | 91 | #[test] |
91 | fn recursive_vars() { | 92 | fn recursive_vars() { |
92 | covers!(type_var_cycles_resolve_completely); | 93 | mark::check!(type_var_cycles_resolve_completely); |
93 | covers!(type_var_cycles_resolve_as_possible); | 94 | mark::check!(type_var_cycles_resolve_as_possible); |
94 | assert_snapshot!( | 95 | assert_snapshot!( |
95 | infer(r#" | 96 | infer(r#" |
96 | fn test() { | 97 | fn test() { |
@@ -112,8 +113,6 @@ fn test() { | |||
112 | 113 | ||
113 | #[test] | 114 | #[test] |
114 | fn recursive_vars_2() { | 115 | fn recursive_vars_2() { |
115 | covers!(type_var_cycles_resolve_completely); | ||
116 | covers!(type_var_cycles_resolve_as_possible); | ||
117 | assert_snapshot!( | 116 | assert_snapshot!( |
118 | infer(r#" | 117 | infer(r#" |
119 | fn test() { | 118 | fn test() { |
@@ -170,7 +169,7 @@ fn write() { | |||
170 | 169 | ||
171 | #[test] | 170 | #[test] |
172 | fn infer_std_crash_2() { | 171 | fn infer_std_crash_2() { |
173 | covers!(type_var_resolves_to_int_var); | 172 | mark::check!(type_var_resolves_to_int_var); |
174 | // caused "equating two type variables, ...", taken from std | 173 | // caused "equating two type variables, ...", taken from std |
175 | assert_snapshot!( | 174 | assert_snapshot!( |
176 | infer(r#" | 175 | infer(r#" |
@@ -564,6 +563,37 @@ fn main() { | |||
564 | } | 563 | } |
565 | 564 | ||
566 | #[test] | 565 | #[test] |
566 | fn issue_4465_dollar_crate_at_type() { | ||
567 | assert_snapshot!( | ||
568 | infer(r#" | ||
569 | pub struct Foo {} | ||
570 | pub fn anything<T>() -> T { | ||
571 | loop {} | ||
572 | } | ||
573 | macro_rules! foo { | ||
574 | () => {{ | ||
575 | let r: $crate::Foo = anything(); | ||
576 | r | ||
577 | }}; | ||
578 | } | ||
579 | fn main() { | ||
580 | let _a = foo!(); | ||
581 | } | ||
582 | "#), @r###" | ||
583 | 45..60 '{ loop {} }': T | ||
584 | 51..58 'loop {}': ! | ||
585 | 56..58 '{}': () | ||
586 | !0..31 '{letr:...g();r}': Foo | ||
587 | !4..5 'r': Foo | ||
588 | !18..26 'anything': fn anything<Foo>() -> Foo | ||
589 | !18..28 'anything()': Foo | ||
590 | !29..30 'r': Foo | ||
591 | 164..188 '{ ...!(); }': () | ||
592 | 174..176 '_a': Foo | ||
593 | "###); | ||
594 | } | ||
595 | |||
596 | #[test] | ||
567 | fn issue_4053_diesel_where_clauses() { | 597 | fn issue_4053_diesel_where_clauses() { |
568 | assert_snapshot!( | 598 | assert_snapshot!( |
569 | infer(r#" | 599 | infer(r#" |
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index 322838f02..fd2208af2 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs | |||
@@ -576,6 +576,50 @@ impl S { | |||
576 | } | 576 | } |
577 | 577 | ||
578 | #[test] | 578 | #[test] |
579 | fn infer_self_as_path() { | ||
580 | assert_snapshot!( | ||
581 | infer(r#" | ||
582 | struct S1; | ||
583 | struct S2(isize); | ||
584 | enum E { | ||
585 | V1, | ||
586 | V2(u32), | ||
587 | } | ||
588 | |||
589 | impl S1 { | ||
590 | fn test() { | ||
591 | Self; | ||
592 | } | ||
593 | } | ||
594 | impl S2 { | ||
595 | fn test() { | ||
596 | Self(1); | ||
597 | } | ||
598 | } | ||
599 | impl E { | ||
600 | fn test() { | ||
601 | Self::V1; | ||
602 | Self::V2(1); | ||
603 | } | ||
604 | } | ||
605 | "#), | ||
606 | @r###" | ||
607 | 87..108 '{ ... }': () | ||
608 | 97..101 'Self': S1 | ||
609 | 135..159 '{ ... }': () | ||
610 | 145..149 'Self': S2(isize) -> S2 | ||
611 | 145..152 'Self(1)': S2 | ||
612 | 150..151 '1': isize | ||
613 | 185..231 '{ ... }': () | ||
614 | 195..203 'Self::V1': E | ||
615 | 213..221 'Self::V2': V2(u32) -> E | ||
616 | 213..224 'Self::V2(1)': E | ||
617 | 222..223 '1': u32 | ||
618 | "### | ||
619 | ); | ||
620 | } | ||
621 | |||
622 | #[test] | ||
579 | fn infer_binary_op() { | 623 | fn infer_binary_op() { |
580 | assert_snapshot!( | 624 | assert_snapshot!( |
581 | infer(r#" | 625 | infer(r#" |
@@ -1816,3 +1860,66 @@ fn test() { | |||
1816 | "### | 1860 | "### |
1817 | ); | 1861 | ); |
1818 | } | 1862 | } |
1863 | |||
1864 | #[test] | ||
1865 | fn infer_loop_break_with_val() { | ||
1866 | assert_snapshot!( | ||
1867 | infer(r#" | ||
1868 | enum Option<T> { Some(T), None } | ||
1869 | use Option::*; | ||
1870 | |||
1871 | fn test() { | ||
1872 | let x = loop { | ||
1873 | if false { | ||
1874 | break None; | ||
1875 | } | ||
1876 | |||
1877 | break Some(true); | ||
1878 | }; | ||
1879 | } | ||
1880 | "#), | ||
1881 | @r###" | ||
1882 | 60..169 '{ ... }; }': () | ||
1883 | 70..71 'x': Option<bool> | ||
1884 | 74..166 'loop {... }': Option<bool> | ||
1885 | 79..166 '{ ... }': () | ||
1886 | 89..133 'if fal... }': () | ||
1887 | 92..97 'false': bool | ||
1888 | 98..133 '{ ... }': () | ||
1889 | 112..122 'break None': ! | ||
1890 | 118..122 'None': Option<bool> | ||
1891 | 143..159 'break ...(true)': ! | ||
1892 | 149..153 'Some': Some<bool>(bool) -> Option<bool> | ||
1893 | 149..159 'Some(true)': Option<bool> | ||
1894 | 154..158 'true': bool | ||
1895 | "### | ||
1896 | ); | ||
1897 | } | ||
1898 | |||
1899 | #[test] | ||
1900 | fn infer_loop_break_without_val() { | ||
1901 | assert_snapshot!( | ||
1902 | infer(r#" | ||
1903 | enum Option<T> { Some(T), None } | ||
1904 | use Option::*; | ||
1905 | |||
1906 | fn test() { | ||
1907 | let x = loop { | ||
1908 | if false { | ||
1909 | break; | ||
1910 | } | ||
1911 | }; | ||
1912 | } | ||
1913 | "#), | ||
1914 | @r###" | ||
1915 | 60..137 '{ ... }; }': () | ||
1916 | 70..71 'x': () | ||
1917 | 74..134 'loop {... }': () | ||
1918 | 79..134 '{ ... }': () | ||
1919 | 89..128 'if fal... }': () | ||
1920 | 92..97 'false': bool | ||
1921 | 98..128 '{ ... }': () | ||
1922 | 112..117 'break': ! | ||
1923 | "### | ||
1924 | ); | ||
1925 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 9d32cbc7a..0419bc751 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -1,10 +1,11 @@ | |||
1 | use insta::assert_snapshot; | 1 | use insta::assert_snapshot; |
2 | |||
3 | use ra_db::fixture::WithFixture; | 2 | use ra_db::fixture::WithFixture; |
3 | use test_utils::mark; | ||
4 | 4 | ||
5 | use super::{infer, infer_with_mismatches, type_at, type_at_pos}; | ||
6 | use crate::test_db::TestDB; | 5 | use crate::test_db::TestDB; |
7 | 6 | ||
7 | use super::{infer, infer_with_mismatches, type_at, type_at_pos}; | ||
8 | |||
8 | #[test] | 9 | #[test] |
9 | fn infer_await() { | 10 | fn infer_await() { |
10 | let (db, pos) = TestDB::with_position( | 11 | let (db, pos) = TestDB::with_position( |
@@ -301,7 +302,7 @@ fn test() { | |||
301 | 302 | ||
302 | #[test] | 303 | #[test] |
303 | fn trait_default_method_self_bound_implements_trait() { | 304 | fn trait_default_method_self_bound_implements_trait() { |
304 | test_utils::covers!(trait_self_implements_self); | 305 | mark::check!(trait_self_implements_self); |
305 | assert_snapshot!( | 306 | assert_snapshot!( |
306 | infer(r#" | 307 | infer(r#" |
307 | trait Trait { | 308 | trait Trait { |
@@ -324,7 +325,6 @@ trait Trait { | |||
324 | 325 | ||
325 | #[test] | 326 | #[test] |
326 | fn trait_default_method_self_bound_implements_super_trait() { | 327 | fn trait_default_method_self_bound_implements_super_trait() { |
327 | test_utils::covers!(trait_self_implements_self); | ||
328 | assert_snapshot!( | 328 | assert_snapshot!( |
329 | infer(r#" | 329 | infer(r#" |
330 | trait SuperTrait { | 330 | trait SuperTrait { |
@@ -1617,6 +1617,138 @@ fn test<F: FnOnce(u32, u64) -> u128>(f: F) { | |||
1617 | } | 1617 | } |
1618 | 1618 | ||
1619 | #[test] | 1619 | #[test] |
1620 | fn fn_ptr_and_item() { | ||
1621 | assert_snapshot!( | ||
1622 | infer(r#" | ||
1623 | #[lang="fn_once"] | ||
1624 | trait FnOnce<Args> { | ||
1625 | type Output; | ||
1626 | |||
1627 | fn call_once(self, args: Args) -> Self::Output; | ||
1628 | } | ||
1629 | |||
1630 | trait Foo<T> { | ||
1631 | fn foo(&self) -> T; | ||
1632 | } | ||
1633 | |||
1634 | struct Bar<T>(T); | ||
1635 | |||
1636 | impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> { | ||
1637 | fn foo(&self) -> (A1, R) {} | ||
1638 | } | ||
1639 | |||
1640 | enum Opt<T> { None, Some(T) } | ||
1641 | impl<T> Opt<T> { | ||
1642 | fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> {} | ||
1643 | } | ||
1644 | |||
1645 | fn test() { | ||
1646 | let bar: Bar<fn(u8) -> u32>; | ||
1647 | bar.foo(); | ||
1648 | |||
1649 | let opt: Opt<u8>; | ||
1650 | let f: fn(u8) -> u32; | ||
1651 | opt.map(f); | ||
1652 | } | ||
1653 | "#), | ||
1654 | @r###" | ||
1655 | 75..79 'self': Self | ||
1656 | 81..85 'args': Args | ||
1657 | 140..144 'self': &Self | ||
1658 | 244..248 'self': &Bar<F> | ||
1659 | 261..263 '{}': () | ||
1660 | 347..351 'self': Opt<T> | ||
1661 | 353..354 'f': F | ||
1662 | 369..371 '{}': () | ||
1663 | 385..501 '{ ...(f); }': () | ||
1664 | 395..398 'bar': Bar<fn(u8) -> u32> | ||
1665 | 424..427 'bar': Bar<fn(u8) -> u32> | ||
1666 | 424..433 'bar.foo()': {unknown} | ||
1667 | 444..447 'opt': Opt<u8> | ||
1668 | 466..467 'f': fn(u8) -> u32 | ||
1669 | 488..491 'opt': Opt<u8> | ||
1670 | 488..498 'opt.map(f)': Opt<FnOnce::Output<fn(u8) -> u32, (u8,)>> | ||
1671 | 496..497 'f': fn(u8) -> u32 | ||
1672 | "### | ||
1673 | ); | ||
1674 | } | ||
1675 | |||
1676 | #[test] | ||
1677 | fn fn_trait_deref_with_ty_default() { | ||
1678 | assert_snapshot!( | ||
1679 | infer(r#" | ||
1680 | #[lang = "deref"] | ||
1681 | trait Deref { | ||
1682 | type Target; | ||
1683 | |||
1684 | fn deref(&self) -> &Self::Target; | ||
1685 | } | ||
1686 | |||
1687 | #[lang="fn_once"] | ||
1688 | trait FnOnce<Args> { | ||
1689 | type Output; | ||
1690 | |||
1691 | fn call_once(self, args: Args) -> Self::Output; | ||
1692 | } | ||
1693 | |||
1694 | struct Foo; | ||
1695 | |||
1696 | impl Foo { | ||
1697 | fn foo(&self) -> usize {} | ||
1698 | } | ||
1699 | |||
1700 | struct Lazy<T, F = fn() -> T>(F); | ||
1701 | |||
1702 | impl<T, F> Lazy<T, F> { | ||
1703 | pub fn new(f: F) -> Lazy<T, F> {} | ||
1704 | } | ||
1705 | |||
1706 | impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> { | ||
1707 | type Target = T; | ||
1708 | } | ||
1709 | |||
1710 | fn test() { | ||
1711 | let lazy1: Lazy<Foo, _> = Lazy::new(|| Foo); | ||
1712 | let r1 = lazy1.foo(); | ||
1713 | |||
1714 | fn make_foo_fn() -> Foo {} | ||
1715 | let make_foo_fn_ptr: fn() -> Foo = make_foo_fn; | ||
1716 | let lazy2: Lazy<Foo, _> = Lazy::new(make_foo_fn_ptr); | ||
1717 | let r2 = lazy2.foo(); | ||
1718 | } | ||
1719 | "#), | ||
1720 | @r###" | ||
1721 | 65..69 'self': &Self | ||
1722 | 166..170 'self': Self | ||
1723 | 172..176 'args': Args | ||
1724 | 240..244 'self': &Foo | ||
1725 | 255..257 '{}': () | ||
1726 | 335..336 'f': F | ||
1727 | 355..357 '{}': () | ||
1728 | 444..690 '{ ...o(); }': () | ||
1729 | 454..459 'lazy1': Lazy<Foo, fn() -> T> | ||
1730 | 476..485 'Lazy::new': fn new<Foo, fn() -> T>(fn() -> T) -> Lazy<Foo, fn() -> T> | ||
1731 | 476..493 'Lazy::...| Foo)': Lazy<Foo, fn() -> T> | ||
1732 | 486..492 '|| Foo': || -> T | ||
1733 | 489..492 'Foo': Foo | ||
1734 | 503..505 'r1': {unknown} | ||
1735 | 508..513 'lazy1': Lazy<Foo, fn() -> T> | ||
1736 | 508..519 'lazy1.foo()': {unknown} | ||
1737 | 561..576 'make_foo_fn_ptr': fn() -> Foo | ||
1738 | 592..603 'make_foo_fn': fn make_foo_fn() -> Foo | ||
1739 | 613..618 'lazy2': Lazy<Foo, fn() -> T> | ||
1740 | 635..644 'Lazy::new': fn new<Foo, fn() -> T>(fn() -> T) -> Lazy<Foo, fn() -> T> | ||
1741 | 635..661 'Lazy::...n_ptr)': Lazy<Foo, fn() -> T> | ||
1742 | 645..660 'make_foo_fn_ptr': fn() -> Foo | ||
1743 | 671..673 'r2': {unknown} | ||
1744 | 676..681 'lazy2': Lazy<Foo, fn() -> T> | ||
1745 | 676..687 'lazy2.foo()': {unknown} | ||
1746 | 550..552 '{}': () | ||
1747 | "### | ||
1748 | ); | ||
1749 | } | ||
1750 | |||
1751 | #[test] | ||
1620 | fn closure_1() { | 1752 | fn closure_1() { |
1621 | assert_snapshot!( | 1753 | assert_snapshot!( |
1622 | infer(r#" | 1754 | infer(r#" |
@@ -2470,3 +2602,155 @@ fn test(x: &dyn Foo) { | |||
2470 | "### | 2602 | "### |
2471 | ); | 2603 | ); |
2472 | } | 2604 | } |
2605 | |||
2606 | #[test] | ||
2607 | fn builtin_copy() { | ||
2608 | assert_snapshot!( | ||
2609 | infer_with_mismatches(r#" | ||
2610 | #[lang = "copy"] | ||
2611 | trait Copy {} | ||
2612 | |||
2613 | struct IsCopy; | ||
2614 | impl Copy for IsCopy {} | ||
2615 | struct NotCopy; | ||
2616 | |||
2617 | trait Test { fn test(&self) -> bool; } | ||
2618 | impl<T: Copy> Test for T {} | ||
2619 | |||
2620 | fn test() { | ||
2621 | IsCopy.test(); | ||
2622 | NotCopy.test(); | ||
2623 | (IsCopy, IsCopy).test(); | ||
2624 | (IsCopy, NotCopy).test(); | ||
2625 | } | ||
2626 | "#, true), | ||
2627 | @r###" | ||
2628 | 111..115 'self': &Self | ||
2629 | 167..268 '{ ...t(); }': () | ||
2630 | 173..179 'IsCopy': IsCopy | ||
2631 | 173..186 'IsCopy.test()': bool | ||
2632 | 192..199 'NotCopy': NotCopy | ||
2633 | 192..206 'NotCopy.test()': {unknown} | ||
2634 | 212..228 '(IsCop...sCopy)': (IsCopy, IsCopy) | ||
2635 | 212..235 '(IsCop...test()': bool | ||
2636 | 213..219 'IsCopy': IsCopy | ||
2637 | 221..227 'IsCopy': IsCopy | ||
2638 | 241..258 '(IsCop...tCopy)': (IsCopy, NotCopy) | ||
2639 | 241..265 '(IsCop...test()': {unknown} | ||
2640 | 242..248 'IsCopy': IsCopy | ||
2641 | 250..257 'NotCopy': NotCopy | ||
2642 | "### | ||
2643 | ); | ||
2644 | } | ||
2645 | |||
2646 | #[test] | ||
2647 | fn builtin_fn_def_copy() { | ||
2648 | assert_snapshot!( | ||
2649 | infer_with_mismatches(r#" | ||
2650 | #[lang = "copy"] | ||
2651 | trait Copy {} | ||
2652 | |||
2653 | fn foo() {} | ||
2654 | fn bar<T: Copy>(T) -> T {} | ||
2655 | struct Struct(usize); | ||
2656 | enum Enum { Variant(usize) } | ||
2657 | |||
2658 | trait Test { fn test(&self) -> bool; } | ||
2659 | impl<T: Copy> Test for T {} | ||
2660 | |||
2661 | fn test() { | ||
2662 | foo.test(); | ||
2663 | bar.test(); | ||
2664 | Struct.test(); | ||
2665 | Enum::Variant.test(); | ||
2666 | } | ||
2667 | "#, true), | ||
2668 | // wrong result, because the built-in Copy impl for fn defs doesn't exist in Chalk yet | ||
2669 | @r###" | ||
2670 | 42..44 '{}': () | ||
2671 | 61..62 'T': {unknown} | ||
2672 | 69..71 '{}': () | ||
2673 | 69..71: expected T, got () | ||
2674 | 146..150 'self': &Self | ||
2675 | 202..282 '{ ...t(); }': () | ||
2676 | 208..211 'foo': fn foo() | ||
2677 | 208..218 'foo.test()': {unknown} | ||
2678 | 224..227 'bar': fn bar<{unknown}>({unknown}) -> {unknown} | ||
2679 | 224..234 'bar.test()': {unknown} | ||
2680 | 240..246 'Struct': Struct(usize) -> Struct | ||
2681 | 240..253 'Struct.test()': {unknown} | ||
2682 | 259..272 'Enum::Variant': Variant(usize) -> Enum | ||
2683 | 259..279 'Enum::...test()': {unknown} | ||
2684 | "### | ||
2685 | ); | ||
2686 | } | ||
2687 | |||
2688 | #[test] | ||
2689 | fn builtin_fn_ptr_copy() { | ||
2690 | assert_snapshot!( | ||
2691 | infer_with_mismatches(r#" | ||
2692 | #[lang = "copy"] | ||
2693 | trait Copy {} | ||
2694 | |||
2695 | trait Test { fn test(&self) -> bool; } | ||
2696 | impl<T: Copy> Test for T {} | ||
2697 | |||
2698 | fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) { | ||
2699 | f1.test(); | ||
2700 | f2.test(); | ||
2701 | f3.test(); | ||
2702 | } | ||
2703 | "#, true), | ||
2704 | @r###" | ||
2705 | 55..59 'self': &Self | ||
2706 | 109..111 'f1': fn() | ||
2707 | 119..121 'f2': fn(usize) -> u8 | ||
2708 | 140..142 'f3': fn(u8, u8) -> &u8 | ||
2709 | 163..211 '{ ...t(); }': () | ||
2710 | 169..171 'f1': fn() | ||
2711 | 169..178 'f1.test()': bool | ||
2712 | 184..186 'f2': fn(usize) -> u8 | ||
2713 | 184..193 'f2.test()': bool | ||
2714 | 199..201 'f3': fn(u8, u8) -> &u8 | ||
2715 | 199..208 'f3.test()': bool | ||
2716 | "### | ||
2717 | ); | ||
2718 | } | ||
2719 | |||
2720 | #[test] | ||
2721 | fn builtin_sized() { | ||
2722 | assert_snapshot!( | ||
2723 | infer_with_mismatches(r#" | ||
2724 | #[lang = "sized"] | ||
2725 | trait Sized {} | ||
2726 | |||
2727 | trait Test { fn test(&self) -> bool; } | ||
2728 | impl<T: Sized> Test for T {} | ||
2729 | |||
2730 | fn test() { | ||
2731 | 1u8.test(); | ||
2732 | (*"foo").test(); // not Sized | ||
2733 | (1u8, 1u8).test(); | ||
2734 | (1u8, *"foo").test(); // not Sized | ||
2735 | } | ||
2736 | "#, true), | ||
2737 | @r###" | ||
2738 | 57..61 'self': &Self | ||
2739 | 114..229 '{ ...ized }': () | ||
2740 | 120..123 '1u8': u8 | ||
2741 | 120..130 '1u8.test()': bool | ||
2742 | 136..151 '(*"foo").test()': {unknown} | ||
2743 | 137..143 '*"foo"': str | ||
2744 | 138..143 '"foo"': &str | ||
2745 | 170..180 '(1u8, 1u8)': (u8, u8) | ||
2746 | 170..187 '(1u8, ...test()': bool | ||
2747 | 171..174 '1u8': u8 | ||
2748 | 176..179 '1u8': u8 | ||
2749 | 193..206 '(1u8, *"foo")': (u8, str) | ||
2750 | 193..213 '(1u8, ...test()': {unknown} | ||
2751 | 194..197 '1u8': u8 | ||
2752 | 199..205 '*"foo"': str | ||
2753 | 200..205 '"foo"': &str | ||
2754 | "### | ||
2755 | ); | ||
2756 | } | ||
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 1ccb7c3b4..5b0f12a3c 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -1,298 +1,29 @@ | |||
1 | //! Conversion code from/to Chalk. | 1 | //! Conversion code from/to Chalk. |
2 | use std::{fmt, sync::Arc}; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use log::debug; | 4 | use log::debug; |
5 | 5 | ||
6 | use chalk_ir::{ | 6 | use chalk_ir::{fold::shift::Shift, GenericArg, TypeName}; |
7 | cast::Cast, fold::shift::Shift, interner::HasInterner, Goal, GoalData, Parameter, | ||
8 | PlaceholderIndex, TypeName, UniverseIndex, | ||
9 | }; | ||
10 | 7 | ||
11 | use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId}; | 8 | use hir_def::{ |
12 | use ra_db::{ | 9 | lang_item::{lang_attr, LangItemTarget}, |
13 | salsa::{InternId, InternKey}, | 10 | AssocContainerId, AssocItemId, HasModule, Lookup, TypeAliasId, |
14 | CrateId, | ||
15 | }; | 11 | }; |
12 | use ra_db::{salsa::InternKey, CrateId}; | ||
16 | 13 | ||
17 | use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; | 14 | use super::{builtin, AssocTyValue, ChalkContext, Impl}; |
18 | use crate::{ | 15 | use crate::{ |
19 | db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics, | 16 | db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics, |
20 | ApplicationTy, DebruijnIndex, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 17 | CallableDef, DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor, |
21 | }; | 18 | }; |
19 | use chalk_rust_ir::WellKnownTrait; | ||
20 | use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders}; | ||
22 | 21 | ||
23 | pub(super) mod tls; | 22 | pub use self::interner::*; |
24 | |||
25 | #[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] | ||
26 | pub struct Interner; | ||
27 | |||
28 | impl chalk_ir::interner::Interner for Interner { | ||
29 | type InternedType = Box<chalk_ir::TyData<Self>>; | ||
30 | type InternedLifetime = chalk_ir::LifetimeData<Self>; | ||
31 | type InternedParameter = chalk_ir::ParameterData<Self>; | ||
32 | type InternedGoal = Arc<GoalData<Self>>; | ||
33 | type InternedGoals = Vec<Goal<Self>>; | ||
34 | type InternedSubstitution = Vec<Parameter<Self>>; | ||
35 | type InternedProgramClause = chalk_ir::ProgramClauseData<Self>; | ||
36 | type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>; | ||
37 | type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; | ||
38 | type InternedParameterKinds = Vec<chalk_ir::ParameterKind<()>>; | ||
39 | type InternedCanonicalVarKinds = Vec<chalk_ir::ParameterKind<UniverseIndex>>; | ||
40 | type Identifier = TypeAliasId; | ||
41 | type DefId = InternId; | ||
42 | |||
43 | fn debug_struct_id( | ||
44 | type_kind_id: StructId, | ||
45 | fmt: &mut fmt::Formatter<'_>, | ||
46 | ) -> Option<fmt::Result> { | ||
47 | tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt))) | ||
48 | } | ||
49 | |||
50 | fn debug_trait_id(type_kind_id: TraitId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
51 | tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt))) | ||
52 | } | ||
53 | |||
54 | fn debug_assoc_type_id(id: AssocTypeId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
55 | tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt))) | ||
56 | } | ||
57 | |||
58 | fn debug_alias( | ||
59 | alias: &chalk_ir::AliasTy<Interner>, | ||
60 | fmt: &mut fmt::Formatter<'_>, | ||
61 | ) -> Option<fmt::Result> { | ||
62 | tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt))) | ||
63 | } | ||
64 | |||
65 | fn debug_projection_ty( | ||
66 | proj: &chalk_ir::ProjectionTy<Interner>, | ||
67 | fmt: &mut fmt::Formatter<'_>, | ||
68 | ) -> Option<fmt::Result> { | ||
69 | tls::with_current_program(|prog| Some(prog?.debug_projection_ty(proj, fmt))) | ||
70 | } | ||
71 | |||
72 | fn debug_opaque_ty( | ||
73 | opaque_ty: &chalk_ir::OpaqueTy<Interner>, | ||
74 | fmt: &mut fmt::Formatter<'_>, | ||
75 | ) -> Option<fmt::Result> { | ||
76 | tls::with_current_program(|prog| Some(prog?.debug_opaque_ty(opaque_ty, fmt))) | ||
77 | } | ||
78 | |||
79 | fn debug_opaque_ty_id( | ||
80 | opaque_ty_id: chalk_ir::OpaqueTyId<Self>, | ||
81 | fmt: &mut fmt::Formatter<'_>, | ||
82 | ) -> Option<fmt::Result> { | ||
83 | tls::with_current_program(|prog| Some(prog?.debug_opaque_ty_id(opaque_ty_id, fmt))) | ||
84 | } | ||
85 | |||
86 | fn debug_ty(ty: &chalk_ir::Ty<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
87 | tls::with_current_program(|prog| Some(prog?.debug_ty(ty, fmt))) | ||
88 | } | ||
89 | |||
90 | fn debug_lifetime( | ||
91 | lifetime: &chalk_ir::Lifetime<Interner>, | ||
92 | fmt: &mut fmt::Formatter<'_>, | ||
93 | ) -> Option<fmt::Result> { | ||
94 | tls::with_current_program(|prog| Some(prog?.debug_lifetime(lifetime, fmt))) | ||
95 | } | ||
96 | |||
97 | fn debug_parameter( | ||
98 | parameter: &Parameter<Interner>, | ||
99 | fmt: &mut fmt::Formatter<'_>, | ||
100 | ) -> Option<fmt::Result> { | ||
101 | tls::with_current_program(|prog| Some(prog?.debug_parameter(parameter, fmt))) | ||
102 | } | ||
103 | |||
104 | fn debug_goal(goal: &Goal<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
105 | tls::with_current_program(|prog| Some(prog?.debug_goal(goal, fmt))) | ||
106 | } | ||
107 | |||
108 | fn debug_goals( | ||
109 | goals: &chalk_ir::Goals<Interner>, | ||
110 | fmt: &mut fmt::Formatter<'_>, | ||
111 | ) -> Option<fmt::Result> { | ||
112 | tls::with_current_program(|prog| Some(prog?.debug_goals(goals, fmt))) | ||
113 | } | ||
114 | |||
115 | fn debug_program_clause_implication( | ||
116 | pci: &chalk_ir::ProgramClauseImplication<Interner>, | ||
117 | fmt: &mut fmt::Formatter<'_>, | ||
118 | ) -> Option<fmt::Result> { | ||
119 | tls::with_current_program(|prog| Some(prog?.debug_program_clause_implication(pci, fmt))) | ||
120 | } | ||
121 | |||
122 | fn debug_application_ty( | ||
123 | application_ty: &chalk_ir::ApplicationTy<Interner>, | ||
124 | fmt: &mut fmt::Formatter<'_>, | ||
125 | ) -> Option<fmt::Result> { | ||
126 | tls::with_current_program(|prog| Some(prog?.debug_application_ty(application_ty, fmt))) | ||
127 | } | ||
128 | |||
129 | fn debug_substitution( | ||
130 | substitution: &chalk_ir::Substitution<Interner>, | ||
131 | fmt: &mut fmt::Formatter<'_>, | ||
132 | ) -> Option<fmt::Result> { | ||
133 | tls::with_current_program(|prog| Some(prog?.debug_substitution(substitution, fmt))) | ||
134 | } | ||
135 | |||
136 | fn debug_separator_trait_ref( | ||
137 | separator_trait_ref: &chalk_ir::SeparatorTraitRef<Interner>, | ||
138 | fmt: &mut fmt::Formatter<'_>, | ||
139 | ) -> Option<fmt::Result> { | ||
140 | tls::with_current_program(|prog| { | ||
141 | Some(prog?.debug_separator_trait_ref(separator_trait_ref, fmt)) | ||
142 | }) | ||
143 | } | ||
144 | |||
145 | fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> { | ||
146 | Box::new(ty) | ||
147 | } | ||
148 | |||
149 | fn ty_data<'a>(&self, ty: &'a Box<chalk_ir::TyData<Self>>) -> &'a chalk_ir::TyData<Self> { | ||
150 | ty | ||
151 | } | ||
152 | |||
153 | fn intern_lifetime( | ||
154 | &self, | ||
155 | lifetime: chalk_ir::LifetimeData<Self>, | ||
156 | ) -> chalk_ir::LifetimeData<Self> { | ||
157 | lifetime | ||
158 | } | ||
159 | |||
160 | fn lifetime_data<'a>( | ||
161 | &self, | ||
162 | lifetime: &'a chalk_ir::LifetimeData<Self>, | ||
163 | ) -> &'a chalk_ir::LifetimeData<Self> { | ||
164 | lifetime | ||
165 | } | ||
166 | |||
167 | fn intern_parameter( | ||
168 | &self, | ||
169 | parameter: chalk_ir::ParameterData<Self>, | ||
170 | ) -> chalk_ir::ParameterData<Self> { | ||
171 | parameter | ||
172 | } | ||
173 | |||
174 | fn parameter_data<'a>( | ||
175 | &self, | ||
176 | parameter: &'a chalk_ir::ParameterData<Self>, | ||
177 | ) -> &'a chalk_ir::ParameterData<Self> { | ||
178 | parameter | ||
179 | } | ||
180 | |||
181 | fn intern_goal(&self, goal: GoalData<Self>) -> Arc<GoalData<Self>> { | ||
182 | Arc::new(goal) | ||
183 | } | ||
184 | |||
185 | fn intern_goals(&self, data: impl IntoIterator<Item = Goal<Self>>) -> Self::InternedGoals { | ||
186 | data.into_iter().collect() | ||
187 | } | ||
188 | |||
189 | fn goal_data<'a>(&self, goal: &'a Arc<GoalData<Self>>) -> &'a GoalData<Self> { | ||
190 | goal | ||
191 | } | ||
192 | |||
193 | fn goals_data<'a>(&self, goals: &'a Vec<Goal<Interner>>) -> &'a [Goal<Interner>] { | ||
194 | goals | ||
195 | } | ||
196 | |||
197 | fn intern_substitution<E>( | ||
198 | &self, | ||
199 | data: impl IntoIterator<Item = Result<Parameter<Self>, E>>, | ||
200 | ) -> Result<Vec<Parameter<Self>>, E> { | ||
201 | data.into_iter().collect() | ||
202 | } | ||
203 | |||
204 | fn substitution_data<'a>( | ||
205 | &self, | ||
206 | substitution: &'a Vec<Parameter<Self>>, | ||
207 | ) -> &'a [Parameter<Self>] { | ||
208 | substitution | ||
209 | } | ||
210 | |||
211 | fn intern_program_clause( | ||
212 | &self, | ||
213 | data: chalk_ir::ProgramClauseData<Self>, | ||
214 | ) -> chalk_ir::ProgramClauseData<Self> { | ||
215 | data | ||
216 | } | ||
217 | 23 | ||
218 | fn program_clause_data<'a>( | 24 | pub(super) mod tls; |
219 | &self, | 25 | mod interner; |
220 | clause: &'a chalk_ir::ProgramClauseData<Self>, | 26 | mod mapping; |
221 | ) -> &'a chalk_ir::ProgramClauseData<Self> { | ||
222 | clause | ||
223 | } | ||
224 | |||
225 | fn intern_program_clauses( | ||
226 | &self, | ||
227 | data: impl IntoIterator<Item = chalk_ir::ProgramClause<Self>>, | ||
228 | ) -> Arc<[chalk_ir::ProgramClause<Self>]> { | ||
229 | data.into_iter().collect() | ||
230 | } | ||
231 | |||
232 | fn program_clauses_data<'a>( | ||
233 | &self, | ||
234 | clauses: &'a Arc<[chalk_ir::ProgramClause<Self>]>, | ||
235 | ) -> &'a [chalk_ir::ProgramClause<Self>] { | ||
236 | &clauses | ||
237 | } | ||
238 | |||
239 | fn intern_quantified_where_clauses( | ||
240 | &self, | ||
241 | data: impl IntoIterator<Item = chalk_ir::QuantifiedWhereClause<Self>>, | ||
242 | ) -> Self::InternedQuantifiedWhereClauses { | ||
243 | data.into_iter().collect() | ||
244 | } | ||
245 | |||
246 | fn quantified_where_clauses_data<'a>( | ||
247 | &self, | ||
248 | clauses: &'a Self::InternedQuantifiedWhereClauses, | ||
249 | ) -> &'a [chalk_ir::QuantifiedWhereClause<Self>] { | ||
250 | clauses | ||
251 | } | ||
252 | |||
253 | fn intern_parameter_kinds( | ||
254 | &self, | ||
255 | data: impl IntoIterator<Item = chalk_ir::ParameterKind<()>>, | ||
256 | ) -> Self::InternedParameterKinds { | ||
257 | data.into_iter().collect() | ||
258 | } | ||
259 | |||
260 | fn parameter_kinds_data<'a>( | ||
261 | &self, | ||
262 | parameter_kinds: &'a Self::InternedParameterKinds, | ||
263 | ) -> &'a [chalk_ir::ParameterKind<()>] { | ||
264 | ¶meter_kinds | ||
265 | } | ||
266 | |||
267 | fn intern_canonical_var_kinds( | ||
268 | &self, | ||
269 | data: impl IntoIterator<Item = chalk_ir::ParameterKind<UniverseIndex>>, | ||
270 | ) -> Self::InternedCanonicalVarKinds { | ||
271 | data.into_iter().collect() | ||
272 | } | ||
273 | |||
274 | fn canonical_var_kinds_data<'a>( | ||
275 | &self, | ||
276 | canonical_var_kinds: &'a Self::InternedCanonicalVarKinds, | ||
277 | ) -> &'a [chalk_ir::ParameterKind<UniverseIndex>] { | ||
278 | &canonical_var_kinds | ||
279 | } | ||
280 | } | ||
281 | |||
282 | impl chalk_ir::interner::HasInterner for Interner { | ||
283 | type Interner = Self; | ||
284 | } | ||
285 | |||
286 | pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; | ||
287 | pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum<Interner>; | ||
288 | pub type TraitId = chalk_ir::TraitId<Interner>; | ||
289 | pub type TraitDatum = chalk_rust_ir::TraitDatum<Interner>; | ||
290 | pub type StructId = chalk_ir::StructId<Interner>; | ||
291 | pub type StructDatum = chalk_rust_ir::StructDatum<Interner>; | ||
292 | pub type ImplId = chalk_ir::ImplId<Interner>; | ||
293 | pub type ImplDatum = chalk_rust_ir::ImplDatum<Interner>; | ||
294 | pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId<Interner>; | ||
295 | pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<Interner>; | ||
296 | 27 | ||
297 | pub(super) trait ToChalk { | 28 | pub(super) trait ToChalk { |
298 | type Chalk; | 29 | type Chalk; |
@@ -307,500 +38,6 @@ where | |||
307 | T::from_chalk(db, chalk) | 38 | T::from_chalk(db, chalk) |
308 | } | 39 | } |
309 | 40 | ||
310 | impl ToChalk for Ty { | ||
311 | type Chalk = chalk_ir::Ty<Interner>; | ||
312 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> { | ||
313 | match self { | ||
314 | Ty::Apply(apply_ty) => { | ||
315 | let name = apply_ty.ctor.to_chalk(db); | ||
316 | let substitution = apply_ty.parameters.to_chalk(db); | ||
317 | chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) | ||
318 | } | ||
319 | Ty::Projection(proj_ty) => { | ||
320 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); | ||
321 | let substitution = proj_ty.parameters.to_chalk(db); | ||
322 | chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { | ||
323 | associated_ty_id, | ||
324 | substitution, | ||
325 | }) | ||
326 | .cast(&Interner) | ||
327 | .intern(&Interner) | ||
328 | } | ||
329 | Ty::Placeholder(id) => { | ||
330 | let interned_id = db.intern_type_param_id(id); | ||
331 | PlaceholderIndex { | ||
332 | ui: UniverseIndex::ROOT, | ||
333 | idx: interned_id.as_intern_id().as_usize(), | ||
334 | } | ||
335 | .to_ty::<Interner>(&Interner) | ||
336 | } | ||
337 | Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner), | ||
338 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), | ||
339 | Ty::Dyn(predicates) => { | ||
340 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from( | ||
341 | &Interner, | ||
342 | predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)), | ||
343 | ); | ||
344 | let bounded_ty = chalk_ir::DynTy { bounds: make_binders(where_clauses, 1) }; | ||
345 | chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) | ||
346 | } | ||
347 | Ty::Opaque(_) | Ty::Unknown => { | ||
348 | let substitution = chalk_ir::Substitution::empty(&Interner); | ||
349 | let name = TypeName::Error; | ||
350 | chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) | ||
351 | } | ||
352 | } | ||
353 | } | ||
354 | fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self { | ||
355 | match chalk.data(&Interner).clone() { | ||
356 | chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { | ||
357 | TypeName::Error => Ty::Unknown, | ||
358 | _ => { | ||
359 | let ctor = from_chalk(db, apply_ty.name); | ||
360 | let parameters = from_chalk(db, apply_ty.substitution); | ||
361 | Ty::Apply(ApplicationTy { ctor, parameters }) | ||
362 | } | ||
363 | }, | ||
364 | chalk_ir::TyData::Placeholder(idx) => { | ||
365 | assert_eq!(idx.ui, UniverseIndex::ROOT); | ||
366 | let interned_id = crate::db::GlobalTypeParamId::from_intern_id( | ||
367 | crate::salsa::InternId::from(idx.idx), | ||
368 | ); | ||
369 | Ty::Placeholder(db.lookup_intern_type_param_id(interned_id)) | ||
370 | } | ||
371 | chalk_ir::TyData::Alias(chalk_ir::AliasTy::Projection(proj)) => { | ||
372 | let associated_ty = from_chalk(db, proj.associated_ty_id); | ||
373 | let parameters = from_chalk(db, proj.substitution); | ||
374 | Ty::Projection(ProjectionTy { associated_ty, parameters }) | ||
375 | } | ||
376 | chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(_)) => unimplemented!(), | ||
377 | chalk_ir::TyData::Function(_) => unimplemented!(), | ||
378 | chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx), | ||
379 | chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, | ||
380 | chalk_ir::TyData::Dyn(where_clauses) => { | ||
381 | assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); | ||
382 | let predicates = where_clauses | ||
383 | .bounds | ||
384 | .skip_binders() | ||
385 | .iter(&Interner) | ||
386 | .map(|c| from_chalk(db, c.clone())) | ||
387 | .collect(); | ||
388 | Ty::Dyn(predicates) | ||
389 | } | ||
390 | } | ||
391 | } | ||
392 | } | ||
393 | |||
394 | impl ToChalk for Substs { | ||
395 | type Chalk = chalk_ir::Substitution<Interner>; | ||
396 | |||
397 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> { | ||
398 | chalk_ir::Substitution::from(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db))) | ||
399 | } | ||
400 | |||
401 | fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs { | ||
402 | let tys = parameters | ||
403 | .iter(&Interner) | ||
404 | .map(|p| match p.ty(&Interner) { | ||
405 | Some(ty) => from_chalk(db, ty.clone()), | ||
406 | None => unimplemented!(), | ||
407 | }) | ||
408 | .collect(); | ||
409 | Substs(tys) | ||
410 | } | ||
411 | } | ||
412 | |||
413 | impl ToChalk for TraitRef { | ||
414 | type Chalk = chalk_ir::TraitRef<Interner>; | ||
415 | |||
416 | fn to_chalk(self: TraitRef, db: &dyn HirDatabase) -> chalk_ir::TraitRef<Interner> { | ||
417 | let trait_id = self.trait_.to_chalk(db); | ||
418 | let substitution = self.substs.to_chalk(db); | ||
419 | chalk_ir::TraitRef { trait_id, substitution } | ||
420 | } | ||
421 | |||
422 | fn from_chalk(db: &dyn HirDatabase, trait_ref: chalk_ir::TraitRef<Interner>) -> Self { | ||
423 | let trait_ = from_chalk(db, trait_ref.trait_id); | ||
424 | let substs = from_chalk(db, trait_ref.substitution); | ||
425 | TraitRef { trait_, substs } | ||
426 | } | ||
427 | } | ||
428 | |||
429 | impl ToChalk for hir_def::TraitId { | ||
430 | type Chalk = TraitId; | ||
431 | |||
432 | fn to_chalk(self, _db: &dyn HirDatabase) -> TraitId { | ||
433 | chalk_ir::TraitId(self.as_intern_id()) | ||
434 | } | ||
435 | |||
436 | fn from_chalk(_db: &dyn HirDatabase, trait_id: TraitId) -> hir_def::TraitId { | ||
437 | InternKey::from_intern_id(trait_id.0) | ||
438 | } | ||
439 | } | ||
440 | |||
441 | impl ToChalk for TypeCtor { | ||
442 | type Chalk = TypeName<Interner>; | ||
443 | |||
444 | fn to_chalk(self, db: &dyn HirDatabase) -> TypeName<Interner> { | ||
445 | match self { | ||
446 | TypeCtor::AssociatedType(type_alias) => { | ||
447 | let type_id = type_alias.to_chalk(db); | ||
448 | TypeName::AssociatedType(type_id) | ||
449 | } | ||
450 | _ => { | ||
451 | // other TypeCtors get interned and turned into a chalk StructId | ||
452 | let struct_id = db.intern_type_ctor(self).into(); | ||
453 | TypeName::Struct(struct_id) | ||
454 | } | ||
455 | } | ||
456 | } | ||
457 | |||
458 | fn from_chalk(db: &dyn HirDatabase, type_name: TypeName<Interner>) -> TypeCtor { | ||
459 | match type_name { | ||
460 | TypeName::Struct(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), | ||
461 | TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), | ||
462 | TypeName::OpaqueType(_) => unreachable!(), | ||
463 | TypeName::Error => { | ||
464 | // this should not be reached, since we don't represent TypeName::Error with TypeCtor | ||
465 | unreachable!() | ||
466 | } | ||
467 | } | ||
468 | } | ||
469 | } | ||
470 | |||
471 | impl ToChalk for Impl { | ||
472 | type Chalk = ImplId; | ||
473 | |||
474 | fn to_chalk(self, db: &dyn HirDatabase) -> ImplId { | ||
475 | db.intern_chalk_impl(self).into() | ||
476 | } | ||
477 | |||
478 | fn from_chalk(db: &dyn HirDatabase, impl_id: ImplId) -> Impl { | ||
479 | db.lookup_intern_chalk_impl(impl_id.into()) | ||
480 | } | ||
481 | } | ||
482 | |||
483 | impl ToChalk for TypeAliasId { | ||
484 | type Chalk = AssocTypeId; | ||
485 | |||
486 | fn to_chalk(self, _db: &dyn HirDatabase) -> AssocTypeId { | ||
487 | chalk_ir::AssocTypeId(self.as_intern_id()) | ||
488 | } | ||
489 | |||
490 | fn from_chalk(_db: &dyn HirDatabase, type_alias_id: AssocTypeId) -> TypeAliasId { | ||
491 | InternKey::from_intern_id(type_alias_id.0) | ||
492 | } | ||
493 | } | ||
494 | |||
495 | impl ToChalk for AssocTyValue { | ||
496 | type Chalk = AssociatedTyValueId; | ||
497 | |||
498 | fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValueId { | ||
499 | db.intern_assoc_ty_value(self).into() | ||
500 | } | ||
501 | |||
502 | fn from_chalk(db: &dyn HirDatabase, assoc_ty_value_id: AssociatedTyValueId) -> AssocTyValue { | ||
503 | db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) | ||
504 | } | ||
505 | } | ||
506 | |||
507 | impl ToChalk for GenericPredicate { | ||
508 | type Chalk = chalk_ir::QuantifiedWhereClause<Interner>; | ||
509 | |||
510 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> { | ||
511 | match self { | ||
512 | GenericPredicate::Implemented(trait_ref) => { | ||
513 | let chalk_trait_ref = trait_ref.to_chalk(db); | ||
514 | let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner); | ||
515 | make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0) | ||
516 | } | ||
517 | GenericPredicate::Projection(projection_pred) => { | ||
518 | let ty = projection_pred.ty.to_chalk(db).shifted_in(&Interner); | ||
519 | let projection = projection_pred.projection_ty.to_chalk(db).shifted_in(&Interner); | ||
520 | let alias = chalk_ir::AliasTy::Projection(projection); | ||
521 | make_binders(chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), 0) | ||
522 | } | ||
523 | GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), | ||
524 | } | ||
525 | } | ||
526 | |||
527 | fn from_chalk( | ||
528 | db: &dyn HirDatabase, | ||
529 | where_clause: chalk_ir::QuantifiedWhereClause<Interner>, | ||
530 | ) -> GenericPredicate { | ||
531 | // we don't produce any where clauses with binders and can't currently deal with them | ||
532 | match where_clause | ||
533 | .skip_binders() | ||
534 | .shifted_out(&Interner) | ||
535 | .expect("unexpected bound vars in where clause") | ||
536 | { | ||
537 | chalk_ir::WhereClause::Implemented(tr) => { | ||
538 | GenericPredicate::Implemented(from_chalk(db, tr)) | ||
539 | } | ||
540 | chalk_ir::WhereClause::AliasEq(projection_eq) => { | ||
541 | let projection_ty = from_chalk( | ||
542 | db, | ||
543 | match projection_eq.alias { | ||
544 | chalk_ir::AliasTy::Projection(p) => p, | ||
545 | _ => unimplemented!(), | ||
546 | }, | ||
547 | ); | ||
548 | let ty = from_chalk(db, projection_eq.ty); | ||
549 | GenericPredicate::Projection(super::ProjectionPredicate { projection_ty, ty }) | ||
550 | } | ||
551 | } | ||
552 | } | ||
553 | } | ||
554 | |||
555 | impl ToChalk for ProjectionTy { | ||
556 | type Chalk = chalk_ir::ProjectionTy<Interner>; | ||
557 | |||
558 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::ProjectionTy<Interner> { | ||
559 | chalk_ir::ProjectionTy { | ||
560 | associated_ty_id: self.associated_ty.to_chalk(db), | ||
561 | substitution: self.parameters.to_chalk(db), | ||
562 | } | ||
563 | } | ||
564 | |||
565 | fn from_chalk( | ||
566 | db: &dyn HirDatabase, | ||
567 | projection_ty: chalk_ir::ProjectionTy<Interner>, | ||
568 | ) -> ProjectionTy { | ||
569 | ProjectionTy { | ||
570 | associated_ty: from_chalk(db, projection_ty.associated_ty_id), | ||
571 | parameters: from_chalk(db, projection_ty.substitution), | ||
572 | } | ||
573 | } | ||
574 | } | ||
575 | |||
576 | impl ToChalk for super::ProjectionPredicate { | ||
577 | type Chalk = chalk_ir::AliasEq<Interner>; | ||
578 | |||
579 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> { | ||
580 | chalk_ir::AliasEq { | ||
581 | alias: chalk_ir::AliasTy::Projection(self.projection_ty.to_chalk(db)), | ||
582 | ty: self.ty.to_chalk(db), | ||
583 | } | ||
584 | } | ||
585 | |||
586 | fn from_chalk(_db: &dyn HirDatabase, _normalize: chalk_ir::AliasEq<Interner>) -> Self { | ||
587 | unimplemented!() | ||
588 | } | ||
589 | } | ||
590 | |||
591 | impl ToChalk for Obligation { | ||
592 | type Chalk = chalk_ir::DomainGoal<Interner>; | ||
593 | |||
594 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> { | ||
595 | match self { | ||
596 | Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner), | ||
597 | Obligation::Projection(pr) => pr.to_chalk(db).cast(&Interner), | ||
598 | } | ||
599 | } | ||
600 | |||
601 | fn from_chalk(_db: &dyn HirDatabase, _goal: chalk_ir::DomainGoal<Interner>) -> Self { | ||
602 | unimplemented!() | ||
603 | } | ||
604 | } | ||
605 | |||
606 | impl<T> ToChalk for Canonical<T> | ||
607 | where | ||
608 | T: ToChalk, | ||
609 | T::Chalk: HasInterner<Interner = Interner>, | ||
610 | { | ||
611 | type Chalk = chalk_ir::Canonical<T::Chalk>; | ||
612 | |||
613 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { | ||
614 | let parameter = chalk_ir::ParameterKind::Ty(chalk_ir::UniverseIndex::ROOT); | ||
615 | let value = self.value.to_chalk(db); | ||
616 | chalk_ir::Canonical { | ||
617 | value, | ||
618 | binders: chalk_ir::CanonicalVarKinds::from(&Interner, vec![parameter; self.num_vars]), | ||
619 | } | ||
620 | } | ||
621 | |||
622 | fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { | ||
623 | Canonical { | ||
624 | num_vars: canonical.binders.len(&Interner), | ||
625 | value: from_chalk(db, canonical.value), | ||
626 | } | ||
627 | } | ||
628 | } | ||
629 | |||
630 | impl ToChalk for Arc<super::TraitEnvironment> { | ||
631 | type Chalk = chalk_ir::Environment<Interner>; | ||
632 | |||
633 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Environment<Interner> { | ||
634 | let mut clauses = Vec::new(); | ||
635 | for pred in &self.predicates { | ||
636 | if pred.is_error() { | ||
637 | // for env, we just ignore errors | ||
638 | continue; | ||
639 | } | ||
640 | let program_clause: chalk_ir::ProgramClause<Interner> = | ||
641 | pred.clone().to_chalk(db).cast(&Interner); | ||
642 | clauses.push(program_clause.into_from_env_clause(&Interner)); | ||
643 | } | ||
644 | chalk_ir::Environment::new(&Interner).add_clauses(&Interner, clauses) | ||
645 | } | ||
646 | |||
647 | fn from_chalk( | ||
648 | _db: &dyn HirDatabase, | ||
649 | _env: chalk_ir::Environment<Interner>, | ||
650 | ) -> Arc<super::TraitEnvironment> { | ||
651 | unimplemented!() | ||
652 | } | ||
653 | } | ||
654 | |||
655 | impl<T: ToChalk> ToChalk for super::InEnvironment<T> | ||
656 | where | ||
657 | T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>, | ||
658 | { | ||
659 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; | ||
660 | |||
661 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { | ||
662 | chalk_ir::InEnvironment { | ||
663 | environment: self.environment.to_chalk(db), | ||
664 | goal: self.value.to_chalk(db), | ||
665 | } | ||
666 | } | ||
667 | |||
668 | fn from_chalk( | ||
669 | db: &dyn HirDatabase, | ||
670 | in_env: chalk_ir::InEnvironment<T::Chalk>, | ||
671 | ) -> super::InEnvironment<T> { | ||
672 | super::InEnvironment { | ||
673 | environment: from_chalk(db, in_env.environment), | ||
674 | value: from_chalk(db, in_env.goal), | ||
675 | } | ||
676 | } | ||
677 | } | ||
678 | |||
679 | impl ToChalk for builtin::BuiltinImplData { | ||
680 | type Chalk = ImplDatum; | ||
681 | |||
682 | fn to_chalk(self, db: &dyn HirDatabase) -> ImplDatum { | ||
683 | let impl_type = chalk_rust_ir::ImplType::External; | ||
684 | let where_clauses = self.where_clauses.into_iter().map(|w| w.to_chalk(db)).collect(); | ||
685 | |||
686 | let impl_datum_bound = | ||
687 | chalk_rust_ir::ImplDatumBound { trait_ref: self.trait_ref.to_chalk(db), where_clauses }; | ||
688 | let associated_ty_value_ids = | ||
689 | self.assoc_ty_values.into_iter().map(|v| v.to_chalk(db)).collect(); | ||
690 | chalk_rust_ir::ImplDatum { | ||
691 | binders: make_binders(impl_datum_bound, self.num_vars), | ||
692 | impl_type, | ||
693 | polarity: chalk_rust_ir::Polarity::Positive, | ||
694 | associated_ty_value_ids, | ||
695 | } | ||
696 | } | ||
697 | |||
698 | fn from_chalk(_db: &dyn HirDatabase, _data: ImplDatum) -> Self { | ||
699 | unimplemented!() | ||
700 | } | ||
701 | } | ||
702 | |||
703 | impl ToChalk for builtin::BuiltinImplAssocTyValueData { | ||
704 | type Chalk = AssociatedTyValue; | ||
705 | |||
706 | fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValue { | ||
707 | let ty = self.value.to_chalk(db); | ||
708 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty }; | ||
709 | |||
710 | chalk_rust_ir::AssociatedTyValue { | ||
711 | associated_ty_id: self.assoc_ty_id.to_chalk(db), | ||
712 | impl_id: self.impl_.to_chalk(db), | ||
713 | value: make_binders(value_bound, self.num_vars), | ||
714 | } | ||
715 | } | ||
716 | |||
717 | fn from_chalk( | ||
718 | _db: &dyn HirDatabase, | ||
719 | _data: AssociatedTyValue, | ||
720 | ) -> builtin::BuiltinImplAssocTyValueData { | ||
721 | unimplemented!() | ||
722 | } | ||
723 | } | ||
724 | |||
725 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> | ||
726 | where | ||
727 | T: HasInterner<Interner = Interner>, | ||
728 | { | ||
729 | chalk_ir::Binders::new( | ||
730 | chalk_ir::ParameterKinds::from( | ||
731 | &Interner, | ||
732 | std::iter::repeat(chalk_ir::ParameterKind::Ty(())).take(num_vars), | ||
733 | ), | ||
734 | value, | ||
735 | ) | ||
736 | } | ||
737 | |||
738 | fn convert_where_clauses( | ||
739 | db: &dyn HirDatabase, | ||
740 | def: GenericDefId, | ||
741 | substs: &Substs, | ||
742 | ) -> Vec<chalk_ir::QuantifiedWhereClause<Interner>> { | ||
743 | let generic_predicates = db.generic_predicates(def); | ||
744 | let mut result = Vec::with_capacity(generic_predicates.len()); | ||
745 | for pred in generic_predicates.iter() { | ||
746 | if pred.value.is_error() { | ||
747 | // skip errored predicates completely | ||
748 | continue; | ||
749 | } | ||
750 | result.push(pred.clone().subst(substs).to_chalk(db)); | ||
751 | } | ||
752 | result | ||
753 | } | ||
754 | |||
755 | fn generic_predicate_to_inline_bound( | ||
756 | db: &dyn HirDatabase, | ||
757 | pred: &GenericPredicate, | ||
758 | self_ty: &Ty, | ||
759 | ) -> Option<chalk_rust_ir::InlineBound<Interner>> { | ||
760 | // An InlineBound is like a GenericPredicate, except the self type is left out. | ||
761 | // We don't have a special type for this, but Chalk does. | ||
762 | match pred { | ||
763 | GenericPredicate::Implemented(trait_ref) => { | ||
764 | if &trait_ref.substs[0] != self_ty { | ||
765 | // we can only convert predicates back to type bounds if they | ||
766 | // have the expected self type | ||
767 | return None; | ||
768 | } | ||
769 | let args_no_self = trait_ref.substs[1..] | ||
770 | .iter() | ||
771 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | ||
772 | .collect(); | ||
773 | let trait_bound = | ||
774 | chalk_rust_ir::TraitBound { trait_id: trait_ref.trait_.to_chalk(db), args_no_self }; | ||
775 | Some(chalk_rust_ir::InlineBound::TraitBound(trait_bound)) | ||
776 | } | ||
777 | GenericPredicate::Projection(proj) => { | ||
778 | if &proj.projection_ty.parameters[0] != self_ty { | ||
779 | return None; | ||
780 | } | ||
781 | let trait_ = match proj.projection_ty.associated_ty.lookup(db.upcast()).container { | ||
782 | AssocContainerId::TraitId(t) => t, | ||
783 | _ => panic!("associated type not in trait"), | ||
784 | }; | ||
785 | let args_no_self = proj.projection_ty.parameters[1..] | ||
786 | .iter() | ||
787 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | ||
788 | .collect(); | ||
789 | let alias_eq_bound = chalk_rust_ir::AliasEqBound { | ||
790 | value: proj.ty.clone().to_chalk(db), | ||
791 | trait_bound: chalk_rust_ir::TraitBound { | ||
792 | trait_id: trait_.to_chalk(db), | ||
793 | args_no_self, | ||
794 | }, | ||
795 | associated_ty_id: proj.projection_ty.associated_ty.to_chalk(db), | ||
796 | parameters: Vec::new(), // FIXME we don't support generic associated types yet | ||
797 | }; | ||
798 | Some(chalk_rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) | ||
799 | } | ||
800 | GenericPredicate::Error => None, | ||
801 | } | ||
802 | } | ||
803 | |||
804 | impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | 41 | impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { |
805 | fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> { | 42 | fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> { |
806 | self.db.associated_ty_data(id) | 43 | self.db.associated_ty_data(id) |
@@ -808,16 +45,24 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
808 | fn trait_datum(&self, trait_id: TraitId) -> Arc<TraitDatum> { | 45 | fn trait_datum(&self, trait_id: TraitId) -> Arc<TraitDatum> { |
809 | self.db.trait_datum(self.krate, trait_id) | 46 | self.db.trait_datum(self.krate, trait_id) |
810 | } | 47 | } |
811 | fn struct_datum(&self, struct_id: StructId) -> Arc<StructDatum> { | 48 | fn adt_datum(&self, struct_id: AdtId) -> Arc<StructDatum> { |
812 | self.db.struct_datum(self.krate, struct_id) | 49 | self.db.struct_datum(self.krate, struct_id) |
813 | } | 50 | } |
814 | fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> { | 51 | fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> { |
815 | self.db.impl_datum(self.krate, impl_id) | 52 | self.db.impl_datum(self.krate, impl_id) |
816 | } | 53 | } |
54 | |||
55 | fn fn_def_datum( | ||
56 | &self, | ||
57 | fn_def_id: chalk_ir::FnDefId<Interner>, | ||
58 | ) -> Arc<chalk_rust_ir::FnDefDatum<Interner>> { | ||
59 | self.db.fn_def_datum(self.krate, fn_def_id) | ||
60 | } | ||
61 | |||
817 | fn impls_for_trait( | 62 | fn impls_for_trait( |
818 | &self, | 63 | &self, |
819 | trait_id: TraitId, | 64 | trait_id: TraitId, |
820 | parameters: &[Parameter<Interner>], | 65 | parameters: &[GenericArg<Interner>], |
821 | ) -> Vec<ImplId> { | 66 | ) -> Vec<ImplId> { |
822 | debug!("impls_for_trait {:?}", trait_id); | 67 | debug!("impls_for_trait {:?}", trait_id); |
823 | let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); | 68 | let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); |
@@ -848,7 +93,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
848 | debug!("impls_for_trait returned {} impls", result.len()); | 93 | debug!("impls_for_trait returned {} impls", result.len()); |
849 | result | 94 | result |
850 | } | 95 | } |
851 | fn impl_provided_for(&self, auto_trait_id: TraitId, struct_id: StructId) -> bool { | 96 | fn impl_provided_for(&self, auto_trait_id: TraitId, struct_id: AdtId) -> bool { |
852 | debug!("impl_provided_for {:?}, {:?}", auto_trait_id, struct_id); | 97 | debug!("impl_provided_for {:?}, {:?}", auto_trait_id, struct_id); |
853 | false // FIXME | 98 | false // FIXME |
854 | } | 99 | } |
@@ -862,21 +107,20 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
862 | // We don't do coherence checking (yet) | 107 | // We don't do coherence checking (yet) |
863 | unimplemented!() | 108 | unimplemented!() |
864 | } | 109 | } |
865 | fn as_struct_id(&self, id: &TypeName<Interner>) -> Option<StructId> { | ||
866 | match id { | ||
867 | TypeName::Struct(struct_id) => Some(*struct_id), | ||
868 | _ => None, | ||
869 | } | ||
870 | } | ||
871 | fn interner(&self) -> &Interner { | 110 | fn interner(&self) -> &Interner { |
872 | &Interner | 111 | &Interner |
873 | } | 112 | } |
874 | fn well_known_trait_id( | 113 | fn well_known_trait_id( |
875 | &self, | 114 | &self, |
876 | _well_known_trait: chalk_rust_ir::WellKnownTrait, | 115 | well_known_trait: chalk_rust_ir::WellKnownTrait, |
877 | ) -> Option<chalk_ir::TraitId<Interner>> { | 116 | ) -> Option<chalk_ir::TraitId<Interner>> { |
878 | // FIXME tell Chalk about well-known traits (here and in trait_datum) | 117 | let lang_attr = lang_attr_from_well_known_trait(well_known_trait); |
879 | None | 118 | let lang_items = self.db.crate_lang_items(self.krate); |
119 | let trait_ = match lang_items.target(lang_attr) { | ||
120 | Some(LangItemTarget::TraitId(trait_)) => trait_, | ||
121 | _ => return None, | ||
122 | }; | ||
123 | Some(trait_.to_chalk(self.db)) | ||
880 | } | 124 | } |
881 | 125 | ||
882 | fn program_clauses_for_env( | 126 | fn program_clauses_for_env( |
@@ -892,6 +136,20 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
892 | ) -> Arc<chalk_rust_ir::OpaqueTyDatum<Interner>> { | 136 | ) -> Arc<chalk_rust_ir::OpaqueTyDatum<Interner>> { |
893 | unimplemented!() | 137 | unimplemented!() |
894 | } | 138 | } |
139 | |||
140 | fn force_impl_for( | ||
141 | &self, | ||
142 | _well_known: chalk_rust_ir::WellKnownTrait, | ||
143 | _ty: &chalk_ir::TyData<Interner>, | ||
144 | ) -> Option<bool> { | ||
145 | // this method is mostly for rustc | ||
146 | None | ||
147 | } | ||
148 | |||
149 | fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool { | ||
150 | // FIXME: implement actual object safety | ||
151 | true | ||
152 | } | ||
895 | } | 153 | } |
896 | 154 | ||
897 | pub(crate) fn program_clauses_for_chalk_env_query( | 155 | pub(crate) fn program_clauses_for_chalk_env_query( |
@@ -964,7 +222,8 @@ pub(crate) fn trait_datum_query( | |||
964 | let associated_ty_ids = | 222 | let associated_ty_ids = |
965 | trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect(); | 223 | trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect(); |
966 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses }; | 224 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses }; |
967 | let well_known = None; // FIXME set this (depending on lang items) | 225 | let well_known = |
226 | lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name)); | ||
968 | let trait_datum = TraitDatum { | 227 | let trait_datum = TraitDatum { |
969 | id: trait_id, | 228 | id: trait_id, |
970 | binders: make_binders(trait_datum_bound, bound_vars.len()), | 229 | binders: make_binders(trait_datum_bound, bound_vars.len()), |
@@ -975,13 +234,32 @@ pub(crate) fn trait_datum_query( | |||
975 | Arc::new(trait_datum) | 234 | Arc::new(trait_datum) |
976 | } | 235 | } |
977 | 236 | ||
237 | fn well_known_trait_from_lang_attr(name: &str) -> Option<WellKnownTrait> { | ||
238 | Some(match name { | ||
239 | "sized" => WellKnownTrait::SizedTrait, | ||
240 | "copy" => WellKnownTrait::CopyTrait, | ||
241 | "clone" => WellKnownTrait::CloneTrait, | ||
242 | "drop" => WellKnownTrait::DropTrait, | ||
243 | _ => return None, | ||
244 | }) | ||
245 | } | ||
246 | |||
247 | fn lang_attr_from_well_known_trait(attr: WellKnownTrait) -> &'static str { | ||
248 | match attr { | ||
249 | WellKnownTrait::SizedTrait => "sized", | ||
250 | WellKnownTrait::CopyTrait => "copy", | ||
251 | WellKnownTrait::CloneTrait => "clone", | ||
252 | WellKnownTrait::DropTrait => "drop", | ||
253 | } | ||
254 | } | ||
255 | |||
978 | pub(crate) fn struct_datum_query( | 256 | pub(crate) fn struct_datum_query( |
979 | db: &dyn HirDatabase, | 257 | db: &dyn HirDatabase, |
980 | krate: CrateId, | 258 | krate: CrateId, |
981 | struct_id: StructId, | 259 | struct_id: AdtId, |
982 | ) -> Arc<StructDatum> { | 260 | ) -> Arc<StructDatum> { |
983 | debug!("struct_datum {:?}", struct_id); | 261 | debug!("struct_datum {:?}", struct_id); |
984 | let type_ctor: TypeCtor = from_chalk(db, TypeName::Struct(struct_id)); | 262 | let type_ctor: TypeCtor = from_chalk(db, TypeName::Adt(struct_id)); |
985 | debug!("struct {:?} = {:?}", struct_id, type_ctor); | 263 | debug!("struct {:?} = {:?}", struct_id, type_ctor); |
986 | let num_params = type_ctor.num_ty_params(db); | 264 | let num_params = type_ctor.num_ty_params(db); |
987 | let upstream = type_ctor.krate(db) != Some(krate); | 265 | let upstream = type_ctor.krate(db) != Some(krate); |
@@ -993,12 +271,12 @@ pub(crate) fn struct_datum_query( | |||
993 | convert_where_clauses(db, generic_def, &bound_vars) | 271 | convert_where_clauses(db, generic_def, &bound_vars) |
994 | }) | 272 | }) |
995 | .unwrap_or_else(Vec::new); | 273 | .unwrap_or_else(Vec::new); |
996 | let flags = chalk_rust_ir::StructFlags { | 274 | let flags = chalk_rust_ir::AdtFlags { |
997 | upstream, | 275 | upstream, |
998 | // FIXME set fundamental flag correctly | 276 | // FIXME set fundamental flag correctly |
999 | fundamental: false, | 277 | fundamental: false, |
1000 | }; | 278 | }; |
1001 | let struct_datum_bound = chalk_rust_ir::StructDatumBound { | 279 | let struct_datum_bound = chalk_rust_ir::AdtDatumBound { |
1002 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits) | 280 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits) |
1003 | where_clauses, | 281 | where_clauses, |
1004 | }; | 282 | }; |
@@ -1126,15 +404,47 @@ fn type_alias_associated_ty_value( | |||
1126 | Arc::new(value) | 404 | Arc::new(value) |
1127 | } | 405 | } |
1128 | 406 | ||
1129 | impl From<StructId> for crate::TypeCtorId { | 407 | pub(crate) fn fn_def_datum_query( |
1130 | fn from(struct_id: StructId) -> Self { | 408 | db: &dyn HirDatabase, |
1131 | InternKey::from_intern_id(struct_id.0) | 409 | _krate: CrateId, |
410 | fn_def_id: FnDefId, | ||
411 | ) -> Arc<FnDefDatum> { | ||
412 | let callable_def: CallableDef = from_chalk(db, fn_def_id); | ||
413 | let generic_params = generics(db.upcast(), callable_def.into()); | ||
414 | let sig = db.callable_item_signature(callable_def); | ||
415 | let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); | ||
416 | let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars); | ||
417 | let bound = chalk_rust_ir::FnDefDatumBound { | ||
418 | // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway | ||
419 | argument_types: sig.value.params().iter().map(|ty| ty.clone().to_chalk(db)).collect(), | ||
420 | return_type: sig.value.ret().clone().to_chalk(db), | ||
421 | where_clauses, | ||
422 | }; | ||
423 | let datum = FnDefDatum { id: fn_def_id, binders: make_binders(bound, sig.num_binders) }; | ||
424 | Arc::new(datum) | ||
425 | } | ||
426 | |||
427 | impl From<AdtId> for crate::TypeCtorId { | ||
428 | fn from(struct_id: AdtId) -> Self { | ||
429 | struct_id.0 | ||
1132 | } | 430 | } |
1133 | } | 431 | } |
1134 | 432 | ||
1135 | impl From<crate::TypeCtorId> for StructId { | 433 | impl From<crate::TypeCtorId> for AdtId { |
1136 | fn from(type_ctor_id: crate::TypeCtorId) -> Self { | 434 | fn from(type_ctor_id: crate::TypeCtorId) -> Self { |
1137 | chalk_ir::StructId(type_ctor_id.as_intern_id()) | 435 | chalk_ir::AdtId(type_ctor_id) |
436 | } | ||
437 | } | ||
438 | |||
439 | impl From<FnDefId> for crate::CallableDefId { | ||
440 | fn from(fn_def_id: FnDefId) -> Self { | ||
441 | InternKey::from_intern_id(fn_def_id.0) | ||
442 | } | ||
443 | } | ||
444 | |||
445 | impl From<crate::CallableDefId> for FnDefId { | ||
446 | fn from(callable_def_id: crate::CallableDefId) -> Self { | ||
447 | chalk_ir::FnDefId(callable_def_id.as_intern_id()) | ||
1138 | } | 448 | } |
1139 | } | 449 | } |
1140 | 450 | ||
diff --git a/crates/ra_hir_ty/src/traits/chalk/interner.rs b/crates/ra_hir_ty/src/traits/chalk/interner.rs new file mode 100644 index 000000000..2a27f8ed8 --- /dev/null +++ b/crates/ra_hir_ty/src/traits/chalk/interner.rs | |||
@@ -0,0 +1,353 @@ | |||
1 | //! Implementation of the Chalk `Interner` trait, which allows customizing the | ||
2 | //! representation of the various objects Chalk deals with (types, goals etc.). | ||
3 | |||
4 | use super::tls; | ||
5 | use chalk_ir::{GenericArg, Goal, GoalData}; | ||
6 | use hir_def::TypeAliasId; | ||
7 | use ra_db::salsa::InternId; | ||
8 | use std::{fmt, sync::Arc}; | ||
9 | |||
10 | #[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] | ||
11 | pub struct Interner; | ||
12 | |||
13 | pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; | ||
14 | pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum<Interner>; | ||
15 | pub type TraitId = chalk_ir::TraitId<Interner>; | ||
16 | pub type TraitDatum = chalk_rust_ir::TraitDatum<Interner>; | ||
17 | pub type AdtId = chalk_ir::AdtId<Interner>; | ||
18 | pub type StructDatum = chalk_rust_ir::AdtDatum<Interner>; | ||
19 | pub type ImplId = chalk_ir::ImplId<Interner>; | ||
20 | pub type ImplDatum = chalk_rust_ir::ImplDatum<Interner>; | ||
21 | pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId<Interner>; | ||
22 | pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<Interner>; | ||
23 | pub type FnDefId = chalk_ir::FnDefId<Interner>; | ||
24 | pub type FnDefDatum = chalk_rust_ir::FnDefDatum<Interner>; | ||
25 | |||
26 | impl chalk_ir::interner::Interner for Interner { | ||
27 | type InternedType = Box<chalk_ir::TyData<Self>>; // FIXME use Arc? | ||
28 | type InternedLifetime = chalk_ir::LifetimeData<Self>; | ||
29 | type InternedConst = Arc<chalk_ir::ConstData<Self>>; | ||
30 | type InternedConcreteConst = (); | ||
31 | type InternedGenericArg = chalk_ir::GenericArgData<Self>; | ||
32 | type InternedGoal = Arc<GoalData<Self>>; | ||
33 | type InternedGoals = Vec<Goal<Self>>; | ||
34 | type InternedSubstitution = Vec<GenericArg<Self>>; | ||
35 | type InternedProgramClause = chalk_ir::ProgramClauseData<Self>; | ||
36 | type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>; | ||
37 | type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; | ||
38 | type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>; | ||
39 | type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>; | ||
40 | type DefId = InternId; | ||
41 | type InternedAdtId = crate::TypeCtorId; | ||
42 | type Identifier = TypeAliasId; | ||
43 | |||
44 | fn debug_adt_id(type_kind_id: AdtId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
45 | tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt))) | ||
46 | } | ||
47 | |||
48 | fn debug_trait_id(type_kind_id: TraitId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
49 | tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt))) | ||
50 | } | ||
51 | |||
52 | fn debug_assoc_type_id(id: AssocTypeId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
53 | tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt))) | ||
54 | } | ||
55 | |||
56 | fn debug_alias( | ||
57 | alias: &chalk_ir::AliasTy<Interner>, | ||
58 | fmt: &mut fmt::Formatter<'_>, | ||
59 | ) -> Option<fmt::Result> { | ||
60 | tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt))) | ||
61 | } | ||
62 | |||
63 | fn debug_projection_ty( | ||
64 | proj: &chalk_ir::ProjectionTy<Interner>, | ||
65 | fmt: &mut fmt::Formatter<'_>, | ||
66 | ) -> Option<fmt::Result> { | ||
67 | tls::with_current_program(|prog| Some(prog?.debug_projection_ty(proj, fmt))) | ||
68 | } | ||
69 | |||
70 | fn debug_opaque_ty( | ||
71 | opaque_ty: &chalk_ir::OpaqueTy<Interner>, | ||
72 | fmt: &mut fmt::Formatter<'_>, | ||
73 | ) -> Option<fmt::Result> { | ||
74 | tls::with_current_program(|prog| Some(prog?.debug_opaque_ty(opaque_ty, fmt))) | ||
75 | } | ||
76 | |||
77 | fn debug_opaque_ty_id( | ||
78 | opaque_ty_id: chalk_ir::OpaqueTyId<Self>, | ||
79 | fmt: &mut fmt::Formatter<'_>, | ||
80 | ) -> Option<fmt::Result> { | ||
81 | tls::with_current_program(|prog| Some(prog?.debug_opaque_ty_id(opaque_ty_id, fmt))) | ||
82 | } | ||
83 | |||
84 | fn debug_ty(ty: &chalk_ir::Ty<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
85 | tls::with_current_program(|prog| Some(prog?.debug_ty(ty, fmt))) | ||
86 | } | ||
87 | |||
88 | fn debug_lifetime( | ||
89 | lifetime: &chalk_ir::Lifetime<Interner>, | ||
90 | fmt: &mut fmt::Formatter<'_>, | ||
91 | ) -> Option<fmt::Result> { | ||
92 | tls::with_current_program(|prog| Some(prog?.debug_lifetime(lifetime, fmt))) | ||
93 | } | ||
94 | |||
95 | fn debug_generic_arg( | ||
96 | parameter: &GenericArg<Interner>, | ||
97 | fmt: &mut fmt::Formatter<'_>, | ||
98 | ) -> Option<fmt::Result> { | ||
99 | tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt))) | ||
100 | } | ||
101 | |||
102 | fn debug_goal(goal: &Goal<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | ||
103 | tls::with_current_program(|prog| Some(prog?.debug_goal(goal, fmt))) | ||
104 | } | ||
105 | |||
106 | fn debug_goals( | ||
107 | goals: &chalk_ir::Goals<Interner>, | ||
108 | fmt: &mut fmt::Formatter<'_>, | ||
109 | ) -> Option<fmt::Result> { | ||
110 | tls::with_current_program(|prog| Some(prog?.debug_goals(goals, fmt))) | ||
111 | } | ||
112 | |||
113 | fn debug_program_clause_implication( | ||
114 | pci: &chalk_ir::ProgramClauseImplication<Interner>, | ||
115 | fmt: &mut fmt::Formatter<'_>, | ||
116 | ) -> Option<fmt::Result> { | ||
117 | tls::with_current_program(|prog| Some(prog?.debug_program_clause_implication(pci, fmt))) | ||
118 | } | ||
119 | |||
120 | fn debug_application_ty( | ||
121 | application_ty: &chalk_ir::ApplicationTy<Interner>, | ||
122 | fmt: &mut fmt::Formatter<'_>, | ||
123 | ) -> Option<fmt::Result> { | ||
124 | tls::with_current_program(|prog| Some(prog?.debug_application_ty(application_ty, fmt))) | ||
125 | } | ||
126 | |||
127 | fn debug_substitution( | ||
128 | substitution: &chalk_ir::Substitution<Interner>, | ||
129 | fmt: &mut fmt::Formatter<'_>, | ||
130 | ) -> Option<fmt::Result> { | ||
131 | tls::with_current_program(|prog| Some(prog?.debug_substitution(substitution, fmt))) | ||
132 | } | ||
133 | |||
134 | fn debug_separator_trait_ref( | ||
135 | separator_trait_ref: &chalk_ir::SeparatorTraitRef<Interner>, | ||
136 | fmt: &mut fmt::Formatter<'_>, | ||
137 | ) -> Option<fmt::Result> { | ||
138 | tls::with_current_program(|prog| { | ||
139 | Some(prog?.debug_separator_trait_ref(separator_trait_ref, fmt)) | ||
140 | }) | ||
141 | } | ||
142 | |||
143 | fn debug_fn_def_id( | ||
144 | fn_def_id: chalk_ir::FnDefId<Self>, | ||
145 | fmt: &mut fmt::Formatter<'_>, | ||
146 | ) -> Option<fmt::Result> { | ||
147 | tls::with_current_program(|prog| Some(prog?.debug_fn_def_id(fn_def_id, fmt))) | ||
148 | } | ||
149 | fn debug_const( | ||
150 | constant: &chalk_ir::Const<Self>, | ||
151 | fmt: &mut fmt::Formatter<'_>, | ||
152 | ) -> Option<fmt::Result> { | ||
153 | tls::with_current_program(|prog| Some(prog?.debug_const(constant, fmt))) | ||
154 | } | ||
155 | fn debug_variable_kinds( | ||
156 | variable_kinds: &chalk_ir::VariableKinds<Self>, | ||
157 | fmt: &mut fmt::Formatter<'_>, | ||
158 | ) -> Option<fmt::Result> { | ||
159 | tls::with_current_program(|prog| Some(prog?.debug_variable_kinds(variable_kinds, fmt))) | ||
160 | } | ||
161 | fn debug_variable_kinds_with_angles( | ||
162 | variable_kinds: &chalk_ir::VariableKinds<Self>, | ||
163 | fmt: &mut fmt::Formatter<'_>, | ||
164 | ) -> Option<fmt::Result> { | ||
165 | tls::with_current_program(|prog| { | ||
166 | Some(prog?.debug_variable_kinds_with_angles(variable_kinds, fmt)) | ||
167 | }) | ||
168 | } | ||
169 | fn debug_canonical_var_kinds( | ||
170 | canonical_var_kinds: &chalk_ir::CanonicalVarKinds<Self>, | ||
171 | fmt: &mut fmt::Formatter<'_>, | ||
172 | ) -> Option<fmt::Result> { | ||
173 | tls::with_current_program(|prog| { | ||
174 | Some(prog?.debug_canonical_var_kinds(canonical_var_kinds, fmt)) | ||
175 | }) | ||
176 | } | ||
177 | fn debug_program_clause( | ||
178 | clause: &chalk_ir::ProgramClause<Self>, | ||
179 | fmt: &mut fmt::Formatter<'_>, | ||
180 | ) -> Option<fmt::Result> { | ||
181 | tls::with_current_program(|prog| Some(prog?.debug_program_clause(clause, fmt))) | ||
182 | } | ||
183 | fn debug_program_clauses( | ||
184 | clauses: &chalk_ir::ProgramClauses<Self>, | ||
185 | fmt: &mut fmt::Formatter<'_>, | ||
186 | ) -> Option<fmt::Result> { | ||
187 | tls::with_current_program(|prog| Some(prog?.debug_program_clauses(clauses, fmt))) | ||
188 | } | ||
189 | fn debug_quantified_where_clauses( | ||
190 | clauses: &chalk_ir::QuantifiedWhereClauses<Self>, | ||
191 | fmt: &mut fmt::Formatter<'_>, | ||
192 | ) -> Option<fmt::Result> { | ||
193 | tls::with_current_program(|prog| Some(prog?.debug_quantified_where_clauses(clauses, fmt))) | ||
194 | } | ||
195 | |||
196 | fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> { | ||
197 | Box::new(ty) | ||
198 | } | ||
199 | |||
200 | fn ty_data<'a>(&self, ty: &'a Box<chalk_ir::TyData<Self>>) -> &'a chalk_ir::TyData<Self> { | ||
201 | ty | ||
202 | } | ||
203 | |||
204 | fn intern_lifetime( | ||
205 | &self, | ||
206 | lifetime: chalk_ir::LifetimeData<Self>, | ||
207 | ) -> chalk_ir::LifetimeData<Self> { | ||
208 | lifetime | ||
209 | } | ||
210 | |||
211 | fn lifetime_data<'a>( | ||
212 | &self, | ||
213 | lifetime: &'a chalk_ir::LifetimeData<Self>, | ||
214 | ) -> &'a chalk_ir::LifetimeData<Self> { | ||
215 | lifetime | ||
216 | } | ||
217 | |||
218 | fn intern_const(&self, constant: chalk_ir::ConstData<Self>) -> Arc<chalk_ir::ConstData<Self>> { | ||
219 | Arc::new(constant) | ||
220 | } | ||
221 | |||
222 | fn const_data<'a>( | ||
223 | &self, | ||
224 | constant: &'a Arc<chalk_ir::ConstData<Self>>, | ||
225 | ) -> &'a chalk_ir::ConstData<Self> { | ||
226 | constant | ||
227 | } | ||
228 | |||
229 | fn const_eq(&self, _ty: &Box<chalk_ir::TyData<Self>>, _c1: &(), _c2: &()) -> bool { | ||
230 | true | ||
231 | } | ||
232 | |||
233 | fn intern_generic_arg( | ||
234 | &self, | ||
235 | parameter: chalk_ir::GenericArgData<Self>, | ||
236 | ) -> chalk_ir::GenericArgData<Self> { | ||
237 | parameter | ||
238 | } | ||
239 | |||
240 | fn generic_arg_data<'a>( | ||
241 | &self, | ||
242 | parameter: &'a chalk_ir::GenericArgData<Self>, | ||
243 | ) -> &'a chalk_ir::GenericArgData<Self> { | ||
244 | parameter | ||
245 | } | ||
246 | |||
247 | fn intern_goal(&self, goal: GoalData<Self>) -> Arc<GoalData<Self>> { | ||
248 | Arc::new(goal) | ||
249 | } | ||
250 | |||
251 | fn intern_goals<E>( | ||
252 | &self, | ||
253 | data: impl IntoIterator<Item = Result<Goal<Self>, E>>, | ||
254 | ) -> Result<Self::InternedGoals, E> { | ||
255 | data.into_iter().collect() | ||
256 | } | ||
257 | |||
258 | fn goal_data<'a>(&self, goal: &'a Arc<GoalData<Self>>) -> &'a GoalData<Self> { | ||
259 | goal | ||
260 | } | ||
261 | |||
262 | fn goals_data<'a>(&self, goals: &'a Vec<Goal<Interner>>) -> &'a [Goal<Interner>] { | ||
263 | goals | ||
264 | } | ||
265 | |||
266 | fn intern_substitution<E>( | ||
267 | &self, | ||
268 | data: impl IntoIterator<Item = Result<GenericArg<Self>, E>>, | ||
269 | ) -> Result<Vec<GenericArg<Self>>, E> { | ||
270 | data.into_iter().collect() | ||
271 | } | ||
272 | |||
273 | fn substitution_data<'a>( | ||
274 | &self, | ||
275 | substitution: &'a Vec<GenericArg<Self>>, | ||
276 | ) -> &'a [GenericArg<Self>] { | ||
277 | substitution | ||
278 | } | ||
279 | |||
280 | fn intern_program_clause( | ||
281 | &self, | ||
282 | data: chalk_ir::ProgramClauseData<Self>, | ||
283 | ) -> chalk_ir::ProgramClauseData<Self> { | ||
284 | data | ||
285 | } | ||
286 | |||
287 | fn program_clause_data<'a>( | ||
288 | &self, | ||
289 | clause: &'a chalk_ir::ProgramClauseData<Self>, | ||
290 | ) -> &'a chalk_ir::ProgramClauseData<Self> { | ||
291 | clause | ||
292 | } | ||
293 | |||
294 | fn intern_program_clauses<E>( | ||
295 | &self, | ||
296 | data: impl IntoIterator<Item = Result<chalk_ir::ProgramClause<Self>, E>>, | ||
297 | ) -> Result<Arc<[chalk_ir::ProgramClause<Self>]>, E> { | ||
298 | data.into_iter().collect() | ||
299 | } | ||
300 | |||
301 | fn program_clauses_data<'a>( | ||
302 | &self, | ||
303 | clauses: &'a Arc<[chalk_ir::ProgramClause<Self>]>, | ||
304 | ) -> &'a [chalk_ir::ProgramClause<Self>] { | ||
305 | &clauses | ||
306 | } | ||
307 | |||
308 | fn intern_quantified_where_clauses<E>( | ||
309 | &self, | ||
310 | data: impl IntoIterator<Item = Result<chalk_ir::QuantifiedWhereClause<Self>, E>>, | ||
311 | ) -> Result<Self::InternedQuantifiedWhereClauses, E> { | ||
312 | data.into_iter().collect() | ||
313 | } | ||
314 | |||
315 | fn quantified_where_clauses_data<'a>( | ||
316 | &self, | ||
317 | clauses: &'a Self::InternedQuantifiedWhereClauses, | ||
318 | ) -> &'a [chalk_ir::QuantifiedWhereClause<Self>] { | ||
319 | clauses | ||
320 | } | ||
321 | |||
322 | fn intern_generic_arg_kinds<E>( | ||
323 | &self, | ||
324 | data: impl IntoIterator<Item = Result<chalk_ir::VariableKind<Self>, E>>, | ||
325 | ) -> Result<Self::InternedVariableKinds, E> { | ||
326 | data.into_iter().collect() | ||
327 | } | ||
328 | |||
329 | fn variable_kinds_data<'a>( | ||
330 | &self, | ||
331 | parameter_kinds: &'a Self::InternedVariableKinds, | ||
332 | ) -> &'a [chalk_ir::VariableKind<Self>] { | ||
333 | ¶meter_kinds | ||
334 | } | ||
335 | |||
336 | fn intern_canonical_var_kinds<E>( | ||
337 | &self, | ||
338 | data: impl IntoIterator<Item = Result<chalk_ir::CanonicalVarKind<Self>, E>>, | ||
339 | ) -> Result<Self::InternedCanonicalVarKinds, E> { | ||
340 | data.into_iter().collect() | ||
341 | } | ||
342 | |||
343 | fn canonical_var_kinds_data<'a>( | ||
344 | &self, | ||
345 | canonical_var_kinds: &'a Self::InternedCanonicalVarKinds, | ||
346 | ) -> &'a [chalk_ir::CanonicalVarKind<Self>] { | ||
347 | &canonical_var_kinds | ||
348 | } | ||
349 | } | ||
350 | |||
351 | impl chalk_ir::interner::HasInterner for Interner { | ||
352 | type Interner = Self; | ||
353 | } | ||
diff --git a/crates/ra_hir_ty/src/traits/chalk/mapping.rs b/crates/ra_hir_ty/src/traits/chalk/mapping.rs new file mode 100644 index 000000000..7082cb095 --- /dev/null +++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs | |||
@@ -0,0 +1,701 @@ | |||
1 | //! This module contains the implementations of the `ToChalk` trait, which | ||
2 | //! handles conversion between our data types and their corresponding types in | ||
3 | //! Chalk (in both directions); plus some helper functions for more specialized | ||
4 | //! conversions. | ||
5 | |||
6 | use chalk_ir::{ | ||
7 | cast::Cast, fold::shift::Shift, interner::HasInterner, PlaceholderIndex, Scalar, TypeName, | ||
8 | UniverseIndex, | ||
9 | }; | ||
10 | |||
11 | use hir_def::{type_ref::Mutability, AssocContainerId, GenericDefId, Lookup, TypeAliasId}; | ||
12 | use ra_db::salsa::InternKey; | ||
13 | |||
14 | use crate::{ | ||
15 | db::HirDatabase, | ||
16 | primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain}, | ||
17 | traits::{builtin, AssocTyValue, Canonical, Impl, Obligation}, | ||
18 | ApplicationTy, CallableDef, GenericPredicate, InEnvironment, ProjectionPredicate, ProjectionTy, | ||
19 | Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, | ||
20 | }; | ||
21 | |||
22 | use super::interner::*; | ||
23 | use super::*; | ||
24 | |||
25 | impl ToChalk for Ty { | ||
26 | type Chalk = chalk_ir::Ty<Interner>; | ||
27 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> { | ||
28 | match self { | ||
29 | Ty::Apply(apply_ty) => match apply_ty.ctor { | ||
30 | TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters), | ||
31 | TypeCtor::FnPtr { num_args: _ } => { | ||
32 | let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner); | ||
33 | chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: 0, substitution }) | ||
34 | .intern(&Interner) | ||
35 | } | ||
36 | _ => { | ||
37 | let name = apply_ty.ctor.to_chalk(db); | ||
38 | let substitution = apply_ty.parameters.to_chalk(db); | ||
39 | chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) | ||
40 | } | ||
41 | }, | ||
42 | Ty::Projection(proj_ty) => { | ||
43 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); | ||
44 | let substitution = proj_ty.parameters.to_chalk(db); | ||
45 | chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { | ||
46 | associated_ty_id, | ||
47 | substitution, | ||
48 | }) | ||
49 | .cast(&Interner) | ||
50 | .intern(&Interner) | ||
51 | } | ||
52 | Ty::Placeholder(id) => { | ||
53 | let interned_id = db.intern_type_param_id(id); | ||
54 | PlaceholderIndex { | ||
55 | ui: UniverseIndex::ROOT, | ||
56 | idx: interned_id.as_intern_id().as_usize(), | ||
57 | } | ||
58 | .to_ty::<Interner>(&Interner) | ||
59 | } | ||
60 | Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner), | ||
61 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), | ||
62 | Ty::Dyn(predicates) => { | ||
63 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from( | ||
64 | &Interner, | ||
65 | predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)), | ||
66 | ); | ||
67 | let bounded_ty = chalk_ir::DynTy { bounds: make_binders(where_clauses, 1) }; | ||
68 | chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) | ||
69 | } | ||
70 | Ty::Opaque(_) | Ty::Unknown => { | ||
71 | let substitution = chalk_ir::Substitution::empty(&Interner); | ||
72 | let name = TypeName::Error; | ||
73 | chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) | ||
74 | } | ||
75 | } | ||
76 | } | ||
77 | fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self { | ||
78 | match chalk.data(&Interner).clone() { | ||
79 | chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { | ||
80 | TypeName::Error => Ty::Unknown, | ||
81 | TypeName::Ref(m) => ref_from_chalk(db, m, apply_ty.substitution), | ||
82 | _ => { | ||
83 | let ctor = from_chalk(db, apply_ty.name); | ||
84 | let parameters = from_chalk(db, apply_ty.substitution); | ||
85 | Ty::Apply(ApplicationTy { ctor, parameters }) | ||
86 | } | ||
87 | }, | ||
88 | chalk_ir::TyData::Placeholder(idx) => { | ||
89 | assert_eq!(idx.ui, UniverseIndex::ROOT); | ||
90 | let interned_id = crate::db::GlobalTypeParamId::from_intern_id( | ||
91 | crate::salsa::InternId::from(idx.idx), | ||
92 | ); | ||
93 | Ty::Placeholder(db.lookup_intern_type_param_id(interned_id)) | ||
94 | } | ||
95 | chalk_ir::TyData::Alias(chalk_ir::AliasTy::Projection(proj)) => { | ||
96 | let associated_ty = from_chalk(db, proj.associated_ty_id); | ||
97 | let parameters = from_chalk(db, proj.substitution); | ||
98 | Ty::Projection(ProjectionTy { associated_ty, parameters }) | ||
99 | } | ||
100 | chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(_)) => unimplemented!(), | ||
101 | chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: _, substitution }) => { | ||
102 | let parameters: Substs = from_chalk(db, substitution); | ||
103 | Ty::Apply(ApplicationTy { | ||
104 | ctor: TypeCtor::FnPtr { num_args: (parameters.len() - 1) as u16 }, | ||
105 | parameters, | ||
106 | }) | ||
107 | } | ||
108 | chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx), | ||
109 | chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, | ||
110 | chalk_ir::TyData::Dyn(where_clauses) => { | ||
111 | assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); | ||
112 | let predicates = where_clauses | ||
113 | .bounds | ||
114 | .skip_binders() | ||
115 | .iter(&Interner) | ||
116 | .map(|c| from_chalk(db, c.clone())) | ||
117 | .collect(); | ||
118 | Ty::Dyn(predicates) | ||
119 | } | ||
120 | } | ||
121 | } | ||
122 | } | ||
123 | |||
124 | const LIFETIME_PLACEHOLDER: PlaceholderIndex = | ||
125 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX }; | ||
126 | |||
127 | /// We currently don't model lifetimes, but Chalk does. So, we have to insert a | ||
128 | /// fake lifetime here, because Chalks built-in logic may expect it to be there. | ||
129 | fn ref_to_chalk( | ||
130 | db: &dyn HirDatabase, | ||
131 | mutability: Mutability, | ||
132 | subst: Substs, | ||
133 | ) -> chalk_ir::Ty<Interner> { | ||
134 | let arg = subst[0].clone().to_chalk(db); | ||
135 | let lifetime = LIFETIME_PLACEHOLDER.to_lifetime(&Interner); | ||
136 | chalk_ir::ApplicationTy { | ||
137 | name: TypeName::Ref(mutability.to_chalk(db)), | ||
138 | substitution: chalk_ir::Substitution::from( | ||
139 | &Interner, | ||
140 | vec![lifetime.cast(&Interner), arg.cast(&Interner)], | ||
141 | ), | ||
142 | } | ||
143 | .intern(&Interner) | ||
144 | } | ||
145 | |||
146 | /// Here we remove the lifetime from the type we got from Chalk. | ||
147 | fn ref_from_chalk( | ||
148 | db: &dyn HirDatabase, | ||
149 | mutability: chalk_ir::Mutability, | ||
150 | subst: chalk_ir::Substitution<Interner>, | ||
151 | ) -> Ty { | ||
152 | let tys = subst | ||
153 | .iter(&Interner) | ||
154 | .filter_map(|p| Some(from_chalk(db, p.ty(&Interner)?.clone()))) | ||
155 | .collect(); | ||
156 | Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys)) | ||
157 | } | ||
158 | |||
159 | impl ToChalk for Substs { | ||
160 | type Chalk = chalk_ir::Substitution<Interner>; | ||
161 | |||
162 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> { | ||
163 | chalk_ir::Substitution::from(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db))) | ||
164 | } | ||
165 | |||
166 | fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs { | ||
167 | let tys = parameters | ||
168 | .iter(&Interner) | ||
169 | .map(|p| match p.ty(&Interner) { | ||
170 | Some(ty) => from_chalk(db, ty.clone()), | ||
171 | None => unimplemented!(), | ||
172 | }) | ||
173 | .collect(); | ||
174 | Substs(tys) | ||
175 | } | ||
176 | } | ||
177 | |||
178 | impl ToChalk for TraitRef { | ||
179 | type Chalk = chalk_ir::TraitRef<Interner>; | ||
180 | |||
181 | fn to_chalk(self: TraitRef, db: &dyn HirDatabase) -> chalk_ir::TraitRef<Interner> { | ||
182 | let trait_id = self.trait_.to_chalk(db); | ||
183 | let substitution = self.substs.to_chalk(db); | ||
184 | chalk_ir::TraitRef { trait_id, substitution } | ||
185 | } | ||
186 | |||
187 | fn from_chalk(db: &dyn HirDatabase, trait_ref: chalk_ir::TraitRef<Interner>) -> Self { | ||
188 | let trait_ = from_chalk(db, trait_ref.trait_id); | ||
189 | let substs = from_chalk(db, trait_ref.substitution); | ||
190 | TraitRef { trait_, substs } | ||
191 | } | ||
192 | } | ||
193 | |||
194 | impl ToChalk for hir_def::TraitId { | ||
195 | type Chalk = TraitId; | ||
196 | |||
197 | fn to_chalk(self, _db: &dyn HirDatabase) -> TraitId { | ||
198 | chalk_ir::TraitId(self.as_intern_id()) | ||
199 | } | ||
200 | |||
201 | fn from_chalk(_db: &dyn HirDatabase, trait_id: TraitId) -> hir_def::TraitId { | ||
202 | InternKey::from_intern_id(trait_id.0) | ||
203 | } | ||
204 | } | ||
205 | |||
206 | impl ToChalk for TypeCtor { | ||
207 | type Chalk = TypeName<Interner>; | ||
208 | |||
209 | fn to_chalk(self, db: &dyn HirDatabase) -> TypeName<Interner> { | ||
210 | match self { | ||
211 | TypeCtor::AssociatedType(type_alias) => { | ||
212 | let type_id = type_alias.to_chalk(db); | ||
213 | TypeName::AssociatedType(type_id) | ||
214 | } | ||
215 | |||
216 | TypeCtor::Bool => TypeName::Scalar(Scalar::Bool), | ||
217 | TypeCtor::Char => TypeName::Scalar(Scalar::Char), | ||
218 | TypeCtor::Int(Uncertain::Known(int_ty)) => TypeName::Scalar(int_ty_to_chalk(int_ty)), | ||
219 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X32 })) => { | ||
220 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F32)) | ||
221 | } | ||
222 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X64 })) => { | ||
223 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F64)) | ||
224 | } | ||
225 | |||
226 | TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()), | ||
227 | TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)), | ||
228 | TypeCtor::Slice => TypeName::Slice, | ||
229 | TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)), | ||
230 | TypeCtor::Str => TypeName::Str, | ||
231 | TypeCtor::FnDef(callable_def) => { | ||
232 | let id = callable_def.to_chalk(db); | ||
233 | TypeName::FnDef(id) | ||
234 | } | ||
235 | TypeCtor::Int(Uncertain::Unknown) | ||
236 | | TypeCtor::Float(Uncertain::Unknown) | ||
237 | | TypeCtor::Adt(_) | ||
238 | | TypeCtor::Array | ||
239 | | TypeCtor::FnPtr { .. } | ||
240 | | TypeCtor::Never | ||
241 | | TypeCtor::Closure { .. } => { | ||
242 | // other TypeCtors get interned and turned into a chalk StructId | ||
243 | let struct_id = db.intern_type_ctor(self).into(); | ||
244 | TypeName::Adt(struct_id) | ||
245 | } | ||
246 | } | ||
247 | } | ||
248 | |||
249 | fn from_chalk(db: &dyn HirDatabase, type_name: TypeName<Interner>) -> TypeCtor { | ||
250 | match type_name { | ||
251 | TypeName::Adt(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), | ||
252 | TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), | ||
253 | TypeName::OpaqueType(_) => unreachable!(), | ||
254 | |||
255 | TypeName::Scalar(Scalar::Bool) => TypeCtor::Bool, | ||
256 | TypeName::Scalar(Scalar::Char) => TypeCtor::Char, | ||
257 | TypeName::Scalar(Scalar::Int(int_ty)) => TypeCtor::Int(Uncertain::Known(IntTy { | ||
258 | signedness: Signedness::Signed, | ||
259 | bitness: bitness_from_chalk_int(int_ty), | ||
260 | })), | ||
261 | TypeName::Scalar(Scalar::Uint(uint_ty)) => TypeCtor::Int(Uncertain::Known(IntTy { | ||
262 | signedness: Signedness::Unsigned, | ||
263 | bitness: bitness_from_chalk_uint(uint_ty), | ||
264 | })), | ||
265 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F32)) => { | ||
266 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X32 })) | ||
267 | } | ||
268 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F64)) => { | ||
269 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X64 })) | ||
270 | } | ||
271 | TypeName::Tuple(cardinality) => TypeCtor::Tuple { cardinality: cardinality as u16 }, | ||
272 | TypeName::Raw(mutability) => TypeCtor::RawPtr(from_chalk(db, mutability)), | ||
273 | TypeName::Slice => TypeCtor::Slice, | ||
274 | TypeName::Ref(mutability) => TypeCtor::Ref(from_chalk(db, mutability)), | ||
275 | TypeName::Str => TypeCtor::Str, | ||
276 | |||
277 | TypeName::FnDef(fn_def_id) => { | ||
278 | let callable_def = from_chalk(db, fn_def_id); | ||
279 | TypeCtor::FnDef(callable_def) | ||
280 | } | ||
281 | |||
282 | TypeName::Error => { | ||
283 | // this should not be reached, since we don't represent TypeName::Error with TypeCtor | ||
284 | unreachable!() | ||
285 | } | ||
286 | } | ||
287 | } | ||
288 | } | ||
289 | |||
290 | fn bitness_from_chalk_uint(uint_ty: chalk_ir::UintTy) -> IntBitness { | ||
291 | use chalk_ir::UintTy; | ||
292 | |||
293 | match uint_ty { | ||
294 | UintTy::Usize => IntBitness::Xsize, | ||
295 | UintTy::U8 => IntBitness::X8, | ||
296 | UintTy::U16 => IntBitness::X16, | ||
297 | UintTy::U32 => IntBitness::X32, | ||
298 | UintTy::U64 => IntBitness::X64, | ||
299 | UintTy::U128 => IntBitness::X128, | ||
300 | } | ||
301 | } | ||
302 | |||
303 | fn bitness_from_chalk_int(int_ty: chalk_ir::IntTy) -> IntBitness { | ||
304 | use chalk_ir::IntTy; | ||
305 | |||
306 | match int_ty { | ||
307 | IntTy::Isize => IntBitness::Xsize, | ||
308 | IntTy::I8 => IntBitness::X8, | ||
309 | IntTy::I16 => IntBitness::X16, | ||
310 | IntTy::I32 => IntBitness::X32, | ||
311 | IntTy::I64 => IntBitness::X64, | ||
312 | IntTy::I128 => IntBitness::X128, | ||
313 | } | ||
314 | } | ||
315 | |||
316 | fn int_ty_to_chalk(int_ty: IntTy) -> Scalar { | ||
317 | use chalk_ir::{IntTy, UintTy}; | ||
318 | |||
319 | match int_ty.signedness { | ||
320 | Signedness::Signed => Scalar::Int(match int_ty.bitness { | ||
321 | IntBitness::Xsize => IntTy::Isize, | ||
322 | IntBitness::X8 => IntTy::I8, | ||
323 | IntBitness::X16 => IntTy::I16, | ||
324 | IntBitness::X32 => IntTy::I32, | ||
325 | IntBitness::X64 => IntTy::I64, | ||
326 | IntBitness::X128 => IntTy::I128, | ||
327 | }), | ||
328 | Signedness::Unsigned => Scalar::Uint(match int_ty.bitness { | ||
329 | IntBitness::Xsize => UintTy::Usize, | ||
330 | IntBitness::X8 => UintTy::U8, | ||
331 | IntBitness::X16 => UintTy::U16, | ||
332 | IntBitness::X32 => UintTy::U32, | ||
333 | IntBitness::X64 => UintTy::U64, | ||
334 | IntBitness::X128 => UintTy::U128, | ||
335 | }), | ||
336 | } | ||
337 | } | ||
338 | |||
339 | impl ToChalk for Mutability { | ||
340 | type Chalk = chalk_ir::Mutability; | ||
341 | fn to_chalk(self, _db: &dyn HirDatabase) -> Self::Chalk { | ||
342 | match self { | ||
343 | Mutability::Shared => chalk_ir::Mutability::Not, | ||
344 | Mutability::Mut => chalk_ir::Mutability::Mut, | ||
345 | } | ||
346 | } | ||
347 | fn from_chalk(_db: &dyn HirDatabase, chalk: Self::Chalk) -> Self { | ||
348 | match chalk { | ||
349 | chalk_ir::Mutability::Mut => Mutability::Mut, | ||
350 | chalk_ir::Mutability::Not => Mutability::Shared, | ||
351 | } | ||
352 | } | ||
353 | } | ||
354 | |||
355 | impl ToChalk for Impl { | ||
356 | type Chalk = ImplId; | ||
357 | |||
358 | fn to_chalk(self, db: &dyn HirDatabase) -> ImplId { | ||
359 | db.intern_chalk_impl(self).into() | ||
360 | } | ||
361 | |||
362 | fn from_chalk(db: &dyn HirDatabase, impl_id: ImplId) -> Impl { | ||
363 | db.lookup_intern_chalk_impl(impl_id.into()) | ||
364 | } | ||
365 | } | ||
366 | |||
367 | impl ToChalk for CallableDef { | ||
368 | type Chalk = FnDefId; | ||
369 | |||
370 | fn to_chalk(self, db: &dyn HirDatabase) -> FnDefId { | ||
371 | db.intern_callable_def(self).into() | ||
372 | } | ||
373 | |||
374 | fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDef { | ||
375 | db.lookup_intern_callable_def(fn_def_id.into()) | ||
376 | } | ||
377 | } | ||
378 | |||
379 | impl ToChalk for TypeAliasId { | ||
380 | type Chalk = AssocTypeId; | ||
381 | |||
382 | fn to_chalk(self, _db: &dyn HirDatabase) -> AssocTypeId { | ||
383 | chalk_ir::AssocTypeId(self.as_intern_id()) | ||
384 | } | ||
385 | |||
386 | fn from_chalk(_db: &dyn HirDatabase, type_alias_id: AssocTypeId) -> TypeAliasId { | ||
387 | InternKey::from_intern_id(type_alias_id.0) | ||
388 | } | ||
389 | } | ||
390 | |||
391 | impl ToChalk for AssocTyValue { | ||
392 | type Chalk = AssociatedTyValueId; | ||
393 | |||
394 | fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValueId { | ||
395 | db.intern_assoc_ty_value(self).into() | ||
396 | } | ||
397 | |||
398 | fn from_chalk(db: &dyn HirDatabase, assoc_ty_value_id: AssociatedTyValueId) -> AssocTyValue { | ||
399 | db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) | ||
400 | } | ||
401 | } | ||
402 | |||
403 | impl ToChalk for GenericPredicate { | ||
404 | type Chalk = chalk_ir::QuantifiedWhereClause<Interner>; | ||
405 | |||
406 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> { | ||
407 | match self { | ||
408 | GenericPredicate::Implemented(trait_ref) => { | ||
409 | let chalk_trait_ref = trait_ref.to_chalk(db); | ||
410 | let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner); | ||
411 | make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0) | ||
412 | } | ||
413 | GenericPredicate::Projection(projection_pred) => { | ||
414 | let ty = projection_pred.ty.to_chalk(db).shifted_in(&Interner); | ||
415 | let projection = projection_pred.projection_ty.to_chalk(db).shifted_in(&Interner); | ||
416 | let alias = chalk_ir::AliasTy::Projection(projection); | ||
417 | make_binders(chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), 0) | ||
418 | } | ||
419 | GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), | ||
420 | } | ||
421 | } | ||
422 | |||
423 | fn from_chalk( | ||
424 | db: &dyn HirDatabase, | ||
425 | where_clause: chalk_ir::QuantifiedWhereClause<Interner>, | ||
426 | ) -> GenericPredicate { | ||
427 | // we don't produce any where clauses with binders and can't currently deal with them | ||
428 | match where_clause | ||
429 | .skip_binders() | ||
430 | .shifted_out(&Interner) | ||
431 | .expect("unexpected bound vars in where clause") | ||
432 | { | ||
433 | chalk_ir::WhereClause::Implemented(tr) => { | ||
434 | GenericPredicate::Implemented(from_chalk(db, tr)) | ||
435 | } | ||
436 | chalk_ir::WhereClause::AliasEq(projection_eq) => { | ||
437 | let projection_ty = from_chalk( | ||
438 | db, | ||
439 | match projection_eq.alias { | ||
440 | chalk_ir::AliasTy::Projection(p) => p, | ||
441 | _ => unimplemented!(), | ||
442 | }, | ||
443 | ); | ||
444 | let ty = from_chalk(db, projection_eq.ty); | ||
445 | GenericPredicate::Projection(ProjectionPredicate { projection_ty, ty }) | ||
446 | } | ||
447 | } | ||
448 | } | ||
449 | } | ||
450 | |||
451 | impl ToChalk for ProjectionTy { | ||
452 | type Chalk = chalk_ir::ProjectionTy<Interner>; | ||
453 | |||
454 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::ProjectionTy<Interner> { | ||
455 | chalk_ir::ProjectionTy { | ||
456 | associated_ty_id: self.associated_ty.to_chalk(db), | ||
457 | substitution: self.parameters.to_chalk(db), | ||
458 | } | ||
459 | } | ||
460 | |||
461 | fn from_chalk( | ||
462 | db: &dyn HirDatabase, | ||
463 | projection_ty: chalk_ir::ProjectionTy<Interner>, | ||
464 | ) -> ProjectionTy { | ||
465 | ProjectionTy { | ||
466 | associated_ty: from_chalk(db, projection_ty.associated_ty_id), | ||
467 | parameters: from_chalk(db, projection_ty.substitution), | ||
468 | } | ||
469 | } | ||
470 | } | ||
471 | |||
472 | impl ToChalk for ProjectionPredicate { | ||
473 | type Chalk = chalk_ir::AliasEq<Interner>; | ||
474 | |||
475 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> { | ||
476 | chalk_ir::AliasEq { | ||
477 | alias: chalk_ir::AliasTy::Projection(self.projection_ty.to_chalk(db)), | ||
478 | ty: self.ty.to_chalk(db), | ||
479 | } | ||
480 | } | ||
481 | |||
482 | fn from_chalk(_db: &dyn HirDatabase, _normalize: chalk_ir::AliasEq<Interner>) -> Self { | ||
483 | unimplemented!() | ||
484 | } | ||
485 | } | ||
486 | |||
487 | impl ToChalk for Obligation { | ||
488 | type Chalk = chalk_ir::DomainGoal<Interner>; | ||
489 | |||
490 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> { | ||
491 | match self { | ||
492 | Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner), | ||
493 | Obligation::Projection(pr) => pr.to_chalk(db).cast(&Interner), | ||
494 | } | ||
495 | } | ||
496 | |||
497 | fn from_chalk(_db: &dyn HirDatabase, _goal: chalk_ir::DomainGoal<Interner>) -> Self { | ||
498 | unimplemented!() | ||
499 | } | ||
500 | } | ||
501 | |||
502 | impl<T> ToChalk for Canonical<T> | ||
503 | where | ||
504 | T: ToChalk, | ||
505 | T::Chalk: HasInterner<Interner = Interner>, | ||
506 | { | ||
507 | type Chalk = chalk_ir::Canonical<T::Chalk>; | ||
508 | |||
509 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { | ||
510 | let parameter = chalk_ir::CanonicalVarKind::new( | ||
511 | chalk_ir::VariableKind::Ty, | ||
512 | chalk_ir::UniverseIndex::ROOT, | ||
513 | ); | ||
514 | let value = self.value.to_chalk(db); | ||
515 | chalk_ir::Canonical { | ||
516 | value, | ||
517 | binders: chalk_ir::CanonicalVarKinds::from(&Interner, vec![parameter; self.num_vars]), | ||
518 | } | ||
519 | } | ||
520 | |||
521 | fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { | ||
522 | Canonical { | ||
523 | num_vars: canonical.binders.len(&Interner), | ||
524 | value: from_chalk(db, canonical.value), | ||
525 | } | ||
526 | } | ||
527 | } | ||
528 | |||
529 | impl ToChalk for Arc<TraitEnvironment> { | ||
530 | type Chalk = chalk_ir::Environment<Interner>; | ||
531 | |||
532 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Environment<Interner> { | ||
533 | let mut clauses = Vec::new(); | ||
534 | for pred in &self.predicates { | ||
535 | if pred.is_error() { | ||
536 | // for env, we just ignore errors | ||
537 | continue; | ||
538 | } | ||
539 | let program_clause: chalk_ir::ProgramClause<Interner> = | ||
540 | pred.clone().to_chalk(db).cast(&Interner); | ||
541 | clauses.push(program_clause.into_from_env_clause(&Interner)); | ||
542 | } | ||
543 | chalk_ir::Environment::new(&Interner).add_clauses(&Interner, clauses) | ||
544 | } | ||
545 | |||
546 | fn from_chalk( | ||
547 | _db: &dyn HirDatabase, | ||
548 | _env: chalk_ir::Environment<Interner>, | ||
549 | ) -> Arc<TraitEnvironment> { | ||
550 | unimplemented!() | ||
551 | } | ||
552 | } | ||
553 | |||
554 | impl<T: ToChalk> ToChalk for InEnvironment<T> | ||
555 | where | ||
556 | T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>, | ||
557 | { | ||
558 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; | ||
559 | |||
560 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { | ||
561 | chalk_ir::InEnvironment { | ||
562 | environment: self.environment.to_chalk(db), | ||
563 | goal: self.value.to_chalk(db), | ||
564 | } | ||
565 | } | ||
566 | |||
567 | fn from_chalk( | ||
568 | db: &dyn HirDatabase, | ||
569 | in_env: chalk_ir::InEnvironment<T::Chalk>, | ||
570 | ) -> InEnvironment<T> { | ||
571 | InEnvironment { | ||
572 | environment: from_chalk(db, in_env.environment), | ||
573 | value: from_chalk(db, in_env.goal), | ||
574 | } | ||
575 | } | ||
576 | } | ||
577 | |||
578 | impl ToChalk for builtin::BuiltinImplData { | ||
579 | type Chalk = ImplDatum; | ||
580 | |||
581 | fn to_chalk(self, db: &dyn HirDatabase) -> ImplDatum { | ||
582 | let impl_type = chalk_rust_ir::ImplType::External; | ||
583 | let where_clauses = self.where_clauses.into_iter().map(|w| w.to_chalk(db)).collect(); | ||
584 | |||
585 | let impl_datum_bound = | ||
586 | chalk_rust_ir::ImplDatumBound { trait_ref: self.trait_ref.to_chalk(db), where_clauses }; | ||
587 | let associated_ty_value_ids = | ||
588 | self.assoc_ty_values.into_iter().map(|v| v.to_chalk(db)).collect(); | ||
589 | chalk_rust_ir::ImplDatum { | ||
590 | binders: make_binders(impl_datum_bound, self.num_vars), | ||
591 | impl_type, | ||
592 | polarity: chalk_rust_ir::Polarity::Positive, | ||
593 | associated_ty_value_ids, | ||
594 | } | ||
595 | } | ||
596 | |||
597 | fn from_chalk(_db: &dyn HirDatabase, _data: ImplDatum) -> Self { | ||
598 | unimplemented!() | ||
599 | } | ||
600 | } | ||
601 | |||
602 | impl ToChalk for builtin::BuiltinImplAssocTyValueData { | ||
603 | type Chalk = AssociatedTyValue; | ||
604 | |||
605 | fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValue { | ||
606 | let ty = self.value.to_chalk(db); | ||
607 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty }; | ||
608 | |||
609 | chalk_rust_ir::AssociatedTyValue { | ||
610 | associated_ty_id: self.assoc_ty_id.to_chalk(db), | ||
611 | impl_id: self.impl_.to_chalk(db), | ||
612 | value: make_binders(value_bound, self.num_vars), | ||
613 | } | ||
614 | } | ||
615 | |||
616 | fn from_chalk( | ||
617 | _db: &dyn HirDatabase, | ||
618 | _data: AssociatedTyValue, | ||
619 | ) -> builtin::BuiltinImplAssocTyValueData { | ||
620 | unimplemented!() | ||
621 | } | ||
622 | } | ||
623 | |||
624 | pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> | ||
625 | where | ||
626 | T: HasInterner<Interner = Interner>, | ||
627 | { | ||
628 | chalk_ir::Binders::new( | ||
629 | chalk_ir::VariableKinds::from( | ||
630 | &Interner, | ||
631 | std::iter::repeat(chalk_ir::VariableKind::Ty).take(num_vars), | ||
632 | ), | ||
633 | value, | ||
634 | ) | ||
635 | } | ||
636 | |||
637 | pub(super) fn convert_where_clauses( | ||
638 | db: &dyn HirDatabase, | ||
639 | def: GenericDefId, | ||
640 | substs: &Substs, | ||
641 | ) -> Vec<chalk_ir::QuantifiedWhereClause<Interner>> { | ||
642 | let generic_predicates = db.generic_predicates(def); | ||
643 | let mut result = Vec::with_capacity(generic_predicates.len()); | ||
644 | for pred in generic_predicates.iter() { | ||
645 | if pred.value.is_error() { | ||
646 | // skip errored predicates completely | ||
647 | continue; | ||
648 | } | ||
649 | result.push(pred.clone().subst(substs).to_chalk(db)); | ||
650 | } | ||
651 | result | ||
652 | } | ||
653 | |||
654 | pub(super) fn generic_predicate_to_inline_bound( | ||
655 | db: &dyn HirDatabase, | ||
656 | pred: &GenericPredicate, | ||
657 | self_ty: &Ty, | ||
658 | ) -> Option<chalk_rust_ir::InlineBound<Interner>> { | ||
659 | // An InlineBound is like a GenericPredicate, except the self type is left out. | ||
660 | // We don't have a special type for this, but Chalk does. | ||
661 | match pred { | ||
662 | GenericPredicate::Implemented(trait_ref) => { | ||
663 | if &trait_ref.substs[0] != self_ty { | ||
664 | // we can only convert predicates back to type bounds if they | ||
665 | // have the expected self type | ||
666 | return None; | ||
667 | } | ||
668 | let args_no_self = trait_ref.substs[1..] | ||
669 | .iter() | ||
670 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | ||
671 | .collect(); | ||
672 | let trait_bound = | ||
673 | chalk_rust_ir::TraitBound { trait_id: trait_ref.trait_.to_chalk(db), args_no_self }; | ||
674 | Some(chalk_rust_ir::InlineBound::TraitBound(trait_bound)) | ||
675 | } | ||
676 | GenericPredicate::Projection(proj) => { | ||
677 | if &proj.projection_ty.parameters[0] != self_ty { | ||
678 | return None; | ||
679 | } | ||
680 | let trait_ = match proj.projection_ty.associated_ty.lookup(db.upcast()).container { | ||
681 | AssocContainerId::TraitId(t) => t, | ||
682 | _ => panic!("associated type not in trait"), | ||
683 | }; | ||
684 | let args_no_self = proj.projection_ty.parameters[1..] | ||
685 | .iter() | ||
686 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | ||
687 | .collect(); | ||
688 | let alias_eq_bound = chalk_rust_ir::AliasEqBound { | ||
689 | value: proj.ty.clone().to_chalk(db), | ||
690 | trait_bound: chalk_rust_ir::TraitBound { | ||
691 | trait_id: trait_.to_chalk(db), | ||
692 | args_no_self, | ||
693 | }, | ||
694 | associated_ty_id: proj.projection_ty.associated_ty.to_chalk(db), | ||
695 | parameters: Vec::new(), // FIXME we don't support generic associated types yet | ||
696 | }; | ||
697 | Some(chalk_rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) | ||
698 | } | ||
699 | GenericPredicate::Error => None, | ||
700 | } | ||
701 | } | ||
diff --git a/crates/ra_hir_ty/src/traits/chalk/tls.rs b/crates/ra_hir_ty/src/traits/chalk/tls.rs index 4867cb17e..d88828c7c 100644 --- a/crates/ra_hir_ty/src/traits/chalk/tls.rs +++ b/crates/ra_hir_ty/src/traits/chalk/tls.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! Implementation of Chalk debug helper functions using TLS. | 1 | //! Implementation of Chalk debug helper functions using TLS. |
2 | use std::fmt; | 2 | use std::fmt; |
3 | 3 | ||
4 | use chalk_ir::{AliasTy, Goal, Goals, Lifetime, Parameter, ProgramClauseImplication, TypeName}; | 4 | use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplication, TypeName}; |
5 | use itertools::Itertools; | 5 | use itertools::Itertools; |
6 | 6 | ||
7 | use super::{from_chalk, Interner}; | 7 | use super::{from_chalk, Interner}; |
@@ -15,10 +15,10 @@ pub struct DebugContext<'a>(&'a (dyn HirDatabase + 'a)); | |||
15 | impl DebugContext<'_> { | 15 | impl DebugContext<'_> { |
16 | pub fn debug_struct_id( | 16 | pub fn debug_struct_id( |
17 | &self, | 17 | &self, |
18 | id: super::StructId, | 18 | id: super::AdtId, |
19 | f: &mut fmt::Formatter<'_>, | 19 | f: &mut fmt::Formatter<'_>, |
20 | ) -> Result<(), fmt::Error> { | 20 | ) -> Result<(), fmt::Error> { |
21 | let type_ctor: TypeCtor = from_chalk(self.0, TypeName::Struct(id)); | 21 | let type_ctor: TypeCtor = from_chalk(self.0, TypeName::Adt(id)); |
22 | match type_ctor { | 22 | match type_ctor { |
23 | TypeCtor::Bool => write!(f, "bool")?, | 23 | TypeCtor::Bool => write!(f, "bool")?, |
24 | TypeCtor::Char => write!(f, "char")?, | 24 | TypeCtor::Char => write!(f, "char")?, |
@@ -188,9 +188,9 @@ impl DebugContext<'_> { | |||
188 | write!(fmt, "{:?}", lifetime.data(&Interner)) | 188 | write!(fmt, "{:?}", lifetime.data(&Interner)) |
189 | } | 189 | } |
190 | 190 | ||
191 | pub fn debug_parameter( | 191 | pub fn debug_generic_arg( |
192 | &self, | 192 | &self, |
193 | parameter: &Parameter<Interner>, | 193 | parameter: &GenericArg<Interner>, |
194 | fmt: &mut fmt::Formatter<'_>, | 194 | fmt: &mut fmt::Formatter<'_>, |
195 | ) -> Result<(), fmt::Error> { | 195 | ) -> Result<(), fmt::Error> { |
196 | write!(fmt, "{:?}", parameter.data(&Interner).inner_debug()) | 196 | write!(fmt, "{:?}", parameter.data(&Interner).inner_debug()) |
@@ -244,6 +244,79 @@ impl DebugContext<'_> { | |||
244 | ) -> Result<(), fmt::Error> { | 244 | ) -> Result<(), fmt::Error> { |
245 | write!(fmt, "{:?}", separator_trait_ref.debug(&Interner)) | 245 | write!(fmt, "{:?}", separator_trait_ref.debug(&Interner)) |
246 | } | 246 | } |
247 | |||
248 | pub fn debug_fn_def_id( | ||
249 | &self, | ||
250 | fn_def_id: chalk_ir::FnDefId<Interner>, | ||
251 | fmt: &mut fmt::Formatter<'_>, | ||
252 | ) -> Result<(), fmt::Error> { | ||
253 | let def: CallableDef = from_chalk(self.0, fn_def_id); | ||
254 | let name = match def { | ||
255 | CallableDef::FunctionId(ff) => self.0.function_data(ff).name.clone(), | ||
256 | CallableDef::StructId(s) => self.0.struct_data(s).name.clone(), | ||
257 | CallableDef::EnumVariantId(e) => { | ||
258 | let enum_data = self.0.enum_data(e.parent); | ||
259 | enum_data.variants[e.local_id].name.clone() | ||
260 | } | ||
261 | }; | ||
262 | match def { | ||
263 | CallableDef::FunctionId(_) => write!(fmt, "{{fn {}}}", name), | ||
264 | CallableDef::StructId(_) | CallableDef::EnumVariantId(_) => { | ||
265 | write!(fmt, "{{ctor {}}}", name) | ||
266 | } | ||
267 | } | ||
268 | } | ||
269 | |||
270 | pub fn debug_const( | ||
271 | &self, | ||
272 | _constant: &chalk_ir::Const<Interner>, | ||
273 | fmt: &mut fmt::Formatter<'_>, | ||
274 | ) -> fmt::Result { | ||
275 | write!(fmt, "const") | ||
276 | } | ||
277 | |||
278 | pub fn debug_variable_kinds( | ||
279 | &self, | ||
280 | variable_kinds: &chalk_ir::VariableKinds<Interner>, | ||
281 | fmt: &mut fmt::Formatter<'_>, | ||
282 | ) -> fmt::Result { | ||
283 | write!(fmt, "{:?}", variable_kinds.as_slice(&Interner)) | ||
284 | } | ||
285 | pub fn debug_variable_kinds_with_angles( | ||
286 | &self, | ||
287 | variable_kinds: &chalk_ir::VariableKinds<Interner>, | ||
288 | fmt: &mut fmt::Formatter<'_>, | ||
289 | ) -> fmt::Result { | ||
290 | write!(fmt, "{:?}", variable_kinds.inner_debug(&Interner)) | ||
291 | } | ||
292 | pub fn debug_canonical_var_kinds( | ||
293 | &self, | ||
294 | canonical_var_kinds: &chalk_ir::CanonicalVarKinds<Interner>, | ||
295 | fmt: &mut fmt::Formatter<'_>, | ||
296 | ) -> fmt::Result { | ||
297 | write!(fmt, "{:?}", canonical_var_kinds.as_slice(&Interner)) | ||
298 | } | ||
299 | pub fn debug_program_clause( | ||
300 | &self, | ||
301 | clause: &chalk_ir::ProgramClause<Interner>, | ||
302 | fmt: &mut fmt::Formatter<'_>, | ||
303 | ) -> fmt::Result { | ||
304 | write!(fmt, "{:?}", clause.data(&Interner)) | ||
305 | } | ||
306 | pub fn debug_program_clauses( | ||
307 | &self, | ||
308 | clauses: &chalk_ir::ProgramClauses<Interner>, | ||
309 | fmt: &mut fmt::Formatter<'_>, | ||
310 | ) -> fmt::Result { | ||
311 | write!(fmt, "{:?}", clauses.as_slice(&Interner)) | ||
312 | } | ||
313 | pub fn debug_quantified_where_clauses( | ||
314 | &self, | ||
315 | clauses: &chalk_ir::QuantifiedWhereClauses<Interner>, | ||
316 | fmt: &mut fmt::Formatter<'_>, | ||
317 | ) -> fmt::Result { | ||
318 | write!(fmt, "{:?}", clauses.as_slice(&Interner)) | ||
319 | } | ||
247 | } | 320 | } |
248 | 321 | ||
249 | mod unsafe_tls { | 322 | mod unsafe_tls { |