]>
Commit | Line | Data |
---|---|---|
f9f354fc | 1 | use crate::clauses::builder::ClauseBuilder; |
f035d41b | 2 | use crate::rust_ir::*; |
f9f354fc | 3 | use crate::split::Split; |
f035d41b | 4 | use chalk_ir::cast::{Cast, CastTo, Caster}; |
f9f354fc XL |
5 | use chalk_ir::interner::Interner; |
6 | use chalk_ir::*; | |
f9f354fc | 7 | use std::iter; |
f035d41b | 8 | use tracing::instrument; |
f9f354fc XL |
9 | |
10 | /// Trait for lowering a given piece of rust-ir source (e.g., an impl | |
11 | /// or struct definition) into its associated "program clauses" -- | |
12 | /// that is, into the lowered, logical rules that it defines. | |
13 | pub trait ToProgramClauses<I: Interner> { | |
14 | fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>); | |
15 | } | |
16 | ||
17 | impl<I: Interner> ToProgramClauses<I> for ImplDatum<I> { | |
18 | /// Given `impl<T: Clone> Clone for Vec<T> { ... }`, generate: | |
19 | /// | |
20 | /// ```notrust | |
21 | /// -- Rule Implemented-From-Impl | |
22 | /// forall<T> { | |
23 | /// Implemented(Vec<T>: Clone) :- Implemented(T: Clone). | |
24 | /// } | |
25 | /// ``` | |
26 | /// | |
27 | /// For a negative impl like `impl... !Clone for ...`, however, we | |
28 | /// generate nothing -- this is just a way to *opt out* from the | |
29 | /// default auto trait impls, it doesn't have any positive effect | |
30 | /// on its own. | |
31 | fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>) { | |
32 | if self.is_positive() { | |
33 | let binders = self.binders.map_ref(|b| (&b.trait_ref, &b.where_clauses)); | |
34 | builder.push_binders(&binders, |builder, (trait_ref, where_clauses)| { | |
35 | builder.push_clause(trait_ref, where_clauses); | |
36 | }); | |
37 | } | |
38 | } | |
39 | } | |
40 | ||
41 | impl<I: Interner> ToProgramClauses<I> for AssociatedTyValue<I> { | |
42 | /// Given the following trait: | |
43 | /// | |
44 | /// ```notrust | |
45 | /// trait Iterable { | |
46 | /// type IntoIter<'a>: 'a; | |
47 | /// } | |
48 | /// ``` | |
49 | /// | |
50 | /// Then for the following impl: | |
51 | /// ```notrust | |
52 | /// impl<T> Iterable for Vec<T> where T: Clone { | |
53 | /// type IntoIter<'a> = Iter<'a, T>; | |
54 | /// } | |
55 | /// ``` | |
56 | /// | |
57 | /// we generate: | |
58 | /// | |
59 | /// ```notrust | |
60 | /// -- Rule Normalize-From-Impl | |
61 | /// forall<'a, T> { | |
62 | /// Normalize(<Vec<T> as Iterable>::IntoIter<'a> -> Iter<'a, T>>) :- | |
63 | /// Implemented(T: Clone), // (1) | |
64 | /// Implemented(Iter<'a, T>: 'a). // (2) | |
65 | /// } | |
66 | /// ``` | |
67 | fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>) { | |
68 | let impl_datum = builder.db.impl_datum(self.impl_id); | |
69 | let associated_ty = builder.db.associated_ty_data(self.associated_ty_id); | |
70 | ||
71 | builder.push_binders(&self.value, |builder, assoc_ty_value| { | |
72 | let all_parameters = builder.placeholders_in_scope().to_vec(); | |
73 | ||
74 | // Get the projection for this associated type: | |
75 | // | |
76 | // * `impl_params`: `[!T]` | |
77 | // * `projection`: `<Vec<!T> as Iterable>::Iter<'!a>` | |
78 | let (impl_params, projection) = builder | |
79 | .db | |
80 | .impl_parameters_and_projection_from_associated_ty_value(&all_parameters, self); | |
81 | ||
82 | // Assemble the full list of conditions for projection to be valid. | |
83 | // This comes in two parts, marked as (1) and (2) in doc above: | |
84 | // | |
85 | // 1. require that the where clauses from the impl apply | |
86 | let interner = builder.db.interner(); | |
87 | let impl_where_clauses = impl_datum | |
88 | .binders | |
89 | .map_ref(|b| &b.where_clauses) | |
90 | .into_iter() | |
91 | .map(|wc| wc.substitute(interner, impl_params)); | |
92 | ||
93 | // 2. any where-clauses from the `type` declaration in the trait: the | |
94 | // parameters must be substituted with those of the impl | |
95 | let assoc_ty_where_clauses = associated_ty | |
96 | .binders | |
97 | .map_ref(|b| &b.where_clauses) | |
98 | .into_iter() | |
99 | .map(|wc| wc.substitute(interner, &projection.substitution)); | |
100 | ||
101 | // Create the final program clause: | |
102 | // | |
103 | // ```notrust | |
104 | // -- Rule Normalize-From-Impl | |
105 | // forall<'a, T> { | |
106 | // Normalize(<Vec<T> as Iterable>::IntoIter<'a> -> Iter<'a, T>>) :- | |
107 | // Implemented(T: Clone), // (1) | |
108 | // Implemented(Iter<'a, T>: 'a). // (2) | |
109 | // } | |
110 | // ``` | |
111 | builder.push_clause( | |
112 | Normalize { | |
113 | alias: AliasTy::Projection(projection.clone()), | |
114 | ty: assoc_ty_value.ty, | |
115 | }, | |
116 | impl_where_clauses.chain(assoc_ty_where_clauses), | |
117 | ); | |
118 | }); | |
119 | } | |
120 | } | |
121 | ||
122 | impl<I: Interner> ToProgramClauses<I> for OpaqueTyDatum<I> { | |
123 | /// Given `opaque type T<..>: A + B = HiddenTy;`, we generate: | |
124 | /// | |
125 | /// ```notrust | |
126 | /// AliasEq(T<..> = HiddenTy) :- Reveal. | |
127 | /// AliasEq(T<..> = !T<..>). | |
128 | /// Implemented(!T<..>: A). | |
129 | /// Implemented(!T<..>: B). | |
f9f354fc XL |
130 | /// ``` |
131 | /// where `!T<..>` is the placeholder for the unnormalized type `T<..>`. | |
f035d41b | 132 | #[instrument(level = "debug", skip(builder))] |
f9f354fc | 133 | fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>) { |
f9f354fc XL |
134 | builder.push_binders(&self.bound, |builder, opaque_ty_bound| { |
135 | let interner = builder.interner(); | |
136 | let substitution = builder.substitution_in_scope(); | |
137 | let alias = AliasTy::Opaque(OpaqueTy { | |
138 | opaque_ty_id: self.opaque_ty_id, | |
139 | substitution: substitution.clone(), | |
140 | }); | |
141 | ||
142 | let alias_placeholder_ty = Ty::new( | |
143 | interner, | |
144 | ApplicationTy { | |
f035d41b | 145 | name: self.opaque_ty_id.cast(interner), |
f9f354fc XL |
146 | substitution, |
147 | }, | |
148 | ); | |
149 | ||
150 | // AliasEq(T<..> = HiddenTy) :- Reveal. | |
151 | builder.push_clause( | |
152 | DomainGoal::Holds( | |
153 | AliasEq { | |
154 | alias: alias.clone(), | |
f035d41b | 155 | ty: builder.db.hidden_opaque_type(self.opaque_ty_id), |
f9f354fc XL |
156 | } |
157 | .cast(interner), | |
158 | ), | |
159 | iter::once(DomainGoal::Reveal(())), | |
160 | ); | |
161 | ||
162 | // AliasEq(T<..> = !T<..>). | |
163 | builder.push_fact(DomainGoal::Holds( | |
164 | AliasEq { | |
165 | alias: alias.clone(), | |
166 | ty: alias_placeholder_ty.clone(), | |
167 | } | |
168 | .cast(interner), | |
169 | )); | |
170 | ||
171 | let substitution = Substitution::from1(interner, alias_placeholder_ty.clone()); | |
f035d41b | 172 | for bound in opaque_ty_bound.bounds { |
f9f354fc XL |
173 | // Implemented(!T<..>: Bound). |
174 | let bound_with_placeholder_ty = bound.substitute(interner, &substitution); | |
175 | builder.push_binders(&bound_with_placeholder_ty, |builder, bound| { | |
176 | builder.push_fact(bound); | |
177 | }); | |
178 | } | |
179 | }); | |
180 | } | |
181 | } | |
182 | ||
f035d41b XL |
183 | fn application_ty<I: Interner>( |
184 | builder: &mut ClauseBuilder<'_, I>, | |
185 | type_name: impl CastTo<TypeName<I>>, | |
186 | ) -> ApplicationTy<I> { | |
187 | let interner = builder.interner(); | |
188 | ApplicationTy { | |
189 | name: type_name.cast(interner), | |
190 | substitution: builder.substitution_in_scope(), | |
191 | } | |
192 | } | |
193 | ||
194 | /// Generates the "well-formed" program clauses for an applicative type | |
195 | /// with the name `type_name`. For example, given a struct definition: | |
196 | /// | |
197 | /// ```ignore | |
198 | /// struct Foo<T: Eq> { } | |
199 | /// ``` | |
200 | /// | |
201 | /// we would generate the clause: | |
202 | /// | |
203 | /// ```notrust | |
204 | /// forall<T> { | |
205 | /// WF(Foo<T>) :- WF(T: Eq). | |
206 | /// } | |
207 | /// ``` | |
208 | /// | |
209 | /// # Parameters | |
210 | /// - builder -- the clause builder. We assume all the generic types from `Foo` are in scope | |
211 | /// - type_name -- in our example above, the name `Foo` | |
212 | /// - where_clauses -- the list of where clauses declared on the type (`T: Eq`, in our example) | |
213 | fn well_formed_program_clauses<'a, I, Wc>( | |
214 | builder: &'a mut ClauseBuilder<'_, I>, | |
215 | type_name: impl CastTo<TypeName<I>>, | |
216 | where_clauses: Wc, | |
217 | ) where | |
218 | I: Interner, | |
219 | Wc: Iterator<Item = &'a QuantifiedWhereClause<I>>, | |
220 | { | |
221 | let interner = builder.interner(); | |
222 | let appl_ty = application_ty(builder, type_name); | |
223 | let ty = appl_ty.clone().intern(interner); | |
224 | builder.push_clause( | |
225 | WellFormed::Ty(ty.clone()), | |
226 | where_clauses | |
227 | .cloned() | |
228 | .map(|qwc| qwc.into_well_formed_goal(interner)), | |
229 | ); | |
230 | } | |
231 | ||
232 | /// Generates the "fully visible" program clauses for an applicative type | |
233 | /// with the name `type_name`. For example, given a struct definition: | |
234 | /// | |
235 | /// ```ignore | |
236 | /// struct Foo<T: Eq> { } | |
237 | /// ``` | |
238 | /// | |
239 | /// we would generate the clause: | |
240 | /// | |
241 | /// ```notrust | |
242 | /// forall<T> { | |
243 | /// IsFullyVisible(Foo<T>) :- IsFullyVisible(T). | |
244 | /// } | |
245 | /// ``` | |
246 | /// | |
247 | /// # Parameters | |
248 | /// | |
249 | /// - builder -- the clause builder. We assume all the generic types from `Foo` are in scope | |
250 | /// - type_name -- in our example above, the name `Foo` | |
251 | fn fully_visible_program_clauses<'a, I>( | |
252 | builder: &'a mut ClauseBuilder<'_, I>, | |
253 | type_name: impl CastTo<TypeName<I>>, | |
254 | ) where | |
255 | I: Interner, | |
256 | { | |
257 | let interner = builder.interner(); | |
258 | let appl_ty = application_ty(builder, type_name); | |
259 | let ty = appl_ty.clone().intern(interner); | |
260 | builder.push_clause( | |
261 | DomainGoal::IsFullyVisible(ty.clone()), | |
262 | appl_ty | |
263 | .type_parameters(interner) | |
264 | .map(|typ| DomainGoal::IsFullyVisible(typ).cast::<Goal<_>>(interner)), | |
265 | ); | |
266 | } | |
267 | ||
268 | /// Generates the "implied bounds" clauses for an applicative | |
269 | /// type with the name `type_name`. For example, if `type_name` | |
270 | /// represents a struct `S` that is declared like: | |
271 | /// | |
272 | /// ```ignore | |
273 | /// struct S<T> where T: Eq { } | |
274 | /// ``` | |
275 | /// | |
276 | /// then we would generate the rule: | |
277 | /// | |
278 | /// ```notrust | |
279 | /// FromEnv(T: Eq) :- FromEnv(S<T>) | |
280 | /// ``` | |
281 | /// | |
282 | /// # Parameters | |
283 | /// | |
284 | /// - builder -- the clause builder. We assume all the generic types from `S` are in scope. | |
285 | /// - type_name -- in our example above, the name `S` | |
286 | /// - where_clauses -- the list of where clauses declared on the type (`T: Eq`, in our example). | |
287 | fn implied_bounds_program_clauses<'a, I, Wc>( | |
288 | builder: &'a mut ClauseBuilder<'_, I>, | |
289 | type_name: impl CastTo<TypeName<I>>, | |
290 | where_clauses: Wc, | |
291 | ) where | |
292 | I: Interner, | |
293 | Wc: Iterator<Item = &'a QuantifiedWhereClause<I>>, | |
294 | { | |
295 | let interner = builder.interner(); | |
296 | let appl_ty = application_ty(builder, type_name); | |
297 | let ty = appl_ty.clone().intern(interner); | |
298 | ||
299 | for qwc in where_clauses { | |
300 | builder.push_binders(&qwc, |builder, wc| { | |
301 | builder.push_clause(wc.into_from_env_goal(interner), Some(ty.clone().from_env())); | |
302 | }); | |
303 | } | |
304 | } | |
305 | ||
306 | impl<I: Interner> ToProgramClauses<I> for AdtDatum<I> { | |
f9f354fc XL |
307 | /// Given the following type definition: `struct Foo<T: Eq> { }`, generate: |
308 | /// | |
309 | /// ```notrust | |
310 | /// -- Rule WellFormed-Type | |
311 | /// forall<T> { | |
312 | /// WF(Foo<T>) :- WF(T: Eq). | |
313 | /// } | |
314 | /// | |
315 | /// -- Rule Implied-Bound-From-Type | |
316 | /// forall<T> { | |
317 | /// FromEnv(T: Eq) :- FromEnv(Foo<T>). | |
318 | /// } | |
319 | /// | |
320 | /// forall<T> { | |
321 | /// IsFullyVisible(Foo<T>) :- IsFullyVisible(T). | |
322 | /// } | |
323 | /// ``` | |
324 | /// | |
325 | /// If the type `Foo` is marked `#[upstream]`, we also generate: | |
326 | /// | |
327 | /// ```notrust | |
328 | /// forall<T> { IsUpstream(Foo<T>). } | |
329 | /// ``` | |
330 | /// | |
331 | /// Otherwise, if the type `Foo` is not marked `#[upstream]`, we generate: | |
332 | /// ```notrust | |
333 | /// forall<T> { IsLocal(Foo<T>). } | |
334 | /// ``` | |
335 | /// | |
336 | /// Given an `#[upstream]` type that is also fundamental: | |
337 | /// | |
338 | /// ```notrust | |
339 | /// #[upstream] | |
340 | /// #[fundamental] | |
341 | /// struct Box<T> {} | |
342 | /// ``` | |
343 | /// | |
344 | /// We generate the following clauses: | |
345 | /// | |
346 | /// ```notrust | |
347 | /// forall<T> { IsLocal(Box<T>) :- IsLocal(T). } | |
348 | /// | |
349 | /// forall<T> { IsUpstream(Box<T>) :- IsUpstream(T). } | |
350 | /// | |
351 | /// // Generated for both upstream and local fundamental types | |
352 | /// forall<T> { DownstreamType(Box<T>) :- DownstreamType(T). } | |
353 | /// ``` | |
354 | /// | |
f035d41b | 355 | #[instrument(level = "debug", skip(builder))] |
f9f354fc | 356 | fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>) { |
f9f354fc XL |
357 | let interner = builder.interner(); |
358 | let binders = self.binders.map_ref(|b| &b.where_clauses); | |
f035d41b XL |
359 | let id = self.id; |
360 | ||
f9f354fc | 361 | builder.push_binders(&binders, |builder, where_clauses| { |
f035d41b | 362 | well_formed_program_clauses(builder, id, where_clauses.iter()); |
f9f354fc | 363 | |
f035d41b | 364 | implied_bounds_program_clauses(builder, id, where_clauses.iter()); |
f9f354fc | 365 | |
f035d41b XL |
366 | fully_visible_program_clauses(builder, id); |
367 | ||
368 | let self_appl_ty = application_ty(builder, id); | |
369 | let self_ty = self_appl_ty.clone().intern(interner); | |
f9f354fc XL |
370 | |
371 | // Fundamental types often have rules in the form of: | |
372 | // Goal(FundamentalType<T>) :- Goal(T) | |
373 | // This macro makes creating that kind of clause easy | |
374 | macro_rules! fundamental_rule { | |
375 | ($goal:ident) => { | |
376 | // Fundamental types must always have at least one | |
377 | // type parameter for this rule to make any | |
378 | // sense. We currently do not have have any | |
379 | // fundamental types with more than one type | |
380 | // parameter, nor do we know what the behaviour | |
381 | // for that should be. Thus, we are asserting here | |
382 | // that there is only a single type parameter | |
383 | // until the day when someone makes a decision | |
384 | // about how that should behave. | |
385 | assert_eq!( | |
386 | self_appl_ty.len_type_parameters(interner), | |
387 | 1, | |
388 | "Only fundamental types with a single parameter are supported" | |
389 | ); | |
390 | ||
391 | builder.push_clause( | |
392 | DomainGoal::$goal(self_ty.clone()), | |
393 | Some(DomainGoal::$goal( | |
394 | // This unwrap is safe because we asserted | |
395 | // above for the presence of a type | |
396 | // parameter | |
397 | self_appl_ty.first_type_parameter(interner).unwrap(), | |
398 | )), | |
399 | ); | |
400 | }; | |
401 | } | |
402 | ||
403 | // Types that are not marked `#[upstream]` satisfy IsLocal(TypeName) | |
404 | if !self.flags.upstream { | |
405 | // `IsLocalTy(Ty)` depends *only* on whether the type | |
406 | // is marked #[upstream] and nothing else | |
407 | builder.push_fact(DomainGoal::IsLocal(self_ty.clone())); | |
408 | } else if self.flags.fundamental { | |
409 | // If a type is `#[upstream]`, but is also | |
410 | // `#[fundamental]`, it satisfies IsLocal if and only | |
411 | // if its parameters satisfy IsLocal | |
412 | fundamental_rule!(IsLocal); | |
413 | fundamental_rule!(IsUpstream); | |
414 | } else { | |
415 | // The type is just upstream and not fundamental | |
416 | builder.push_fact(DomainGoal::IsUpstream(self_ty.clone())); | |
417 | } | |
418 | ||
419 | if self.flags.fundamental { | |
420 | fundamental_rule!(DownstreamType); | |
421 | } | |
f035d41b XL |
422 | }); |
423 | } | |
424 | } | |
f9f354fc | 425 | |
f035d41b XL |
426 | impl<I: Interner> ToProgramClauses<I> for FnDefDatum<I> { |
427 | /// Given the following function definition: `fn bar<T>() where T: Eq`, generate: | |
428 | /// | |
429 | /// ```notrust | |
430 | /// -- Rule WellFormed-Type | |
431 | /// forall<T> { | |
432 | /// WF(bar<T>) :- WF(T: Eq) | |
433 | /// } | |
434 | /// | |
435 | /// -- Rule Implied-Bound-From-Type | |
436 | /// forall<T> { | |
437 | /// FromEnv(T: Eq) :- FromEnv(bar<T>). | |
438 | /// } | |
439 | /// | |
440 | /// forall<T> { | |
441 | /// IsFullyVisible(bar<T>) :- IsFullyVisible(T). | |
442 | /// } | |
443 | /// ``` | |
444 | #[instrument(level = "debug", skip(builder))] | |
445 | fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>) { | |
446 | let binders = self.binders.map_ref(|b| &b.where_clauses); | |
447 | let id = self.id; | |
448 | ||
449 | builder.push_binders(&binders, |builder, where_clauses| { | |
450 | well_formed_program_clauses(builder, id, where_clauses.iter()); | |
451 | ||
452 | implied_bounds_program_clauses(builder, id, where_clauses.iter()); | |
453 | ||
454 | fully_visible_program_clauses(builder, id); | |
f9f354fc XL |
455 | }); |
456 | } | |
457 | } | |
458 | ||
459 | impl<I: Interner> ToProgramClauses<I> for TraitDatum<I> { | |
460 | /// Given the following trait declaration: `trait Ord<T> where Self: Eq<T> { ... }`, generate: | |
461 | /// | |
462 | /// ```notrust | |
463 | /// -- Rule WellFormed-TraitRef | |
464 | /// forall<Self, T> { | |
465 | /// WF(Self: Ord<T>) :- Implemented(Self: Ord<T>), WF(Self: Eq<T>). | |
466 | /// } | |
467 | /// ``` | |
468 | /// | |
469 | /// and the reverse rules: | |
470 | /// | |
471 | /// ```notrust | |
472 | /// -- Rule Implemented-From-Env | |
473 | /// forall<Self, T> { | |
474 | /// (Self: Ord<T>) :- FromEnv(Self: Ord<T>). | |
475 | /// } | |
476 | /// | |
477 | /// -- Rule Implied-Bound-From-Trait | |
478 | /// forall<Self, T> { | |
479 | /// FromEnv(Self: Eq<T>) :- FromEnv(Self: Ord<T>). | |
480 | /// } | |
481 | /// ``` | |
482 | /// | |
483 | /// As specified in the orphan rules, if a trait is not marked `#[upstream]`, the current crate | |
484 | /// can implement it for any type. To represent that, we generate: | |
485 | /// | |
486 | /// ```notrust | |
487 | /// // `Ord<T>` would not be `#[upstream]` when compiling `std` | |
488 | /// forall<Self, T> { LocalImplAllowed(Self: Ord<T>). } | |
489 | /// ``` | |
490 | /// | |
491 | /// For traits that are `#[upstream]` (i.e. not in the current crate), the orphan rules dictate | |
492 | /// that impls are allowed as long as at least one type parameter is local and each type | |
493 | /// prior to that is fully visible. That means that each type prior to the first local | |
494 | /// type cannot contain any of the type parameters of the impl. | |
495 | /// | |
496 | /// This rule is fairly complex, so we expand it and generate a program clause for each | |
497 | /// possible case. This is represented as follows: | |
498 | /// | |
499 | /// ```notrust | |
500 | /// // for `#[upstream] trait Foo<T, U, V> where Self: Eq<T> { ... }` | |
501 | /// forall<Self, T, U, V> { | |
502 | /// LocalImplAllowed(Self: Foo<T, U, V>) :- IsLocal(Self). | |
503 | /// } | |
504 | /// | |
505 | /// forall<Self, T, U, V> { | |
506 | /// LocalImplAllowed(Self: Foo<T, U, V>) :- | |
507 | /// IsFullyVisible(Self), | |
508 | /// IsLocal(T). | |
509 | /// } | |
510 | /// | |
511 | /// forall<Self, T, U, V> { | |
512 | /// LocalImplAllowed(Self: Foo<T, U, V>) :- | |
513 | /// IsFullyVisible(Self), | |
514 | /// IsFullyVisible(T), | |
515 | /// IsLocal(U). | |
516 | /// } | |
517 | /// | |
518 | /// forall<Self, T, U, V> { | |
519 | /// LocalImplAllowed(Self: Foo<T, U, V>) :- | |
520 | /// IsFullyVisible(Self), | |
521 | /// IsFullyVisible(T), | |
522 | /// IsFullyVisible(U), | |
523 | /// IsLocal(V). | |
524 | /// } | |
525 | /// ``` | |
526 | /// | |
527 | /// The overlap check uses compatible { ... } mode to ensure that it accounts for impls that | |
528 | /// may exist in some other *compatible* world. For every upstream trait, we add a rule to | |
529 | /// account for the fact that upstream crates are able to compatibly add impls of upstream | |
530 | /// traits for upstream types. | |
531 | /// | |
532 | /// ```notrust | |
533 | /// // For `#[upstream] trait Foo<T, U, V> where Self: Eq<T> { ... }` | |
534 | /// forall<Self, T, U, V> { | |
535 | /// Implemented(Self: Foo<T, U, V>) :- | |
536 | /// Implemented(Self: Eq<T>), // where clauses | |
537 | /// Compatible, // compatible modality | |
538 | /// IsUpstream(Self), | |
539 | /// IsUpstream(T), | |
540 | /// IsUpstream(U), | |
541 | /// IsUpstream(V), | |
542 | /// CannotProve. // returns ambiguous | |
543 | /// } | |
544 | /// ``` | |
545 | /// | |
546 | /// In certain situations, this is too restrictive. Consider the following code: | |
547 | /// | |
548 | /// ```notrust | |
549 | /// /* In crate std */ | |
550 | /// trait Sized { } | |
551 | /// struct str { } | |
552 | /// | |
553 | /// /* In crate bar (depends on std) */ | |
554 | /// trait Bar { } | |
555 | /// impl Bar for str { } | |
556 | /// impl<T> Bar for T where T: Sized { } | |
557 | /// ``` | |
558 | /// | |
559 | /// Here, because of the rules we've defined, these two impls overlap. The std crate is | |
560 | /// upstream to bar, and thus it is allowed to compatibly implement Sized for str. If str | |
561 | /// can implement Sized in a compatible future, these two impls definitely overlap since the | |
562 | /// second impl covers all types that implement Sized. | |
563 | /// | |
564 | /// The solution we've got right now is to mark Sized as "fundamental" when it is defined. | |
565 | /// This signals to the Rust compiler that it can rely on the fact that str does not | |
566 | /// implement Sized in all contexts. A consequence of this is that we can no longer add an | |
567 | /// implementation of Sized compatibly for str. This is the trade off you make when defining | |
568 | /// a fundamental trait. | |
569 | /// | |
570 | /// To implement fundamental traits, we simply just do not add the rule above that allows | |
571 | /// upstream types to implement upstream traits. Fundamental traits are not allowed to | |
572 | /// compatibly do that. | |
573 | fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>) { | |
574 | let interner = builder.interner(); | |
575 | let binders = self.binders.map_ref(|b| &b.where_clauses); | |
576 | builder.push_binders(&binders, |builder, where_clauses| { | |
577 | let trait_ref = chalk_ir::TraitRef { | |
578 | trait_id: self.id, | |
579 | substitution: builder.substitution_in_scope(), | |
580 | }; | |
581 | ||
582 | builder.push_clause( | |
583 | trait_ref.clone().well_formed(), | |
584 | where_clauses | |
585 | .iter() | |
586 | .cloned() | |
587 | .map(|qwc| qwc.into_well_formed_goal(interner)) | |
588 | .casted::<Goal<_>>(interner) | |
589 | .chain(Some(trait_ref.clone().cast(interner))), | |
590 | ); | |
591 | ||
592 | // The number of parameters will always be at least 1 | |
593 | // because of the Self parameter that is automatically | |
594 | // added to every trait. This is important because | |
595 | // otherwise the added program clauses would not have any | |
596 | // conditions. | |
597 | let type_parameters: Vec<_> = trait_ref.type_parameters(interner).collect(); | |
598 | ||
599 | // Drop trait can't have downstream implementation because it can only | |
600 | // be implemented with the same genericity as the struct definition, | |
601 | // i.e. Drop implementation for `struct S<T: Eq> {}` is forced to be | |
602 | // `impl Drop<T: Eq> for S<T> { ... }`. That means that orphan rules | |
603 | // prevent Drop from being implemented in downstream crates. | |
f035d41b | 604 | if self.well_known != Some(WellKnownTrait::Drop) { |
f9f354fc XL |
605 | // Add all cases for potential downstream impls that could exist |
606 | for i in 0..type_parameters.len() { | |
607 | builder.push_clause( | |
608 | trait_ref.clone(), | |
609 | where_clauses | |
610 | .iter() | |
611 | .cloned() | |
612 | .casted(interner) | |
613 | .chain(iter::once(DomainGoal::Compatible(()).cast(interner))) | |
614 | .chain((0..i).map(|j| { | |
615 | DomainGoal::IsFullyVisible(type_parameters[j].clone()) | |
616 | .cast(interner) | |
617 | })) | |
618 | .chain(iter::once( | |
619 | DomainGoal::DownstreamType(type_parameters[i].clone()) | |
620 | .cast(interner), | |
621 | )) | |
622 | .chain(iter::once(GoalData::CannotProve(()).intern(interner))), | |
623 | ); | |
624 | } | |
625 | } | |
626 | ||
627 | // Orphan rules: | |
628 | if !self.flags.upstream { | |
629 | // Impls for traits declared locally always pass the impl rules | |
630 | builder.push_fact(DomainGoal::LocalImplAllowed(trait_ref.clone())); | |
631 | } else { | |
632 | // Impls for remote traits must have a local type in the right place | |
633 | for i in 0..type_parameters.len() { | |
634 | builder.push_clause( | |
635 | DomainGoal::LocalImplAllowed(trait_ref.clone()), | |
636 | (0..i) | |
637 | .map(|j| DomainGoal::IsFullyVisible(type_parameters[j].clone())) | |
638 | .chain(Some(DomainGoal::IsLocal(type_parameters[i].clone()))), | |
639 | ); | |
640 | } | |
641 | } | |
642 | ||
643 | // Fundamental traits can be reasoned about negatively without any ambiguity, so no | |
644 | // need for this rule if the trait is fundamental. | |
645 | if !self.flags.fundamental { | |
646 | builder.push_clause( | |
647 | trait_ref.clone(), | |
648 | where_clauses | |
649 | .iter() | |
650 | .cloned() | |
651 | .casted(interner) | |
652 | .chain(iter::once(DomainGoal::Compatible(()).cast(interner))) | |
653 | .chain( | |
654 | trait_ref | |
655 | .type_parameters(interner) | |
656 | .map(|ty| DomainGoal::IsUpstream(ty).cast(interner)), | |
657 | ) | |
658 | .chain(iter::once(GoalData::CannotProve(()).intern(interner))), | |
659 | ); | |
660 | } | |
661 | ||
662 | // Reverse implied bound rules: given (e.g.) `trait Foo: Bar + Baz`, | |
663 | // we create rules like: | |
664 | // | |
665 | // ``` | |
666 | // FromEnv(T: Bar) :- FromEnv(T: Foo) | |
667 | // ``` | |
668 | // | |
669 | // and | |
670 | // | |
671 | // ``` | |
672 | // FromEnv(T: Baz) :- FromEnv(T: Foo) | |
673 | // ``` | |
674 | for qwc in &where_clauses { | |
675 | builder.push_binders(qwc, |builder, wc| { | |
676 | builder.push_clause( | |
677 | wc.into_from_env_goal(interner), | |
678 | Some(trait_ref.clone().from_env()), | |
679 | ); | |
680 | }); | |
681 | } | |
682 | ||
683 | // Finally, for every trait `Foo` we make a rule | |
684 | // | |
685 | // ``` | |
686 | // Implemented(T: Foo) :- FromEnv(T: Foo) | |
687 | // ``` | |
688 | builder.push_clause(trait_ref.clone(), Some(trait_ref.clone().from_env())); | |
689 | }); | |
690 | } | |
691 | } | |
692 | ||
693 | impl<I: Interner> ToProgramClauses<I> for AssociatedTyDatum<I> { | |
694 | /// For each associated type, we define the "projection | |
695 | /// equality" rules. There are always two; one for a successful normalization, | |
696 | /// and one for the "fallback" notion of equality. | |
697 | /// | |
698 | /// Given: (here, `'a` and `T` represent zero or more parameters) | |
699 | /// | |
700 | /// ```notrust | |
701 | /// trait Foo { | |
702 | /// type Assoc<'a, T>: Bounds where WC; | |
703 | /// } | |
704 | /// ``` | |
705 | /// | |
706 | /// we generate the 'fallback' rule: | |
707 | /// | |
708 | /// ```notrust | |
709 | /// -- Rule AliasEq-Placeholder | |
710 | /// forall<Self, 'a, T> { | |
711 | /// AliasEq(<Self as Foo>::Assoc<'a, T> = (Foo::Assoc<'a, T>)<Self>). | |
712 | /// } | |
713 | /// ``` | |
714 | /// | |
715 | /// and | |
716 | /// | |
717 | /// ```notrust | |
718 | /// -- Rule AliasEq-Normalize | |
719 | /// forall<Self, 'a, T, U> { | |
720 | /// AliasEq(<T as Foo>::Assoc<'a, T> = U) :- | |
721 | /// Normalize(<T as Foo>::Assoc -> U). | |
722 | /// } | |
723 | /// ``` | |
724 | /// | |
725 | /// We used to generate an "elaboration" rule like this: | |
726 | /// | |
727 | /// ```notrust | |
728 | /// forall<T> { | |
729 | /// T: Foo :- exists<U> { AliasEq(<T as Foo>::Assoc = U) }. | |
730 | /// } | |
731 | /// ``` | |
732 | /// | |
733 | /// but this caused problems with the recursive solver. In | |
734 | /// particular, whenever normalization is possible, we cannot | |
735 | /// solve that projection uniquely, since we can now elaborate | |
736 | /// `AliasEq` to fallback *or* normalize it. So instead we | |
737 | /// handle this kind of reasoning through the `FromEnv` predicate. | |
738 | /// | |
739 | /// We also generate rules specific to WF requirements and implied bounds: | |
740 | /// | |
741 | /// ```notrust | |
742 | /// -- Rule WellFormed-AssocTy | |
743 | /// forall<Self, 'a, T> { | |
744 | /// WellFormed((Foo::Assoc)<Self, 'a, T>) :- WellFormed(Self: Foo), WellFormed(WC). | |
745 | /// } | |
746 | /// | |
747 | /// -- Rule Implied-WC-From-AssocTy | |
748 | /// forall<Self, 'a, T> { | |
749 | /// FromEnv(WC) :- FromEnv((Foo::Assoc)<Self, 'a, T>). | |
750 | /// } | |
751 | /// | |
752 | /// -- Rule Implied-Bound-From-AssocTy | |
753 | /// forall<Self, 'a, T> { | |
754 | /// FromEnv(<Self as Foo>::Assoc<'a,T>: Bounds) :- FromEnv(Self: Foo), WC. | |
755 | /// } | |
756 | /// | |
757 | /// -- Rule Implied-Trait-From-AssocTy | |
758 | /// forall<Self,'a, T> { | |
759 | /// FromEnv(Self: Foo) :- FromEnv((Foo::Assoc)<Self, 'a,T>). | |
760 | /// } | |
761 | /// ``` | |
762 | fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>) { | |
763 | let interner = builder.interner(); | |
764 | let binders = self.binders.map_ref(|b| (&b.where_clauses, &b.bounds)); | |
765 | builder.push_binders(&binders, |builder, (where_clauses, bounds)| { | |
766 | let substitution = builder.substitution_in_scope(); | |
767 | ||
768 | let projection = ProjectionTy { | |
769 | associated_ty_id: self.id, | |
770 | substitution: substitution.clone(), | |
771 | }; | |
772 | let projection_ty = AliasTy::Projection(projection.clone()).intern(interner); | |
773 | ||
774 | // Retrieve the trait ref embedding the associated type | |
775 | let trait_ref = builder.db.trait_ref_from_projection(&projection); | |
776 | ||
777 | // Construct an application from the projection. So if we have `<T as Iterator>::Item`, | |
778 | // we would produce `(Iterator::Item)<T>`. | |
779 | let app_ty: Ty<_> = ApplicationTy { | |
780 | name: TypeName::AssociatedType(self.id), | |
781 | substitution, | |
782 | } | |
783 | .intern(interner); | |
784 | ||
785 | let projection_eq = AliasEq { | |
786 | alias: AliasTy::Projection(projection.clone()), | |
787 | ty: app_ty.clone(), | |
788 | }; | |
789 | ||
790 | // Fallback rule. The solver uses this to move between the projection | |
791 | // and placeholder type. | |
792 | // | |
793 | // forall<Self> { | |
794 | // AliasEq(<Self as Foo>::Assoc = (Foo::Assoc)<Self>). | |
795 | // } | |
796 | builder.push_fact_with_priority(projection_eq, ClausePriority::Low); | |
797 | ||
798 | // Well-formedness of projection type. | |
799 | // | |
800 | // forall<Self> { | |
801 | // WellFormed((Foo::Assoc)<Self>) :- WellFormed(Self: Foo), WellFormed(WC). | |
802 | // } | |
803 | builder.push_clause( | |
804 | WellFormed::Ty(app_ty.clone()), | |
805 | iter::once(WellFormed::Trait(trait_ref.clone()).cast::<Goal<_>>(interner)).chain( | |
806 | where_clauses | |
807 | .iter() | |
808 | .cloned() | |
809 | .map(|qwc| qwc.into_well_formed_goal(interner)) | |
810 | .casted(interner), | |
811 | ), | |
812 | ); | |
813 | ||
814 | // Assuming well-formedness of projection type means we can assume | |
815 | // the trait ref as well. Mostly used in function bodies. | |
816 | // | |
817 | // forall<Self> { | |
818 | // FromEnv(Self: Foo) :- FromEnv((Foo::Assoc)<Self>). | |
819 | // } | |
820 | builder.push_clause(FromEnv::Trait(trait_ref.clone()), Some(app_ty.from_env())); | |
821 | ||
822 | // Reverse rule for where clauses. | |
823 | // | |
824 | // forall<Self> { | |
825 | // FromEnv(WC) :- FromEnv((Foo::Assoc)<Self>). | |
826 | // } | |
827 | // | |
828 | // This is really a family of clauses, one for each where clause. | |
829 | for qwc in &where_clauses { | |
830 | builder.push_binders(qwc, |builder, wc| { | |
831 | builder.push_clause( | |
832 | wc.into_from_env_goal(interner), | |
833 | Some(FromEnv::Ty(app_ty.clone())), | |
834 | ); | |
835 | }); | |
836 | } | |
837 | ||
838 | // Reverse rule for implied bounds. | |
839 | // | |
840 | // forall<Self> { | |
841 | // FromEnv(<Self as Foo>::Assoc: Bounds) :- FromEnv(Self: Foo), WC | |
842 | // } | |
843 | for quantified_bound in &bounds { | |
844 | builder.push_binders(quantified_bound, |builder, bound| { | |
845 | for wc in bound.into_where_clauses(interner, projection_ty.clone()) { | |
846 | builder.push_clause( | |
847 | wc.into_from_env_goal(interner), | |
848 | iter::once(FromEnv::Trait(trait_ref.clone()).cast::<Goal<_>>(interner)) | |
849 | .chain(where_clauses.iter().cloned().casted(interner)), | |
850 | ); | |
851 | } | |
852 | }); | |
853 | } | |
854 | ||
855 | // add new type parameter U | |
856 | builder.push_bound_ty(|builder, ty| { | |
857 | // `Normalize(<T as Foo>::Assoc -> U)` | |
858 | let normalize = Normalize { | |
859 | alias: AliasTy::Projection(projection.clone()), | |
860 | ty: ty.clone(), | |
861 | }; | |
862 | ||
863 | // `AliasEq(<T as Foo>::Assoc = U)` | |
864 | let projection_eq = AliasEq { | |
865 | alias: AliasTy::Projection(projection), | |
866 | ty, | |
867 | }; | |
868 | ||
869 | // Projection equality rule from above. | |
870 | // | |
871 | // forall<T, U> { | |
872 | // AliasEq(<T as Foo>::Assoc = U) :- | |
873 | // Normalize(<T as Foo>::Assoc -> U). | |
874 | // } | |
875 | builder.push_clause(projection_eq, Some(normalize)); | |
876 | }); | |
877 | }); | |
878 | } | |
879 | } |