|
1 | 1 | use crate::clauses::builder::ClauseBuilder;
|
2 | 2 | use crate::split::Split;
|
3 |
| -use chalk_ir::cast::{Cast, Caster}; |
| 3 | +use chalk_ir::cast::{Cast, CastTo, Caster}; |
4 | 4 | use chalk_ir::interner::Interner;
|
5 | 5 | use chalk_ir::*;
|
6 | 6 | use chalk_rust_ir::*;
|
@@ -180,6 +180,95 @@ impl<I: Interner> ToProgramClauses<I> for OpaqueTyDatum<I> {
|
180 | 180 | }
|
181 | 181 | }
|
182 | 182 |
|
| 183 | +fn application_ty<I: Interner>( |
| 184 | + builder: &mut ClauseBuilder<'_, I>, |
| 185 | + id: impl CastTo<TypeName<I>>, |
| 186 | +) -> ApplicationTy<I> { |
| 187 | + let interner = builder.interner(); |
| 188 | + ApplicationTy { |
| 189 | + name: id.cast(interner), |
| 190 | + substitution: builder.substitution_in_scope(), |
| 191 | + } |
| 192 | +} |
| 193 | + |
| 194 | +fn interned_application_ty<I: Interner>(interner: &I, appl_ty: &ApplicationTy<I>) -> Ty<I> { |
| 195 | + appl_ty.clone().intern(interner) |
| 196 | +} |
| 197 | + |
| 198 | +fn well_formed_program_clauses<'a, I, Wc>( |
| 199 | + builder: &'a mut ClauseBuilder<'_, I>, |
| 200 | + id: impl CastTo<TypeName<I>>, |
| 201 | + where_clauses: Wc, |
| 202 | +) where |
| 203 | + I: Interner, |
| 204 | + Wc: Iterator<Item = &'a QuantifiedWhereClause<I>>, |
| 205 | +{ |
| 206 | + // Given a type definition `struct Foo<T: Eq> { }` generate the clause |
| 207 | + // forall<T> { |
| 208 | + // WF(Foo<T>) :- WF(T: Eq). |
| 209 | + // } |
| 210 | + let interner = builder.interner(); |
| 211 | + let appl_ty = application_ty(builder, id); |
| 212 | + let ty = appl_ty.clone().intern(interner); |
| 213 | + builder.push_clause( |
| 214 | + WellFormed::Ty(ty.clone()), |
| 215 | + where_clauses |
| 216 | + .cloned() |
| 217 | + .map(|qwc| qwc.into_well_formed_goal(interner)), |
| 218 | + ); |
| 219 | +} |
| 220 | + |
| 221 | +fn fully_visible_program_clauses<'a, I>( |
| 222 | + builder: &'a mut ClauseBuilder<'_, I>, |
| 223 | + id: impl CastTo<TypeName<I>>, |
| 224 | +) where |
| 225 | + I: Interner, |
| 226 | +{ |
| 227 | + // Given a type definition `struct Foo<T: Eq> { }` generate the clause |
| 228 | + // forall<T> { |
| 229 | + // IsFullyVisible(Foo<T>) :- IsFullyVisible(T). |
| 230 | + // } |
| 231 | + let interner = builder.interner(); |
| 232 | + let appl_ty = application_ty(builder, id); |
| 233 | + let ty = interned_application_ty(interner, &appl_ty); |
| 234 | + builder.push_clause( |
| 235 | + DomainGoal::IsFullyVisible(ty.clone()), |
| 236 | + appl_ty |
| 237 | + .type_parameters(interner) |
| 238 | + .map(|typ| DomainGoal::IsFullyVisible(typ).cast::<Goal<_>>(interner)), |
| 239 | + ); |
| 240 | +} |
| 241 | + |
| 242 | +fn implied_bounds_program_clauses<'a, I, Wc>( |
| 243 | + builder: &'a mut ClauseBuilder<'_, I>, |
| 244 | + id: impl CastTo<TypeName<I>>, |
| 245 | + where_clauses: Wc, |
| 246 | +) where |
| 247 | + I: Interner, |
| 248 | + Wc: Iterator<Item = &'a QuantifiedWhereClause<I>>, |
| 249 | +{ |
| 250 | + let interner = builder.interner(); |
| 251 | + let appl_ty = application_ty(builder, id); |
| 252 | + let ty = interned_application_ty(interner, &appl_ty); |
| 253 | + |
| 254 | + for qwc in where_clauses { |
| 255 | + // Generate implied bounds rules. We have to push the binders from the where-clauses |
| 256 | + // too -- e.g., if we had `struct Foo<T: for<'a> Bar<&'a i32>>`, we would |
| 257 | + // create a reverse rule like: |
| 258 | + // |
| 259 | + // ```notrust |
| 260 | + // forall<T, 'a> { FromEnv(T: Bar<&'a i32>) :- FromEnv(Foo<T>) } |
| 261 | + // ``` |
| 262 | + // |
| 263 | + // In other words, you can assume `T: Bar<&'a i32>` |
| 264 | + // for any `'a` *if* you are assuming that `Foo<T>` is |
| 265 | + // well formed. |
| 266 | + builder.push_binders(&qwc, |builder, wc| { |
| 267 | + builder.push_clause(wc.into_from_env_goal(interner), Some(ty.clone().from_env())); |
| 268 | + }); |
| 269 | + } |
| 270 | +} |
| 271 | + |
183 | 272 | impl<I: Interner> ToProgramClauses<I> for StructDatum<I> {
|
184 | 273 | /// Given the following type definition: `struct Foo<T: Eq> { }`, generate:
|
185 | 274 | ///
|
@@ -234,33 +323,17 @@ impl<I: Interner> ToProgramClauses<I> for StructDatum<I> {
|
234 | 323 |
|
235 | 324 | let interner = builder.interner();
|
236 | 325 | let binders = self.binders.map_ref(|b| &b.where_clauses);
|
| 326 | + let id = self.id; |
| 327 | + |
237 | 328 | builder.push_binders(&binders, |builder, where_clauses| {
|
238 |
| - let self_appl_ty = &ApplicationTy { |
239 |
| - name: self.id.cast(interner), |
240 |
| - substitution: builder.substitution_in_scope(), |
241 |
| - }; |
242 |
| - let self_ty = self_appl_ty.clone().intern(interner); |
| 329 | + well_formed_program_clauses(builder, id, where_clauses.iter()); |
243 | 330 |
|
244 |
| - // forall<T> { |
245 |
| - // WF(Foo<T>) :- WF(T: Eq). |
246 |
| - // } |
247 |
| - builder.push_clause( |
248 |
| - WellFormed::Ty(self_ty.clone()), |
249 |
| - where_clauses |
250 |
| - .iter() |
251 |
| - .cloned() |
252 |
| - .map(|qwc| qwc.into_well_formed_goal(interner)), |
253 |
| - ); |
| 331 | + implied_bounds_program_clauses(builder, id, where_clauses.iter()); |
254 | 332 |
|
255 |
| - // forall<T> { |
256 |
| - // IsFullyVisible(Foo<T>) :- IsFullyVisible(T). |
257 |
| - // } |
258 |
| - builder.push_clause( |
259 |
| - DomainGoal::IsFullyVisible(self_ty.clone()), |
260 |
| - self_appl_ty |
261 |
| - .type_parameters(interner) |
262 |
| - .map(|ty| DomainGoal::IsFullyVisible(ty).cast::<Goal<_>>(interner)), |
263 |
| - ); |
| 333 | + fully_visible_program_clauses(builder, id); |
| 334 | + |
| 335 | + let self_appl_ty = application_ty(builder, id); |
| 336 | + let self_ty = interned_application_ty(interner, &self_appl_ty); |
264 | 337 |
|
265 | 338 | // Fundamental types often have rules in the form of:
|
266 | 339 | // Goal(FundamentalType<T>) :- Goal(T)
|
@@ -313,83 +386,40 @@ impl<I: Interner> ToProgramClauses<I> for StructDatum<I> {
|
313 | 386 | if self.flags.fundamental {
|
314 | 387 | fundamental_rule!(DownstreamType);
|
315 | 388 | }
|
316 |
| - |
317 |
| - for qwc in where_clauses { |
318 |
| - // Generate implied bounds rules. We have to push the binders from the where-clauses |
319 |
| - // too -- e.g., if we had `struct Foo<T: for<'a> Bar<&'a i32>>`, we would |
320 |
| - // create a reverse rule like: |
321 |
| - // |
322 |
| - // ```notrust |
323 |
| - // forall<T, 'a> { FromEnv(T: Bar<&'a i32>) :- FromEnv(Foo<T>) } |
324 |
| - // ``` |
325 |
| - // |
326 |
| - // In other words, you can assume `T: Bar<&'a i32>` |
327 |
| - // for any `'a` *if* you are assuming that `Foo<T>` is |
328 |
| - // well formed. |
329 |
| - builder.push_binders(&qwc, |builder, wc| { |
330 |
| - builder.push_clause( |
331 |
| - wc.into_from_env_goal(interner), |
332 |
| - Some(self_ty.clone().from_env()), |
333 |
| - ); |
334 |
| - }); |
335 |
| - } |
336 | 389 | });
|
337 | 390 | }
|
338 | 391 | }
|
339 | 392 |
|
340 | 393 | impl<I: Interner> ToProgramClauses<I> for FnDefDatum<I> {
|
| 394 | + /// Given the following function definition: `fn bar<T>() where T: Eq`, generate: |
| 395 | + /// |
| 396 | + /// ```notrust |
| 397 | + /// -- Rule WellFormed-Type |
| 398 | + /// forall<T> { |
| 399 | + /// WF(bar<T>) :- WF(T: Eq) |
| 400 | + /// } |
| 401 | + /// |
| 402 | + /// -- Rule Implied-Bound-From-Type |
| 403 | + /// forall<T> { |
| 404 | + /// FromEnv(T: Eq) :- FromEnv(bar<T>). |
| 405 | + /// } |
| 406 | + /// |
| 407 | + /// forall<T> { |
| 408 | + /// IsFullyVisible(bar<T>) :- IsFullyVisible(T). |
| 409 | + /// } |
| 410 | + /// ``` |
341 | 411 | fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>) {
|
342 | 412 | debug_heading!("FnDatum::to_program_clauses(self={:?})", self);
|
343 | 413 |
|
344 |
| - let interner = builder.interner(); |
345 | 414 | let binders = self.binders.map_ref(|b| &b.where_clauses);
|
346 |
| - builder.push_binders(&binders, |builder, where_clauses| { |
347 |
| - let self_appl_ty = &ApplicationTy { |
348 |
| - name: self.id.cast(interner), |
349 |
| - substitution: builder.substitution_in_scope(), |
350 |
| - }; |
351 |
| - let self_ty = self_appl_ty.clone().intern(interner); |
| 415 | + let id = self.id; |
352 | 416 |
|
353 |
| - // forall<T> { |
354 |
| - // WF(foo<T>) :- WF(T: Eq). |
355 |
| - // } |
356 |
| - builder.push_clause( |
357 |
| - WellFormed::Ty(self_ty.clone()), |
358 |
| - where_clauses |
359 |
| - .iter() |
360 |
| - .cloned() |
361 |
| - .map(|qwc| qwc.into_well_formed_goal(interner)), |
362 |
| - ); |
| 417 | + builder.push_binders(&binders, |builder, where_clauses| { |
| 418 | + well_formed_program_clauses(builder, id, where_clauses.iter()); |
363 | 419 |
|
364 |
| - // forall<T> { |
365 |
| - // IsFullyVisible(foo<T>) :- IsFullyVisible(T). |
366 |
| - // } |
367 |
| - builder.push_clause( |
368 |
| - DomainGoal::IsFullyVisible(self_ty.clone()), |
369 |
| - self_appl_ty |
370 |
| - .type_parameters(interner) |
371 |
| - .map(|ty| DomainGoal::IsFullyVisible(ty).cast::<Goal<_>>(interner)), |
372 |
| - ); |
| 420 | + implied_bounds_program_clauses(builder, id, where_clauses.iter()); |
373 | 421 |
|
374 |
| - for qwc in where_clauses { |
375 |
| - // Generate implied bounds rules. We have to push the binders from the where-clauses |
376 |
| - // too -- e.g., if we had `fn foo<T: for<'a> Bar<&'a i32>>()`, we would |
377 |
| - // create a reverse rule like: |
378 |
| - // |
379 |
| - // ```notrust |
380 |
| - // forall<T, 'a> { FromEnv(T: Bar<&'a i32>) :- FromEnv(foo<T>) } |
381 |
| - // ``` |
382 |
| - // |
383 |
| - // In other words, you can assume `T: Bar<&'a i32>` |
384 |
| - // for any `'a` *if* you are assuming that `foo<T>` is |
385 |
| - // well formed. |
386 |
| - builder.push_binders(&qwc, |builder, wc| { |
387 |
| - builder.push_clause( |
388 |
| - wc.into_from_env_goal(interner), |
389 |
| - Some(self_ty.clone().from_env()), |
390 |
| - ); |
391 |
| - }); |
392 |
| - } |
| 422 | + fully_visible_program_clauses(builder, id); |
393 | 423 | });
|
394 | 424 | }
|
395 | 425 | }
|
|
0 commit comments