diff options
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r-- | crates/ra_hir_ty/src/traits.rs | 18 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 108 |
2 files changed, 68 insertions, 58 deletions
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs index 4aabd66dc..ac0588193 100644 --- a/crates/ra_hir_ty/src/traits.rs +++ b/crates/ra_hir_ty/src/traits.rs | |||
@@ -50,10 +50,19 @@ impl TraitSolver { | |||
50 | Err(_) => ra_db::Canceled::throw(), | 50 | Err(_) => ra_db::Canceled::throw(), |
51 | }; | 51 | }; |
52 | 52 | ||
53 | let fuel = std::cell::Cell::new(CHALK_SOLVER_FUEL); | ||
54 | |||
53 | let solution = panic::catch_unwind({ | 55 | let solution = panic::catch_unwind({ |
54 | let solver = panic::AssertUnwindSafe(&mut solver); | 56 | let solver = panic::AssertUnwindSafe(&mut solver); |
55 | let context = panic::AssertUnwindSafe(&context); | 57 | let context = panic::AssertUnwindSafe(&context); |
56 | move || solver.0.solve(context.0, goal) | 58 | move || { |
59 | solver.0.solve_limited(context.0, goal, || { | ||
60 | context.0.db.check_canceled(); | ||
61 | let remaining = fuel.get(); | ||
62 | fuel.set(remaining - 1); | ||
63 | remaining > 0 | ||
64 | }) | ||
65 | } | ||
57 | }); | 66 | }); |
58 | 67 | ||
59 | let solution = match solution { | 68 | let solution = match solution { |
@@ -79,6 +88,9 @@ impl TraitSolver { | |||
79 | /// high, we can run into slow edge cases; if we set it too low, Chalk won't | 88 | /// high, we can run into slow edge cases; if we set it too low, Chalk won't |
80 | /// find some solutions. | 89 | /// find some solutions. |
81 | const CHALK_SOLVER_MAX_SIZE: usize = 4; | 90 | const CHALK_SOLVER_MAX_SIZE: usize = 4; |
91 | /// This controls how much 'time' we give the Chalk solver before giving up. | ||
92 | const CHALK_SOLVER_FUEL: i32 = 100; | ||
93 | // TODO: tune both these values | ||
82 | 94 | ||
83 | #[derive(Debug, Copy, Clone)] | 95 | #[derive(Debug, Copy, Clone)] |
84 | struct ChalkContext<'a, DB> { | 96 | struct ChalkContext<'a, DB> { |
@@ -97,7 +109,8 @@ pub(crate) fn trait_solver_query( | |||
97 | } | 109 | } |
98 | 110 | ||
99 | fn create_chalk_solver() -> chalk_solve::Solver<TypeFamily> { | 111 | fn create_chalk_solver() -> chalk_solve::Solver<TypeFamily> { |
100 | let solver_choice = chalk_solve::SolverChoice::SLG { max_size: CHALK_SOLVER_MAX_SIZE }; | 112 | let solver_choice = |
113 | chalk_solve::SolverChoice::SLG { max_size: CHALK_SOLVER_MAX_SIZE, expected_answers: None }; | ||
101 | solver_choice.into_solver() | 114 | solver_choice.into_solver() |
102 | } | 115 | } |
103 | 116 | ||
@@ -232,7 +245,6 @@ fn solution_from_chalk( | |||
232 | let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<TypeFamily>>| { | 245 | let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<TypeFamily>>| { |
233 | let value = subst | 246 | let value = subst |
234 | .value | 247 | .value |
235 | .parameters | ||
236 | .into_iter() | 248 | .into_iter() |
237 | .map(|p| { | 249 | .map(|p| { |
238 | let ty = match p.ty() { | 250 | let ty = match p.ty() { |
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 555930c9b..fe9cb556c 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -3,7 +3,7 @@ use std::{fmt, sync::Arc}; | |||
3 | 3 | ||
4 | use log::debug; | 4 | use log::debug; |
5 | 5 | ||
6 | use chalk_ir::{cast::Cast, Parameter, PlaceholderIndex, TypeName, UniverseIndex}; | 6 | use chalk_ir::{cast::Cast, GoalData, Parameter, PlaceholderIndex, TypeName, UniverseIndex}; |
7 | 7 | ||
8 | use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId}; | 8 | use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId}; |
9 | use ra_db::{ | 9 | use ra_db::{ |
@@ -24,6 +24,8 @@ impl chalk_ir::family::TypeFamily for TypeFamily { | |||
24 | type InternedType = Box<chalk_ir::TyData<Self>>; | 24 | type InternedType = Box<chalk_ir::TyData<Self>>; |
25 | type InternedLifetime = chalk_ir::LifetimeData<Self>; | 25 | type InternedLifetime = chalk_ir::LifetimeData<Self>; |
26 | type InternedParameter = chalk_ir::ParameterData<Self>; | 26 | type InternedParameter = chalk_ir::ParameterData<Self>; |
27 | type InternedGoal = Arc<GoalData<Self>>; | ||
28 | type InternedSubstitution = Vec<Parameter<Self>>; | ||
27 | type DefId = InternId; | 29 | type DefId = InternId; |
28 | 30 | ||
29 | // FIXME: implement these | 31 | // FIXME: implement these |
@@ -48,8 +50,8 @@ impl chalk_ir::family::TypeFamily for TypeFamily { | |||
48 | None | 50 | None |
49 | } | 51 | } |
50 | 52 | ||
51 | fn debug_projection( | 53 | fn debug_alias( |
52 | _projection: &chalk_ir::ProjectionTy<Self>, | 54 | _projection: &chalk_ir::AliasTy<Self>, |
53 | _fmt: &mut fmt::Formatter<'_>, | 55 | _fmt: &mut fmt::Formatter<'_>, |
54 | ) -> Option<fmt::Result> { | 56 | ) -> Option<fmt::Result> { |
55 | None | 57 | None |
@@ -78,6 +80,24 @@ impl chalk_ir::family::TypeFamily for TypeFamily { | |||
78 | fn parameter_data(parameter: &chalk_ir::ParameterData<Self>) -> &chalk_ir::ParameterData<Self> { | 80 | fn parameter_data(parameter: &chalk_ir::ParameterData<Self>) -> &chalk_ir::ParameterData<Self> { |
79 | parameter | 81 | parameter |
80 | } | 82 | } |
83 | |||
84 | fn intern_goal(goal: GoalData<Self>) -> Arc<GoalData<Self>> { | ||
85 | Arc::new(goal) | ||
86 | } | ||
87 | |||
88 | fn goal_data(goal: &Arc<GoalData<Self>>) -> &GoalData<Self> { | ||
89 | goal | ||
90 | } | ||
91 | |||
92 | fn intern_substitution<E>( | ||
93 | data: impl IntoIterator<Item = Result<Parameter<Self>, E>>, | ||
94 | ) -> Result<Vec<Parameter<Self>>, E> { | ||
95 | data.into_iter().collect() | ||
96 | } | ||
97 | |||
98 | fn substitution_data(substitution: &Vec<Parameter<Self>>) -> &[Parameter<Self>] { | ||
99 | substitution | ||
100 | } | ||
81 | } | 101 | } |
82 | 102 | ||
83 | impl chalk_ir::family::HasTypeFamily for TypeFamily { | 103 | impl chalk_ir::family::HasTypeFamily for TypeFamily { |
@@ -114,13 +134,13 @@ impl ToChalk for Ty { | |||
114 | match self { | 134 | match self { |
115 | Ty::Apply(apply_ty) => { | 135 | Ty::Apply(apply_ty) => { |
116 | let name = apply_ty.ctor.to_chalk(db); | 136 | let name = apply_ty.ctor.to_chalk(db); |
117 | let parameters = apply_ty.parameters.to_chalk(db); | 137 | let substitution = apply_ty.parameters.to_chalk(db); |
118 | chalk_ir::ApplicationTy { name, parameters }.cast().intern() | 138 | chalk_ir::ApplicationTy { name, substitution }.cast().intern() |
119 | } | 139 | } |
120 | Ty::Projection(proj_ty) => { | 140 | Ty::Projection(proj_ty) => { |
121 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); | 141 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); |
122 | let parameters = proj_ty.parameters.to_chalk(db); | 142 | let substitution = proj_ty.parameters.to_chalk(db); |
123 | chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast().intern() | 143 | chalk_ir::AliasTy { associated_ty_id, substitution }.cast().intern() |
124 | } | 144 | } |
125 | Ty::Param { idx, .. } => { | 145 | Ty::Param { idx, .. } => { |
126 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize } | 146 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize } |
@@ -135,23 +155,13 @@ impl ToChalk for Ty { | |||
135 | .cloned() | 155 | .cloned() |
136 | .map(|p| p.to_chalk(db)) | 156 | .map(|p| p.to_chalk(db)) |
137 | .collect(); | 157 | .collect(); |
138 | let bounded_ty = chalk_ir::BoundedTy { bounds: make_binders(where_clauses, 1) }; | 158 | let bounded_ty = chalk_ir::DynTy { bounds: make_binders(where_clauses, 1) }; |
139 | chalk_ir::TyData::Dyn(bounded_ty).intern() | 159 | chalk_ir::TyData::Dyn(bounded_ty).intern() |
140 | } | 160 | } |
141 | Ty::Opaque(predicates) => { | 161 | Ty::Opaque(_) | Ty::Unknown => { |
142 | let where_clauses = predicates | 162 | let substitution = chalk_ir::Substitution::empty(); |
143 | .iter() | ||
144 | .filter(|p| !p.is_error()) | ||
145 | .cloned() | ||
146 | .map(|p| p.to_chalk(db)) | ||
147 | .collect(); | ||
148 | let bounded_ty = chalk_ir::BoundedTy { bounds: make_binders(where_clauses, 1) }; | ||
149 | chalk_ir::TyData::Opaque(bounded_ty).intern() | ||
150 | } | ||
151 | Ty::Unknown => { | ||
152 | let parameters = Vec::new(); | ||
153 | let name = TypeName::Error; | 163 | let name = TypeName::Error; |
154 | chalk_ir::ApplicationTy { name, parameters }.cast().intern() | 164 | chalk_ir::ApplicationTy { name, substitution }.cast().intern() |
155 | } | 165 | } |
156 | } | 166 | } |
157 | } | 167 | } |
@@ -161,7 +171,7 @@ impl ToChalk for Ty { | |||
161 | TypeName::Error => Ty::Unknown, | 171 | TypeName::Error => Ty::Unknown, |
162 | _ => { | 172 | _ => { |
163 | let ctor = from_chalk(db, apply_ty.name); | 173 | let ctor = from_chalk(db, apply_ty.name); |
164 | let parameters = from_chalk(db, apply_ty.parameters); | 174 | let parameters = from_chalk(db, apply_ty.substitution); |
165 | Ty::Apply(ApplicationTy { ctor, parameters }) | 175 | Ty::Apply(ApplicationTy { ctor, parameters }) |
166 | } | 176 | } |
167 | }, | 177 | }, |
@@ -169,12 +179,12 @@ impl ToChalk for Ty { | |||
169 | assert_eq!(idx.ui, UniverseIndex::ROOT); | 179 | assert_eq!(idx.ui, UniverseIndex::ROOT); |
170 | Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } | 180 | Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } |
171 | } | 181 | } |
172 | chalk_ir::TyData::Projection(proj) => { | 182 | chalk_ir::TyData::Alias(proj) => { |
173 | let associated_ty = from_chalk(db, proj.associated_ty_id); | 183 | let associated_ty = from_chalk(db, proj.associated_ty_id); |
174 | let parameters = from_chalk(db, proj.parameters); | 184 | let parameters = from_chalk(db, proj.substitution); |
175 | Ty::Projection(ProjectionTy { associated_ty, parameters }) | 185 | Ty::Projection(ProjectionTy { associated_ty, parameters }) |
176 | } | 186 | } |
177 | chalk_ir::TyData::ForAll(_) => unimplemented!(), | 187 | chalk_ir::TyData::Function(_) => unimplemented!(), |
178 | chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32), | 188 | chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32), |
179 | chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, | 189 | chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, |
180 | chalk_ir::TyData::Dyn(where_clauses) => { | 190 | chalk_ir::TyData::Dyn(where_clauses) => { |
@@ -183,27 +193,18 @@ impl ToChalk for Ty { | |||
183 | where_clauses.bounds.value.into_iter().map(|c| from_chalk(db, c)).collect(); | 193 | where_clauses.bounds.value.into_iter().map(|c| from_chalk(db, c)).collect(); |
184 | Ty::Dyn(predicates) | 194 | Ty::Dyn(predicates) |
185 | } | 195 | } |
186 | chalk_ir::TyData::Opaque(where_clauses) => { | ||
187 | assert_eq!(where_clauses.bounds.binders.len(), 1); | ||
188 | let predicates = | ||
189 | where_clauses.bounds.value.into_iter().map(|c| from_chalk(db, c)).collect(); | ||
190 | Ty::Opaque(predicates) | ||
191 | } | ||
192 | } | 196 | } |
193 | } | 197 | } |
194 | } | 198 | } |
195 | 199 | ||
196 | impl ToChalk for Substs { | 200 | impl ToChalk for Substs { |
197 | type Chalk = Vec<chalk_ir::Parameter<TypeFamily>>; | 201 | type Chalk = chalk_ir::Substitution<TypeFamily>; |
198 | 202 | ||
199 | fn to_chalk(self, db: &impl HirDatabase) -> Vec<Parameter<TypeFamily>> { | 203 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Substitution<TypeFamily> { |
200 | self.iter().map(|ty| ty.clone().to_chalk(db).cast()).collect() | 204 | chalk_ir::Substitution::from(self.iter().map(|ty| ty.clone().to_chalk(db))) |
201 | } | 205 | } |
202 | 206 | ||
203 | fn from_chalk( | 207 | fn from_chalk(db: &impl HirDatabase, parameters: chalk_ir::Substitution<TypeFamily>) -> Substs { |
204 | db: &impl HirDatabase, | ||
205 | parameters: Vec<chalk_ir::Parameter<TypeFamily>>, | ||
206 | ) -> Substs { | ||
207 | let tys = parameters | 208 | let tys = parameters |
208 | .into_iter() | 209 | .into_iter() |
209 | .map(|p| match p.ty() { | 210 | .map(|p| match p.ty() { |
@@ -220,13 +221,13 @@ impl ToChalk for TraitRef { | |||
220 | 221 | ||
221 | fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef<TypeFamily> { | 222 | fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef<TypeFamily> { |
222 | let trait_id = self.trait_.to_chalk(db); | 223 | let trait_id = self.trait_.to_chalk(db); |
223 | let parameters = self.substs.to_chalk(db); | 224 | let substitution = self.substs.to_chalk(db); |
224 | chalk_ir::TraitRef { trait_id, parameters } | 225 | chalk_ir::TraitRef { trait_id, substitution } |
225 | } | 226 | } |
226 | 227 | ||
227 | fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef<TypeFamily>) -> Self { | 228 | fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef<TypeFamily>) -> Self { |
228 | let trait_ = from_chalk(db, trait_ref.trait_id); | 229 | let trait_ = from_chalk(db, trait_ref.trait_id); |
229 | let substs = from_chalk(db, trait_ref.parameters); | 230 | let substs = from_chalk(db, trait_ref.substitution); |
230 | TraitRef { trait_, substs } | 231 | TraitRef { trait_, substs } |
231 | } | 232 | } |
232 | } | 233 | } |
@@ -317,8 +318,8 @@ impl ToChalk for GenericPredicate { | |||
317 | make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) | 318 | make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) |
318 | } | 319 | } |
319 | GenericPredicate::Projection(projection_pred) => make_binders( | 320 | GenericPredicate::Projection(projection_pred) => make_binders( |
320 | chalk_ir::WhereClause::ProjectionEq(chalk_ir::ProjectionEq { | 321 | chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { |
321 | projection: projection_pred.projection_ty.to_chalk(db), | 322 | alias: projection_pred.projection_ty.to_chalk(db), |
322 | ty: projection_pred.ty.to_chalk(db), | 323 | ty: projection_pred.ty.to_chalk(db), |
323 | }), | 324 | }), |
324 | 0, | 325 | 0, |
@@ -335,8 +336,8 @@ impl ToChalk for GenericPredicate { | |||
335 | chalk_ir::WhereClause::Implemented(tr) => { | 336 | chalk_ir::WhereClause::Implemented(tr) => { |
336 | GenericPredicate::Implemented(from_chalk(db, tr)) | 337 | GenericPredicate::Implemented(from_chalk(db, tr)) |
337 | } | 338 | } |
338 | chalk_ir::WhereClause::ProjectionEq(projection_eq) => { | 339 | chalk_ir::WhereClause::AliasEq(projection_eq) => { |
339 | let projection_ty = from_chalk(db, projection_eq.projection); | 340 | let projection_ty = from_chalk(db, projection_eq.alias); |
340 | let ty = from_chalk(db, projection_eq.ty); | 341 | let ty = from_chalk(db, projection_eq.ty); |
341 | GenericPredicate::Projection(super::ProjectionPredicate { projection_ty, ty }) | 342 | GenericPredicate::Projection(super::ProjectionPredicate { projection_ty, ty }) |
342 | } | 343 | } |
@@ -345,22 +346,22 @@ impl ToChalk for GenericPredicate { | |||
345 | } | 346 | } |
346 | 347 | ||
347 | impl ToChalk for ProjectionTy { | 348 | impl ToChalk for ProjectionTy { |
348 | type Chalk = chalk_ir::ProjectionTy<TypeFamily>; | 349 | type Chalk = chalk_ir::AliasTy<TypeFamily>; |
349 | 350 | ||
350 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy<TypeFamily> { | 351 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::AliasTy<TypeFamily> { |
351 | chalk_ir::ProjectionTy { | 352 | chalk_ir::AliasTy { |
352 | associated_ty_id: self.associated_ty.to_chalk(db), | 353 | associated_ty_id: self.associated_ty.to_chalk(db), |
353 | parameters: self.parameters.to_chalk(db), | 354 | substitution: self.parameters.to_chalk(db), |
354 | } | 355 | } |
355 | } | 356 | } |
356 | 357 | ||
357 | fn from_chalk( | 358 | fn from_chalk( |
358 | db: &impl HirDatabase, | 359 | db: &impl HirDatabase, |
359 | projection_ty: chalk_ir::ProjectionTy<TypeFamily>, | 360 | projection_ty: chalk_ir::AliasTy<TypeFamily>, |
360 | ) -> ProjectionTy { | 361 | ) -> ProjectionTy { |
361 | ProjectionTy { | 362 | ProjectionTy { |
362 | associated_ty: from_chalk(db, projection_ty.associated_ty_id), | 363 | associated_ty: from_chalk(db, projection_ty.associated_ty_id), |
363 | parameters: from_chalk(db, projection_ty.parameters), | 364 | parameters: from_chalk(db, projection_ty.substitution), |
364 | } | 365 | } |
365 | } | 366 | } |
366 | } | 367 | } |
@@ -369,10 +370,7 @@ impl ToChalk for super::ProjectionPredicate { | |||
369 | type Chalk = chalk_ir::Normalize<TypeFamily>; | 370 | type Chalk = chalk_ir::Normalize<TypeFamily>; |
370 | 371 | ||
371 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize<TypeFamily> { | 372 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize<TypeFamily> { |
372 | chalk_ir::Normalize { | 373 | chalk_ir::Normalize { alias: self.projection_ty.to_chalk(db), ty: self.ty.to_chalk(db) } |
373 | projection: self.projection_ty.to_chalk(db), | ||
374 | ty: self.ty.to_chalk(db), | ||
375 | } | ||
376 | } | 374 | } |
377 | 375 | ||
378 | fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize<TypeFamily>) -> Self { | 376 | fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize<TypeFamily>) -> Self { |