diff options
-rw-r--r-- | crates/hir/src/lib.rs | 19 | ||||
-rw-r--r-- | crates/hir_ty/src/db.rs | 11 | ||||
-rw-r--r-- | crates/hir_ty/src/display.rs | 40 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 5 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 15 | ||||
-rw-r--r-- | crates/hir_ty/src/lib.rs | 78 | ||||
-rw-r--r-- | crates/hir_ty/src/lower.rs | 53 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk.rs | 10 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk/mapping.rs | 92 | ||||
-rw-r--r-- | crates/hir_ty/src/utils.rs | 2 | ||||
-rw-r--r-- | docs/user/manual.adoc | 6 |
11 files changed, 215 insertions, 116 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index e3ac37e4c..a325b6691 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -57,8 +57,8 @@ use hir_ty::{ | |||
57 | to_assoc_type_id, | 57 | to_assoc_type_id, |
58 | traits::{FnTrait, Solution, SolutionVariables}, | 58 | traits::{FnTrait, Solution, SolutionVariables}, |
59 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, Cast, DebruijnIndex, | 59 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, Cast, DebruijnIndex, |
60 | InEnvironment, Interner, ProjectionTy, Scalar, Substitution, Ty, TyDefId, TyKind, | 60 | InEnvironment, Interner, ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, Ty, |
61 | TyVariableKind, WhereClause, | 61 | TyDefId, TyKind, TyVariableKind, WhereClause, |
62 | }; | 62 | }; |
63 | use itertools::Itertools; | 63 | use itertools::Itertools; |
64 | use rustc_hash::FxHashSet; | 64 | use rustc_hash::FxHashSet; |
@@ -1460,7 +1460,7 @@ impl TypeParam { | |||
1460 | pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> { | 1460 | pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> { |
1461 | db.generic_predicates_for_param(self.id) | 1461 | db.generic_predicates_for_param(self.id) |
1462 | .into_iter() | 1462 | .into_iter() |
1463 | .filter_map(|pred| match &pred.value { | 1463 | .filter_map(|pred| match &pred.skip_binders().skip_binders() { |
1464 | hir_ty::WhereClause::Implemented(trait_ref) => { | 1464 | hir_ty::WhereClause::Implemented(trait_ref) => { |
1465 | Some(Trait::from(trait_ref.hir_trait_id())) | 1465 | Some(Trait::from(trait_ref.hir_trait_id())) |
1466 | } | 1466 | } |
@@ -2022,7 +2022,7 @@ impl Type { | |||
2022 | pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> { | 2022 | pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> { |
2023 | self.ty.value.impl_trait_bounds(db).map(|it| { | 2023 | self.ty.value.impl_trait_bounds(db).map(|it| { |
2024 | it.into_iter() | 2024 | it.into_iter() |
2025 | .filter_map(|pred| match pred { | 2025 | .filter_map(|pred| match pred.skip_binders() { |
2026 | hir_ty::WhereClause::Implemented(trait_ref) => { | 2026 | hir_ty::WhereClause::Implemented(trait_ref) => { |
2027 | Some(Trait::from(trait_ref.hir_trait_id())) | 2027 | Some(Trait::from(trait_ref.hir_trait_id())) |
2028 | } | 2028 | } |
@@ -2061,11 +2061,11 @@ impl Type { | |||
2061 | fn walk_bounds( | 2061 | fn walk_bounds( |
2062 | db: &dyn HirDatabase, | 2062 | db: &dyn HirDatabase, |
2063 | type_: &Type, | 2063 | type_: &Type, |
2064 | bounds: &[WhereClause], | 2064 | bounds: &[QuantifiedWhereClause], |
2065 | cb: &mut impl FnMut(Type), | 2065 | cb: &mut impl FnMut(Type), |
2066 | ) { | 2066 | ) { |
2067 | for pred in bounds { | 2067 | for pred in bounds { |
2068 | match pred { | 2068 | match pred.skip_binders() { |
2069 | WhereClause::Implemented(trait_ref) => { | 2069 | WhereClause::Implemented(trait_ref) => { |
2070 | cb(type_.clone()); | 2070 | cb(type_.clone()); |
2071 | // skip the self type. it's likely the type we just got the bounds from | 2071 | // skip the self type. it's likely the type we just got the bounds from |
@@ -2107,7 +2107,12 @@ impl Type { | |||
2107 | } | 2107 | } |
2108 | } | 2108 | } |
2109 | TyKind::Dyn(bounds) => { | 2109 | TyKind::Dyn(bounds) => { |
2110 | walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); | 2110 | walk_bounds( |
2111 | db, | ||
2112 | &type_.derived(ty.clone()), | ||
2113 | bounds.bounds.skip_binders().interned(), | ||
2114 | cb, | ||
2115 | ); | ||
2111 | } | 2116 | } |
2112 | 2117 | ||
2113 | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) | TyKind::Array(ty) | TyKind::Slice(ty) => { | 2118 | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) | TyKind::Array(ty) | TyKind::Slice(ty) => { |
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index 91a2e0b5b..58e4247c6 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs | |||
@@ -12,8 +12,8 @@ use la_arena::ArenaMap; | |||
12 | use crate::{ | 12 | use crate::{ |
13 | method_resolution::{InherentImpls, TraitImpls}, | 13 | method_resolution::{InherentImpls, TraitImpls}, |
14 | traits::chalk, | 14 | traits::chalk, |
15 | Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig, ReturnTypeImplTraits, | 15 | Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig, |
16 | TraitRef, Ty, TyDefId, ValueTyDefId, WhereClause, | 16 | QuantifiedWhereClause, ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId, |
17 | }; | 17 | }; |
18 | use hir_expand::name::Name; | 18 | use hir_expand::name::Name; |
19 | 19 | ||
@@ -57,10 +57,13 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
57 | 57 | ||
58 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] | 58 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] |
59 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] | 59 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] |
60 | fn generic_predicates_for_param(&self, param_id: TypeParamId) -> Arc<[Binders<WhereClause>]>; | 60 | fn generic_predicates_for_param( |
61 | &self, | ||
62 | param_id: TypeParamId, | ||
63 | ) -> Arc<[Binders<QuantifiedWhereClause>]>; | ||
61 | 64 | ||
62 | #[salsa::invoke(crate::lower::generic_predicates_query)] | 65 | #[salsa::invoke(crate::lower::generic_predicates_query)] |
63 | fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<WhereClause>]>; | 66 | fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<QuantifiedWhereClause>]>; |
64 | 67 | ||
65 | #[salsa::invoke(crate::lower::trait_environment_query)] | 68 | #[salsa::invoke(crate::lower::trait_environment_query)] |
66 | fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>; | 69 | fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>; |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 9d3b79be3..cc6b93d37 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use std::{borrow::Cow, fmt}; | 3 | use std::fmt; |
4 | 4 | ||
5 | use arrayvec::ArrayVec; | 5 | use arrayvec::ArrayVec; |
6 | use chalk_ir::Mutability; | 6 | use chalk_ir::Mutability; |
@@ -20,7 +20,7 @@ use crate::{ | |||
20 | db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, | 20 | db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, |
21 | to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, | 21 | to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, |
22 | CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy, | 22 | CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy, |
23 | ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, | 23 | ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | pub struct HirFormatter<'a> { | 26 | pub struct HirFormatter<'a> { |
@@ -328,9 +328,9 @@ impl HirDisplay for Ty { | |||
328 | 328 | ||
329 | // FIXME: all this just to decide whether to use parentheses... | 329 | // FIXME: all this just to decide whether to use parentheses... |
330 | let datas; | 330 | let datas; |
331 | let predicates = match t.interned(&Interner) { | 331 | let predicates: Vec<_> = match t.interned(&Interner) { |
332 | TyKind::Dyn(predicates) if predicates.len() > 1 => { | 332 | TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => { |
333 | Cow::Borrowed(predicates.as_ref()) | 333 | dyn_ty.bounds.skip_binders().interned().iter().cloned().collect() |
334 | } | 334 | } |
335 | &TyKind::Alias(AliasTy::Opaque(OpaqueTy { | 335 | &TyKind::Alias(AliasTy::Opaque(OpaqueTy { |
336 | opaque_ty_id, | 336 | opaque_ty_id, |
@@ -345,17 +345,21 @@ impl HirDisplay for Ty { | |||
345 | .as_ref() | 345 | .as_ref() |
346 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | 346 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); |
347 | let bounds = data.subst(parameters); | 347 | let bounds = data.subst(parameters); |
348 | Cow::Owned(bounds.value) | 348 | bounds.value |
349 | } else { | 349 | } else { |
350 | Cow::Borrowed(&[][..]) | 350 | Vec::new() |
351 | } | 351 | } |
352 | } | 352 | } |
353 | _ => Cow::Borrowed(&[][..]), | 353 | _ => Vec::new(), |
354 | }; | 354 | }; |
355 | 355 | ||
356 | if let [WhereClause::Implemented(trait_ref), _] = predicates.as_ref() { | 356 | if let Some(WhereClause::Implemented(trait_ref)) = |
357 | predicates.get(0).map(|b| b.skip_binders()) | ||
358 | { | ||
357 | let trait_ = trait_ref.hir_trait_id(); | 359 | let trait_ = trait_ref.hir_trait_id(); |
358 | if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) { | 360 | if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) |
361 | && predicates.len() <= 2 | ||
362 | { | ||
359 | return write!(f, "{}", ty_display); | 363 | return write!(f, "{}", ty_display); |
360 | } | 364 | } |
361 | } | 365 | } |
@@ -577,7 +581,7 @@ impl HirDisplay for Ty { | |||
577 | .generic_predicates(id.parent) | 581 | .generic_predicates(id.parent) |
578 | .into_iter() | 582 | .into_iter() |
579 | .map(|pred| pred.clone().subst(&substs)) | 583 | .map(|pred| pred.clone().subst(&substs)) |
580 | .filter(|wc| match &wc { | 584 | .filter(|wc| match &wc.skip_binders() { |
581 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, | 585 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, |
582 | WhereClause::AliasEq(AliasEq { | 586 | WhereClause::AliasEq(AliasEq { |
583 | alias: AliasTy::Projection(proj), | 587 | alias: AliasTy::Projection(proj), |
@@ -591,8 +595,12 @@ impl HirDisplay for Ty { | |||
591 | } | 595 | } |
592 | } | 596 | } |
593 | TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, | 597 | TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, |
594 | TyKind::Dyn(predicates) => { | 598 | TyKind::Dyn(dyn_ty) => { |
595 | write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; | 599 | write_bounds_like_dyn_trait_with_prefix( |
600 | "dyn", | ||
601 | dyn_ty.bounds.skip_binders().interned(), | ||
602 | f, | ||
603 | )?; | ||
596 | } | 604 | } |
597 | TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, | 605 | TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, |
598 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { | 606 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { |
@@ -661,7 +669,7 @@ fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = Trai | |||
661 | 669 | ||
662 | pub fn write_bounds_like_dyn_trait_with_prefix( | 670 | pub fn write_bounds_like_dyn_trait_with_prefix( |
663 | prefix: &str, | 671 | prefix: &str, |
664 | predicates: &[WhereClause], | 672 | predicates: &[QuantifiedWhereClause], |
665 | f: &mut HirFormatter, | 673 | f: &mut HirFormatter, |
666 | ) -> Result<(), HirDisplayError> { | 674 | ) -> Result<(), HirDisplayError> { |
667 | write!(f, "{}", prefix)?; | 675 | write!(f, "{}", prefix)?; |
@@ -674,7 +682,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix( | |||
674 | } | 682 | } |
675 | 683 | ||
676 | fn write_bounds_like_dyn_trait( | 684 | fn write_bounds_like_dyn_trait( |
677 | predicates: &[WhereClause], | 685 | predicates: &[QuantifiedWhereClause], |
678 | f: &mut HirFormatter, | 686 | f: &mut HirFormatter, |
679 | ) -> Result<(), HirDisplayError> { | 687 | ) -> Result<(), HirDisplayError> { |
680 | // Note: This code is written to produce nice results (i.e. | 688 | // Note: This code is written to produce nice results (i.e. |
@@ -687,7 +695,7 @@ fn write_bounds_like_dyn_trait( | |||
687 | let mut angle_open = false; | 695 | let mut angle_open = false; |
688 | let mut is_fn_trait = false; | 696 | let mut is_fn_trait = false; |
689 | for p in predicates.iter() { | 697 | for p in predicates.iter() { |
690 | match p { | 698 | match p.skip_binders() { |
691 | WhereClause::Implemented(trait_ref) => { | 699 | WhereClause::Implemented(trait_ref) => { |
692 | let trait_ = trait_ref.hir_trait_id(); | 700 | let trait_ = trait_ref.hir_trait_id(); |
693 | if !is_fn_trait { | 701 | if !is_fn_trait { |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 24deff707..05cbde4e3 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -11,6 +11,7 @@ use hir_def::{ | |||
11 | AssocContainerId, FieldId, Lookup, | 11 | AssocContainerId, FieldId, Lookup, |
12 | }; | 12 | }; |
13 | use hir_expand::name::{name, Name}; | 13 | use hir_expand::name::{name, Name}; |
14 | use stdx::always; | ||
14 | use syntax::ast::RangeOp; | 15 | use syntax::ast::RangeOp; |
15 | 16 | ||
16 | use crate::{ | 17 | use crate::{ |
@@ -936,7 +937,9 @@ impl<'a> InferenceContext<'a> { | |||
936 | let def: CallableDefId = from_chalk(self.db, *fn_def); | 937 | let def: CallableDefId = from_chalk(self.db, *fn_def); |
937 | let generic_predicates = self.db.generic_predicates(def.into()); | 938 | let generic_predicates = self.db.generic_predicates(def.into()); |
938 | for predicate in generic_predicates.iter() { | 939 | for predicate in generic_predicates.iter() { |
939 | let predicate = predicate.clone().subst(parameters); | 940 | let (predicate, binders) = |
941 | predicate.clone().subst(parameters).into_value_and_skipped_binders(); | ||
942 | always!(binders == 0); // quantified where clauses not yet handled | ||
940 | self.obligations.push(predicate.cast(&Interner)); | 943 | self.obligations.push(predicate.cast(&Interner)); |
941 | } | 944 | } |
942 | // add obligation for trait implementation, if this is a trait method | 945 | // add obligation for trait implementation, if this is a trait method |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 1fc03c8f4..35b0a2059 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -310,9 +310,18 @@ impl InferenceTable { | |||
310 | 310 | ||
311 | (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, | 311 | (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, |
312 | 312 | ||
313 | (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) if dyn1.len() == dyn2.len() => { | 313 | (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) |
314 | for (pred1, pred2) in dyn1.iter().zip(dyn2.iter()) { | 314 | if dyn1.bounds.skip_binders().interned().len() |
315 | if !self.unify_preds(pred1, pred2, depth + 1) { | 315 | == dyn2.bounds.skip_binders().interned().len() => |
316 | { | ||
317 | for (pred1, pred2) in dyn1 | ||
318 | .bounds | ||
319 | .skip_binders() | ||
320 | .interned() | ||
321 | .iter() | ||
322 | .zip(dyn2.bounds.skip_binders().interned().iter()) | ||
323 | { | ||
324 | if !self.unify_preds(pred1.skip_binders(), pred2.skip_binders(), depth + 1) { | ||
316 | return false; | 325 | return false; |
317 | } | 326 | } |
318 | } | 327 | } |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index ad908f957..90b5b17e2 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -132,6 +132,12 @@ impl TypeWalk for ProjectionTy { | |||
132 | } | 132 | } |
133 | } | 133 | } |
134 | 134 | ||
135 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
136 | pub struct DynTy { | ||
137 | /// The unknown self type. | ||
138 | pub bounds: Binders<QuantifiedWhereClauses>, | ||
139 | } | ||
140 | |||
135 | pub type FnSig = chalk_ir::FnSig<Interner>; | 141 | pub type FnSig = chalk_ir::FnSig<Interner>; |
136 | 142 | ||
137 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 143 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
@@ -283,7 +289,7 @@ pub enum TyKind { | |||
283 | /// represents the `Self` type inside the bounds. This is currently | 289 | /// represents the `Self` type inside the bounds. This is currently |
284 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it | 290 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it |
285 | /// didn't seem worth the overhead yet. | 291 | /// didn't seem worth the overhead yet. |
286 | Dyn(Arc<[WhereClause]>), | 292 | Dyn(DynTy), |
287 | 293 | ||
288 | /// A placeholder for a type which could not be computed; this is propagated | 294 | /// A placeholder for a type which could not be computed; this is propagated |
289 | /// to avoid useless error messages. Doubles as a placeholder where type | 295 | /// to avoid useless error messages. Doubles as a placeholder where type |
@@ -490,6 +496,13 @@ impl<T> Binders<T> { | |||
490 | Self { num_binders, value } | 496 | Self { num_binders, value } |
491 | } | 497 | } |
492 | 498 | ||
499 | pub fn wrap_empty(value: T) -> Self | ||
500 | where | ||
501 | T: TypeWalk, | ||
502 | { | ||
503 | Self { num_binders: 0, value: value.shift_bound_vars(DebruijnIndex::ONE) } | ||
504 | } | ||
505 | |||
493 | pub fn as_ref(&self) -> Binders<&T> { | 506 | pub fn as_ref(&self) -> Binders<&T> { |
494 | Binders { num_binders: self.num_binders, value: &self.value } | 507 | Binders { num_binders: self.num_binders, value: &self.value } |
495 | } | 508 | } |
@@ -501,6 +514,14 @@ impl<T> Binders<T> { | |||
501 | pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> { | 514 | pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> { |
502 | Some(Binders { num_binders: self.num_binders, value: f(self.value)? }) | 515 | Some(Binders { num_binders: self.num_binders, value: f(self.value)? }) |
503 | } | 516 | } |
517 | |||
518 | pub fn skip_binders(&self) -> &T { | ||
519 | &self.value | ||
520 | } | ||
521 | |||
522 | pub fn into_value_and_skipped_binders(self) -> (T, usize) { | ||
523 | (self.value, self.num_binders) | ||
524 | } | ||
504 | } | 525 | } |
505 | 526 | ||
506 | impl<T: Clone> Binders<&T> { | 527 | impl<T: Clone> Binders<&T> { |
@@ -614,6 +635,24 @@ impl TypeWalk for WhereClause { | |||
614 | } | 635 | } |
615 | } | 636 | } |
616 | 637 | ||
638 | pub type QuantifiedWhereClause = Binders<WhereClause>; | ||
639 | |||
640 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
641 | pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>); | ||
642 | |||
643 | impl QuantifiedWhereClauses { | ||
644 | pub fn from_iter( | ||
645 | _interner: &Interner, | ||
646 | elements: impl IntoIterator<Item = QuantifiedWhereClause>, | ||
647 | ) -> Self { | ||
648 | QuantifiedWhereClauses(elements.into_iter().collect()) | ||
649 | } | ||
650 | |||
651 | pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> { | ||
652 | &self.0 | ||
653 | } | ||
654 | } | ||
655 | |||
617 | /// Basically a claim (currently not validated / checked) that the contained | 656 | /// Basically a claim (currently not validated / checked) that the contained |
618 | /// type / trait ref contains no inference variables; any inference variables it | 657 | /// type / trait ref contains no inference variables; any inference variables it |
619 | /// contained have been replaced by bound variables, and `kinds` tells us how | 658 | /// contained have been replaced by bound variables, and `kinds` tells us how |
@@ -810,12 +849,14 @@ impl Ty { | |||
810 | } | 849 | } |
811 | 850 | ||
812 | /// If this is a `dyn Trait` type, this returns the `Trait` part. | 851 | /// If this is a `dyn Trait` type, this returns the `Trait` part. |
813 | pub fn dyn_trait_ref(&self) -> Option<&TraitRef> { | 852 | fn dyn_trait_ref(&self) -> Option<&TraitRef> { |
814 | match self.interned(&Interner) { | 853 | match self.interned(&Interner) { |
815 | TyKind::Dyn(bounds) => bounds.get(0).and_then(|b| match b { | 854 | TyKind::Dyn(dyn_ty) => { |
816 | WhereClause::Implemented(trait_ref) => Some(trait_ref), | 855 | dyn_ty.bounds.value.interned().get(0).and_then(|b| match b.skip_binders() { |
817 | _ => None, | 856 | WhereClause::Implemented(trait_ref) => Some(trait_ref), |
818 | }), | 857 | _ => None, |
858 | }) | ||
859 | } | ||
819 | _ => None, | 860 | _ => None, |
820 | } | 861 | } |
821 | } | 862 | } |
@@ -892,7 +933,7 @@ impl Ty { | |||
892 | } | 933 | } |
893 | } | 934 | } |
894 | 935 | ||
895 | pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<WhereClause>> { | 936 | pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> { |
896 | match self.interned(&Interner) { | 937 | match self.interned(&Interner) { |
897 | TyKind::OpaqueType(opaque_ty_id, ..) => { | 938 | TyKind::OpaqueType(opaque_ty_id, ..) => { |
898 | match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { | 939 | match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { |
@@ -905,10 +946,13 @@ impl Ty { | |||
905 | // This is only used by type walking. | 946 | // This is only used by type walking. |
906 | // Parameters will be walked outside, and projection predicate is not used. | 947 | // Parameters will be walked outside, and projection predicate is not used. |
907 | // So just provide the Future trait. | 948 | // So just provide the Future trait. |
908 | let impl_bound = WhereClause::Implemented(TraitRef { | 949 | let impl_bound = Binders::new( |
909 | trait_id: to_chalk_trait_id(future_trait), | 950 | 0, |
910 | substitution: Substitution::empty(), | 951 | WhereClause::Implemented(TraitRef { |
911 | }); | 952 | trait_id: to_chalk_trait_id(future_trait), |
953 | substitution: Substitution::empty(), | ||
954 | }), | ||
955 | ); | ||
912 | Some(vec![impl_bound]) | 956 | Some(vec![impl_bound]) |
913 | } else { | 957 | } else { |
914 | None | 958 | None |
@@ -945,7 +989,7 @@ impl Ty { | |||
945 | .generic_predicates(id.parent) | 989 | .generic_predicates(id.parent) |
946 | .into_iter() | 990 | .into_iter() |
947 | .map(|pred| pred.clone().subst(&substs)) | 991 | .map(|pred| pred.clone().subst(&substs)) |
948 | .filter(|wc| match &wc { | 992 | .filter(|wc| match &wc.skip_binders() { |
949 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, | 993 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, |
950 | WhereClause::AliasEq(AliasEq { | 994 | WhereClause::AliasEq(AliasEq { |
951 | alias: AliasTy::Projection(proj), | 995 | alias: AliasTy::Projection(proj), |
@@ -1094,8 +1138,8 @@ impl TypeWalk for Ty { | |||
1094 | t.walk(f); | 1138 | t.walk(f); |
1095 | } | 1139 | } |
1096 | } | 1140 | } |
1097 | TyKind::Dyn(predicates) => { | 1141 | TyKind::Dyn(dyn_ty) => { |
1098 | for p in predicates.iter() { | 1142 | for p in dyn_ty.bounds.value.interned().iter() { |
1099 | p.walk(f); | 1143 | p.walk(f); |
1100 | } | 1144 | } |
1101 | } | 1145 | } |
@@ -1122,8 +1166,8 @@ impl TypeWalk for Ty { | |||
1122 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | 1166 | TyKind::Alias(AliasTy::Projection(p_ty)) => { |
1123 | p_ty.substitution.walk_mut_binders(f, binders); | 1167 | p_ty.substitution.walk_mut_binders(f, binders); |
1124 | } | 1168 | } |
1125 | TyKind::Dyn(predicates) => { | 1169 | TyKind::Dyn(dyn_ty) => { |
1126 | for p in make_mut_slice(predicates) { | 1170 | for p in make_mut_slice(&mut dyn_ty.bounds.value.0) { |
1127 | p.walk_mut_binders(f, binders.shifted_in()); | 1171 | p.walk_mut_binders(f, binders.shifted_in()); |
1128 | } | 1172 | } |
1129 | } | 1173 | } |
@@ -1173,7 +1217,7 @@ pub struct ReturnTypeImplTraits { | |||
1173 | 1217 | ||
1174 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 1218 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
1175 | pub(crate) struct ReturnTypeImplTrait { | 1219 | pub(crate) struct ReturnTypeImplTrait { |
1176 | pub(crate) bounds: Binders<Vec<WhereClause>>, | 1220 | pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>, |
1177 | } | 1221 | } |
1178 | 1222 | ||
1179 | pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { | 1223 | pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index fd451a823..f60cec649 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -33,9 +33,10 @@ use crate::{ | |||
33 | all_super_trait_refs, associated_type_by_name_including_super_traits, generics, | 33 | all_super_trait_refs, associated_type_by_name_including_super_traits, generics, |
34 | variant_data, | 34 | variant_data, |
35 | }, | 35 | }, |
36 | AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, ImplTraitId, | 36 | AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, |
37 | OpaqueTy, PolyFnSig, ProjectionTy, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, | 37 | ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, |
38 | TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk, WhereClause, | 38 | ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, |
39 | TyKind, TypeWalk, WhereClause, | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | #[derive(Debug)] | 42 | #[derive(Debug)] |
@@ -188,13 +189,14 @@ impl<'a> TyLoweringContext<'a> { | |||
188 | TypeRef::DynTrait(bounds) => { | 189 | TypeRef::DynTrait(bounds) => { |
189 | let self_ty = | 190 | let self_ty = |
190 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); | 191 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); |
191 | let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { | 192 | let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { |
192 | bounds | 193 | QuantifiedWhereClauses::from_iter( |
193 | .iter() | 194 | &Interner, |
194 | .flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)) | 195 | bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)), |
195 | .collect() | 196 | ) |
196 | }); | 197 | }); |
197 | TyKind::Dyn(predicates).intern(&Interner) | 198 | let bounds = Binders::new(1, bounds); |
199 | TyKind::Dyn(DynTy { bounds }).intern(&Interner) | ||
198 | } | 200 | } |
199 | TypeRef::ImplTrait(bounds) => { | 201 | TypeRef::ImplTrait(bounds) => { |
200 | match self.impl_trait_mode { | 202 | match self.impl_trait_mode { |
@@ -376,7 +378,16 @@ impl<'a> TyLoweringContext<'a> { | |||
376 | // FIXME report error (ambiguous associated type) | 378 | // FIXME report error (ambiguous associated type) |
377 | TyKind::Unknown.intern(&Interner) | 379 | TyKind::Unknown.intern(&Interner) |
378 | } else { | 380 | } else { |
379 | TyKind::Dyn(Arc::new([WhereClause::Implemented(trait_ref)])).intern(&Interner) | 381 | let dyn_ty = DynTy { |
382 | bounds: Binders::new( | ||
383 | 1, | ||
384 | QuantifiedWhereClauses::from_iter( | ||
385 | &Interner, | ||
386 | Some(Binders::wrap_empty(WhereClause::Implemented(trait_ref))), | ||
387 | ), | ||
388 | ), | ||
389 | }; | ||
390 | TyKind::Dyn(dyn_ty).intern(&Interner) | ||
380 | }; | 391 | }; |
381 | return (ty, None); | 392 | return (ty, None); |
382 | } | 393 | } |
@@ -670,7 +681,7 @@ impl<'a> TyLoweringContext<'a> { | |||
670 | &'a self, | 681 | &'a self, |
671 | where_predicate: &'a WherePredicate, | 682 | where_predicate: &'a WherePredicate, |
672 | ignore_bindings: bool, | 683 | ignore_bindings: bool, |
673 | ) -> impl Iterator<Item = WhereClause> + 'a { | 684 | ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a { |
674 | match where_predicate { | 685 | match where_predicate { |
675 | WherePredicate::ForLifetime { target, bound, .. } | 686 | WherePredicate::ForLifetime { target, bound, .. } |
676 | | WherePredicate::TypeBound { target, bound } => { | 687 | | WherePredicate::TypeBound { target, bound } => { |
@@ -705,12 +716,12 @@ impl<'a> TyLoweringContext<'a> { | |||
705 | bound: &'a TypeBound, | 716 | bound: &'a TypeBound, |
706 | self_ty: Ty, | 717 | self_ty: Ty, |
707 | ignore_bindings: bool, | 718 | ignore_bindings: bool, |
708 | ) -> impl Iterator<Item = WhereClause> + 'a { | 719 | ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a { |
709 | let mut bindings = None; | 720 | let mut bindings = None; |
710 | let trait_ref = match bound { | 721 | let trait_ref = match bound { |
711 | TypeBound::Path(path) => { | 722 | TypeBound::Path(path) => { |
712 | bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); | 723 | bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); |
713 | bindings.clone().map(WhereClause::Implemented) | 724 | bindings.clone().map(WhereClause::Implemented).map(|b| Binders::wrap_empty(b)) |
714 | } | 725 | } |
715 | TypeBound::Lifetime(_) => None, | 726 | TypeBound::Lifetime(_) => None, |
716 | TypeBound::Error => None, | 727 | TypeBound::Error => None, |
@@ -727,7 +738,7 @@ impl<'a> TyLoweringContext<'a> { | |||
727 | &'a self, | 738 | &'a self, |
728 | bound: &'a TypeBound, | 739 | bound: &'a TypeBound, |
729 | trait_ref: TraitRef, | 740 | trait_ref: TraitRef, |
730 | ) -> impl Iterator<Item = WhereClause> + 'a { | 741 | ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a { |
731 | let last_segment = match bound { | 742 | let last_segment = match bound { |
732 | TypeBound::Path(path) => path.segments().last(), | 743 | TypeBound::Path(path) => path.segments().last(), |
733 | TypeBound::Error | TypeBound::Lifetime(_) => None, | 744 | TypeBound::Error | TypeBound::Lifetime(_) => None, |
@@ -743,7 +754,7 @@ impl<'a> TyLoweringContext<'a> { | |||
743 | &binding.name, | 754 | &binding.name, |
744 | ); | 755 | ); |
745 | let (super_trait_ref, associated_ty) = match found { | 756 | let (super_trait_ref, associated_ty) = match found { |
746 | None => return SmallVec::<[WhereClause; 1]>::new(), | 757 | None => return SmallVec::<[QuantifiedWhereClause; 1]>::new(), |
747 | Some(t) => t, | 758 | Some(t) => t, |
748 | }; | 759 | }; |
749 | let projection_ty = ProjectionTy { | 760 | let projection_ty = ProjectionTy { |
@@ -757,7 +768,7 @@ impl<'a> TyLoweringContext<'a> { | |||
757 | let ty = self.lower_ty(type_ref); | 768 | let ty = self.lower_ty(type_ref); |
758 | let alias_eq = | 769 | let alias_eq = |
759 | AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; | 770 | AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; |
760 | preds.push(WhereClause::AliasEq(alias_eq)); | 771 | preds.push(Binders::wrap_empty(WhereClause::AliasEq(alias_eq))); |
761 | } | 772 | } |
762 | for bound in &binding.bounds { | 773 | for bound in &binding.bounds { |
763 | preds.extend(self.lower_type_bound( | 774 | preds.extend(self.lower_type_bound( |
@@ -814,7 +825,7 @@ pub fn associated_type_shorthand_candidates<R>( | |||
814 | let predicates = db.generic_predicates_for_param(param_id); | 825 | let predicates = db.generic_predicates_for_param(param_id); |
815 | let mut traits_: Vec<_> = predicates | 826 | let mut traits_: Vec<_> = predicates |
816 | .iter() | 827 | .iter() |
817 | .filter_map(|pred| match &pred.value { | 828 | .filter_map(|pred| match &pred.value.value { |
818 | WhereClause::Implemented(tr) => Some(tr.clone()), | 829 | WhereClause::Implemented(tr) => Some(tr.clone()), |
819 | _ => None, | 830 | _ => None, |
820 | }) | 831 | }) |
@@ -887,7 +898,7 @@ pub(crate) fn field_types_query( | |||
887 | pub(crate) fn generic_predicates_for_param_query( | 898 | pub(crate) fn generic_predicates_for_param_query( |
888 | db: &dyn HirDatabase, | 899 | db: &dyn HirDatabase, |
889 | param_id: TypeParamId, | 900 | param_id: TypeParamId, |
890 | ) -> Arc<[Binders<WhereClause>]> { | 901 | ) -> Arc<[Binders<QuantifiedWhereClause>]> { |
891 | let resolver = param_id.parent.resolver(db.upcast()); | 902 | let resolver = param_id.parent.resolver(db.upcast()); |
892 | let ctx = | 903 | let ctx = |
893 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | 904 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
@@ -915,7 +926,7 @@ pub(crate) fn generic_predicates_for_param_recover( | |||
915 | _db: &dyn HirDatabase, | 926 | _db: &dyn HirDatabase, |
916 | _cycle: &[String], | 927 | _cycle: &[String], |
917 | _param_id: &TypeParamId, | 928 | _param_id: &TypeParamId, |
918 | ) -> Arc<[Binders<WhereClause>]> { | 929 | ) -> Arc<[Binders<QuantifiedWhereClause>]> { |
919 | Arc::new([]) | 930 | Arc::new([]) |
920 | } | 931 | } |
921 | 932 | ||
@@ -930,7 +941,7 @@ pub(crate) fn trait_environment_query( | |||
930 | let mut clauses = Vec::new(); | 941 | let mut clauses = Vec::new(); |
931 | for pred in resolver.where_predicates_in_scope() { | 942 | for pred in resolver.where_predicates_in_scope() { |
932 | for pred in ctx.lower_where_predicate(pred, false) { | 943 | for pred in ctx.lower_where_predicate(pred, false) { |
933 | if let WhereClause::Implemented(tr) = &pred { | 944 | if let WhereClause::Implemented(tr) = &pred.skip_binders() { |
934 | traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id())); | 945 | traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id())); |
935 | } | 946 | } |
936 | let program_clause: chalk_ir::ProgramClause<Interner> = | 947 | let program_clause: chalk_ir::ProgramClause<Interner> = |
@@ -970,7 +981,7 @@ pub(crate) fn trait_environment_query( | |||
970 | pub(crate) fn generic_predicates_query( | 981 | pub(crate) fn generic_predicates_query( |
971 | db: &dyn HirDatabase, | 982 | db: &dyn HirDatabase, |
972 | def: GenericDefId, | 983 | def: GenericDefId, |
973 | ) -> Arc<[Binders<WhereClause>]> { | 984 | ) -> Arc<[Binders<QuantifiedWhereClause>]> { |
974 | let resolver = def.resolver(db.upcast()); | 985 | let resolver = def.resolver(db.upcast()); |
975 | let ctx = | 986 | let ctx = |
976 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | 987 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 944145603..4019fdf17 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs | |||
@@ -238,7 +238,10 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
238 | }); | 238 | }); |
239 | let bound = OpaqueTyDatumBound { | 239 | let bound = OpaqueTyDatumBound { |
240 | bounds: make_binders( | 240 | bounds: make_binders( |
241 | vec![impl_bound.to_chalk(self.db), proj_bound.to_chalk(self.db)], | 241 | vec![ |
242 | wrap_in_empty_binders(impl_bound).to_chalk(self.db), | ||
243 | wrap_in_empty_binders(proj_bound).to_chalk(self.db), | ||
244 | ], | ||
242 | 1, | 245 | 1, |
243 | ), | 246 | ), |
244 | where_clauses: make_binders(vec![], 0), | 247 | where_clauses: make_binders(vec![], 0), |
@@ -397,7 +400,6 @@ pub(crate) fn associated_ty_data_query( | |||
397 | .iter() | 400 | .iter() |
398 | .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false)) | 401 | .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false)) |
399 | .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) | 402 | .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) |
400 | .map(|bound| make_binders(bound.shifted_in(&Interner), 0)) | ||
401 | .collect(); | 403 | .collect(); |
402 | 404 | ||
403 | let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); | 405 | let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); |
@@ -720,3 +722,7 @@ impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> { | |||
720 | chalk_ir::ClosureId(id.as_intern_id()) | 722 | chalk_ir::ClosureId(id.as_intern_id()) |
721 | } | 723 | } |
722 | } | 724 | } |
725 | |||
726 | fn wrap_in_empty_binders<T: crate::TypeWalk>(value: T) -> crate::Binders<T> { | ||
727 | crate::Binders::wrap_empty(value) | ||
728 | } | ||
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 65feb82e5..7209dd14e 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs | |||
@@ -7,15 +7,14 @@ use chalk_ir::{cast::Cast, fold::shift::Shift, interner::HasInterner, LifetimeDa | |||
7 | use chalk_solve::rust_ir; | 7 | use chalk_solve::rust_ir; |
8 | 8 | ||
9 | use base_db::salsa::InternKey; | 9 | use base_db::salsa::InternKey; |
10 | use hir_def::{AssocContainerId, GenericDefId, Lookup, TypeAliasId}; | 10 | use hir_def::{GenericDefId, TypeAliasId}; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | db::HirDatabase, | 13 | db::HirDatabase, |
14 | from_assoc_type_id, | ||
15 | primitive::UintTy, | 14 | primitive::UintTy, |
16 | traits::{Canonical, DomainGoal}, | 15 | traits::{Canonical, DomainGoal}, |
17 | AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, Scalar, Substitution, | 16 | AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, |
18 | TraitRef, Ty, WhereClause, | 17 | QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TypeWalk, WhereClause, |
19 | }; | 18 | }; |
20 | 19 | ||
21 | use super::interner::*; | 20 | use super::interner::*; |
@@ -95,10 +94,10 @@ impl ToChalk for Ty { | |||
95 | TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner), | 94 | TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner), |
96 | TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), | 95 | TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), |
97 | TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"), | 96 | TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"), |
98 | TyKind::Dyn(predicates) => { | 97 | TyKind::Dyn(dyn_ty) => { |
99 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( | 98 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( |
100 | &Interner, | 99 | &Interner, |
101 | predicates.iter().cloned().map(|p| p.to_chalk(db)), | 100 | dyn_ty.bounds.value.interned().iter().cloned().map(|p| p.to_chalk(db)), |
102 | ); | 101 | ); |
103 | let bounded_ty = chalk_ir::DynTy { | 102 | let bounded_ty = chalk_ir::DynTy { |
104 | bounds: make_binders(where_clauses, 1), | 103 | bounds: make_binders(where_clauses, 1), |
@@ -144,13 +143,17 @@ impl ToChalk for Ty { | |||
144 | chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Unknown, | 143 | chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Unknown, |
145 | chalk_ir::TyKind::Dyn(where_clauses) => { | 144 | chalk_ir::TyKind::Dyn(where_clauses) => { |
146 | assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); | 145 | assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); |
147 | let predicates = where_clauses | 146 | let bounds = where_clauses |
148 | .bounds | 147 | .bounds |
149 | .skip_binders() | 148 | .skip_binders() |
150 | .iter(&Interner) | 149 | .iter(&Interner) |
151 | .map(|c| from_chalk(db, c.clone())) | 150 | .map(|c| from_chalk(db, c.clone())); |
152 | .collect(); | 151 | TyKind::Dyn(crate::DynTy { |
153 | TyKind::Dyn(predicates) | 152 | bounds: crate::Binders::new( |
153 | 1, | ||
154 | crate::QuantifiedWhereClauses::from_iter(&Interner, bounds), | ||
155 | ), | ||
156 | }) | ||
154 | } | 157 | } |
155 | 158 | ||
156 | chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)), | 159 | chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)), |
@@ -305,33 +308,22 @@ impl ToChalk for TypeAliasAsValue { | |||
305 | } | 308 | } |
306 | 309 | ||
307 | impl ToChalk for WhereClause { | 310 | impl ToChalk for WhereClause { |
308 | type Chalk = chalk_ir::QuantifiedWhereClause<Interner>; | 311 | type Chalk = chalk_ir::WhereClause<Interner>; |
309 | 312 | ||
310 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> { | 313 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::WhereClause<Interner> { |
311 | match self { | 314 | match self { |
312 | WhereClause::Implemented(trait_ref) => { | 315 | WhereClause::Implemented(trait_ref) => { |
313 | let chalk_trait_ref = trait_ref.to_chalk(db); | 316 | chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)) |
314 | let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner); | ||
315 | make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0) | ||
316 | } | 317 | } |
317 | WhereClause::AliasEq(alias_eq) => make_binders( | 318 | WhereClause::AliasEq(alias_eq) => chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db)), |
318 | chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db).shifted_in(&Interner)), | ||
319 | 0, | ||
320 | ), | ||
321 | } | 319 | } |
322 | } | 320 | } |
323 | 321 | ||
324 | fn from_chalk( | 322 | fn from_chalk( |
325 | db: &dyn HirDatabase, | 323 | db: &dyn HirDatabase, |
326 | where_clause: chalk_ir::QuantifiedWhereClause<Interner>, | 324 | where_clause: chalk_ir::WhereClause<Interner>, |
327 | ) -> WhereClause { | 325 | ) -> WhereClause { |
328 | // we don't produce any where clauses with binders and can't currently deal with them | 326 | match where_clause { |
329 | match where_clause | ||
330 | .skip_binders() | ||
331 | .clone() | ||
332 | .shifted_out(&Interner) | ||
333 | .expect("unexpected bound vars in where clause") | ||
334 | { | ||
335 | chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)), | 327 | chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)), |
336 | chalk_ir::WhereClause::AliasEq(alias_eq) => { | 328 | chalk_ir::WhereClause::AliasEq(alias_eq) => { |
337 | WhereClause::AliasEq(from_chalk(db, alias_eq)) | 329 | WhereClause::AliasEq(from_chalk(db, alias_eq)) |
@@ -500,6 +492,29 @@ where | |||
500 | } | 492 | } |
501 | } | 493 | } |
502 | 494 | ||
495 | impl<T: ToChalk> ToChalk for crate::Binders<T> | ||
496 | where | ||
497 | T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>, | ||
498 | { | ||
499 | type Chalk = chalk_ir::Binders<T::Chalk>; | ||
500 | |||
501 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Binders<T::Chalk> { | ||
502 | chalk_ir::Binders::new( | ||
503 | chalk_ir::VariableKinds::from_iter( | ||
504 | &Interner, | ||
505 | std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)) | ||
506 | .take(self.num_binders), | ||
507 | ), | ||
508 | self.value.to_chalk(db), | ||
509 | ) | ||
510 | } | ||
511 | |||
512 | fn from_chalk(db: &dyn HirDatabase, binders: chalk_ir::Binders<T::Chalk>) -> crate::Binders<T> { | ||
513 | let (v, b) = binders.into_value_and_skipped_binders(); | ||
514 | crate::Binders::new(b.len(&Interner), from_chalk(db, v)) | ||
515 | } | ||
516 | } | ||
517 | |||
503 | pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> | 518 | pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> |
504 | where | 519 | where |
505 | T: HasInterner<Interner = Interner>, | 520 | T: HasInterner<Interner = Interner>, |
@@ -529,14 +544,15 @@ pub(super) fn convert_where_clauses( | |||
529 | 544 | ||
530 | pub(super) fn generic_predicate_to_inline_bound( | 545 | pub(super) fn generic_predicate_to_inline_bound( |
531 | db: &dyn HirDatabase, | 546 | db: &dyn HirDatabase, |
532 | pred: &WhereClause, | 547 | pred: &QuantifiedWhereClause, |
533 | self_ty: &Ty, | 548 | self_ty: &Ty, |
534 | ) -> Option<rust_ir::InlineBound<Interner>> { | 549 | ) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> { |
535 | // An InlineBound is like a GenericPredicate, except the self type is left out. | 550 | // An InlineBound is like a GenericPredicate, except the self type is left out. |
536 | // We don't have a special type for this, but Chalk does. | 551 | // We don't have a special type for this, but Chalk does. |
537 | match pred { | 552 | let self_ty_shifted_in = self_ty.clone().shift_bound_vars(DebruijnIndex::ONE); |
553 | match &pred.value { | ||
538 | WhereClause::Implemented(trait_ref) => { | 554 | WhereClause::Implemented(trait_ref) => { |
539 | if &trait_ref.substitution[0] != self_ty { | 555 | if trait_ref.self_type_parameter() != &self_ty_shifted_in { |
540 | // we can only convert predicates back to type bounds if they | 556 | // we can only convert predicates back to type bounds if they |
541 | // have the expected self type | 557 | // have the expected self type |
542 | return None; | 558 | return None; |
@@ -546,19 +562,13 @@ pub(super) fn generic_predicate_to_inline_bound( | |||
546 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | 562 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) |
547 | .collect(); | 563 | .collect(); |
548 | let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; | 564 | let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; |
549 | Some(rust_ir::InlineBound::TraitBound(trait_bound)) | 565 | Some(make_binders(rust_ir::InlineBound::TraitBound(trait_bound), pred.num_binders)) |
550 | } | 566 | } |
551 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { | 567 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { |
552 | if &projection_ty.substitution[0] != self_ty { | 568 | if projection_ty.self_type_parameter() != &self_ty_shifted_in { |
553 | return None; | 569 | return None; |
554 | } | 570 | } |
555 | let trait_ = match from_assoc_type_id(projection_ty.associated_ty_id) | 571 | let trait_ = projection_ty.trait_(db); |
556 | .lookup(db.upcast()) | ||
557 | .container | ||
558 | { | ||
559 | AssocContainerId::TraitId(t) => t, | ||
560 | _ => panic!("associated type not in trait"), | ||
561 | }; | ||
562 | let args_no_self = projection_ty.substitution[1..] | 572 | let args_no_self = projection_ty.substitution[1..] |
563 | .iter() | 573 | .iter() |
564 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | 574 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) |
@@ -569,7 +579,7 @@ pub(super) fn generic_predicate_to_inline_bound( | |||
569 | associated_ty_id: projection_ty.associated_ty_id, | 579 | associated_ty_id: projection_ty.associated_ty_id, |
570 | parameters: Vec::new(), // FIXME we don't support generic associated types yet | 580 | parameters: Vec::new(), // FIXME we don't support generic associated types yet |
571 | }; | 581 | }; |
572 | Some(rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) | 582 | Some(make_binders(rust_ir::InlineBound::AliasEqBound(alias_eq_bound), pred.num_binders)) |
573 | } | 583 | } |
574 | _ => None, | 584 | _ => None, |
575 | } | 585 | } |
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs index 1ec1ecd43..19874e42b 100644 --- a/crates/hir_ty/src/utils.rs +++ b/crates/hir_ty/src/utils.rs | |||
@@ -63,7 +63,7 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr | |||
63 | db.generic_predicates_for_param(trait_self) | 63 | db.generic_predicates_for_param(trait_self) |
64 | .iter() | 64 | .iter() |
65 | .filter_map(|pred| { | 65 | .filter_map(|pred| { |
66 | pred.as_ref().filter_map(|pred| match pred { | 66 | pred.as_ref().filter_map(|pred| match pred.skip_binders() { |
67 | WhereClause::Implemented(tr) => Some(tr.clone()), | 67 | WhereClause::Implemented(tr) => Some(tr.clone()), |
68 | _ => None, | 68 | _ => None, |
69 | }) | 69 | }) |
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc index 9305d9d1a..8656dd1da 100644 --- a/docs/user/manual.adoc +++ b/docs/user/manual.adoc | |||
@@ -519,7 +519,7 @@ You can set `RA_LOG` environmental variable to `rust_analyzer=info` to inspect h | |||
519 | == Security | 519 | == Security |
520 | 520 | ||
521 | At the moment, rust-analyzer assumes that all code is trusted. | 521 | At the moment, rust-analyzer assumes that all code is trusted. |
522 | Here is a **no-exhaustive** list of ways to make rust-analyzer execute arbitrary code: | 522 | Here is a **non-exhaustive** list of ways to make rust-analyzer execute arbitrary code: |
523 | 523 | ||
524 | * proc macros and build scripts are executed by default | 524 | * proc macros and build scripts are executed by default |
525 | * `.cargo/config` can override `rustc` with an arbitrary executable | 525 | * `.cargo/config` can override `rustc` with an arbitrary executable |
@@ -527,8 +527,8 @@ Here is a **no-exhaustive** list of ways to make rust-analyzer execute arbitrary | |||
527 | * rust-analyzer's syntax trees library uses a lot of `unsafe` and hasn't been properly audited for memory safety. | 527 | * rust-analyzer's syntax trees library uses a lot of `unsafe` and hasn't been properly audited for memory safety. |
528 | 528 | ||
529 | rust-analyzer itself doesn't access the network. | 529 | rust-analyzer itself doesn't access the network. |
530 | VS Code plugin doesn't access the network unless the nightly channel is selected in the settings. | 530 | The VS Code plugin doesn't access the network unless the nightly channel is selected in the settings. |
531 | In that case, the plugin uses GitHub API to check for and download updates. | 531 | In that case, the plugin uses the GitHub API to check for and download updates. |
532 | 532 | ||
533 | == Features | 533 | == Features |
534 | 534 | ||