aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r--crates/ra_hir_ty/src/traits.rs18
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs108
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.
81const CHALK_SOLVER_MAX_SIZE: usize = 4; 90const CHALK_SOLVER_MAX_SIZE: usize = 4;
91/// This controls how much 'time' we give the Chalk solver before giving up.
92const CHALK_SOLVER_FUEL: i32 = 100;
93// TODO: tune both these values
82 94
83#[derive(Debug, Copy, Clone)] 95#[derive(Debug, Copy, Clone)]
84struct ChalkContext<'a, DB> { 96struct ChalkContext<'a, DB> {
@@ -97,7 +109,8 @@ pub(crate) fn trait_solver_query(
97} 109}
98 110
99fn create_chalk_solver() -> chalk_solve::Solver<TypeFamily> { 111fn 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
4use log::debug; 4use log::debug;
5 5
6use chalk_ir::{cast::Cast, Parameter, PlaceholderIndex, TypeName, UniverseIndex}; 6use chalk_ir::{cast::Cast, GoalData, Parameter, PlaceholderIndex, TypeName, UniverseIndex};
7 7
8use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId}; 8use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId};
9use ra_db::{ 9use 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
83impl chalk_ir::family::HasTypeFamily for TypeFamily { 103impl 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
196impl ToChalk for Substs { 200impl 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
347impl ToChalk for ProjectionTy { 348impl 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 {