]> git.proxmox.com Git - rustc.git/blame - vendor/chalk-solve/src/clauses.rs
New upstream version 1.48.0~beta.8+dfsg1
[rustc.git] / vendor / chalk-solve / src / clauses.rs
CommitLineData
f9f354fc
XL
1use self::builder::ClauseBuilder;
2use self::env_elaborator::elaborate_env_clauses;
3use self::program_clauses::ToProgramClauses;
4use crate::split::Split;
5use crate::RustIrDatabase;
3dfed10e 6use chalk_ir::cast::{Cast, Caster};
f9f354fc
XL
7use chalk_ir::could_match::CouldMatch;
8use chalk_ir::interner::Interner;
9use chalk_ir::*;
10use rustc_hash::FxHashSet;
3dfed10e 11use std::iter;
f035d41b 12use tracing::{debug, instrument};
f9f354fc
XL
13
14pub mod builder;
15mod builtin_traits;
f035d41b 16mod dyn_ty;
f9f354fc
XL
17mod env_elaborator;
18mod generalize;
19pub mod program_clauses;
20
1b1a35ee
XL
21// yields the types "contained" in `app_ty`
22fn constituent_types<I: Interner>(
23 db: &dyn RustIrDatabase<I>,
24 app_ty: &ApplicationTy<I>,
25) -> Vec<Ty<I>> {
26 let interner = db.interner();
27
28 match app_ty.name {
29 // For non-phantom_data adts we collect its variants/fields
30 TypeName::Adt(adt_id) if !db.adt_datum(adt_id).flags.phantom_data => {
31 let adt_datum = &db.adt_datum(adt_id);
32 let adt_datum_bound = adt_datum.binders.substitute(interner, &app_ty.substitution);
33 adt_datum_bound
34 .variants
35 .into_iter()
36 .flat_map(|variant| variant.fields.into_iter())
37 .collect()
38 }
39 // And for `PhantomData<T>`, we pass `T`.
40 TypeName::Adt(_)
41 | TypeName::Array
42 | TypeName::Tuple(_)
43 | TypeName::Slice
44 | TypeName::Raw(_)
45 | TypeName::Ref(_)
46 | TypeName::Scalar(_)
47 | TypeName::Str
48 | TypeName::Never
49 | TypeName::FnDef(_) => app_ty
50 .substitution
51 .iter(interner)
52 .filter_map(|x| x.ty(interner))
53 .cloned()
54 .collect(),
55
56 TypeName::Closure(_) => panic!("this function should not be called for closures"),
57 TypeName::Foreign(_) => panic!("constituent_types of foreign types are unknown!"),
58 TypeName::Error => Vec::new(),
59 TypeName::OpaqueType(_) => unimplemented!(),
60 TypeName::AssociatedType(_) => unimplemented!(),
61 }
62}
63
3dfed10e 64/// FIXME(#505) update comments for ADTs
f9f354fc
XL
65/// For auto-traits, we generate a default rule for every struct,
66/// unless there is a manual impl for that struct given explicitly.
67///
68/// So, if you have `impl Send for MyList<Foo>`, then we would
69/// generate no rule for `MyList` at all -- similarly if you have
70/// `impl !Send for MyList<Foo>`, or `impl<T> Send for MyList<T>`.
71///
72/// But if you have no rules at all for `Send` / `MyList`, then we
73/// generate an impl based on the field types of `MyList`. For example
74/// given the following program:
75///
76/// ```notrust
77/// #[auto] trait Send { }
78///
79/// struct MyList<T> {
80/// data: T,
81/// next: Box<Option<MyList<T>>>,
82/// }
83///
84/// ```
85///
86/// we generate:
87///
88/// ```notrust
89/// forall<T> {
90/// Implemented(MyList<T>: Send) :-
91/// Implemented(T: Send),
92/// Implemented(Box<Option<MyList<T>>>: Send).
93/// }
94/// ```
f035d41b 95#[instrument(level = "debug", skip(builder))]
f9f354fc
XL
96pub fn push_auto_trait_impls<I: Interner>(
97 builder: &mut ClauseBuilder<'_, I>,
98 auto_trait_id: TraitId<I>,
1b1a35ee 99 app_ty: &ApplicationTy<I>,
f9f354fc 100) {
f9f354fc
XL
101 let interner = builder.interner();
102
103 // Must be an auto trait.
104 assert!(builder.db.trait_datum(auto_trait_id).is_auto_trait());
105
106 // Auto traits never have generic parameters of their own (apart from `Self`).
107 assert_eq!(
108 builder.db.trait_datum(auto_trait_id).binders.len(interner),
109 1
110 );
111
1b1a35ee
XL
112 // we assume that the builder has no binders so far.
113 assert!(builder.placeholders_in_scope().is_empty());
114
f9f354fc 115 // If there is a `impl AutoTrait for Foo<..>` or `impl !AutoTrait
f035d41b 116 // for Foo<..>`, where `Foo` is the adt we're looking at, then
f9f354fc 117 // we don't generate our own rules.
1b1a35ee 118 if builder.db.impl_provided_for(auto_trait_id, app_ty) {
f9f354fc
XL
119 debug!("impl provided");
120 return;
121 }
122
1b1a35ee
XL
123 let mk_ref = |ty: Ty<I>| TraitRef {
124 trait_id: auto_trait_id,
125 substitution: Substitution::from1(interner, ty.cast(interner)),
126 };
127
128 let consequence = mk_ref(app_ty.clone().intern(interner));
129
130 match app_ty.name {
131 // auto traits are not implemented for foreign types
132 TypeName::Foreign(_) => return,
133
134 // closures require binders, while the other types do not
135 TypeName::Closure(closure_id) => {
136 let binders = builder
137 .db
138 .closure_upvars(closure_id, &Substitution::empty(interner));
139 builder.push_binders(&binders, |builder, upvar_ty| {
140 let conditions = iter::once(mk_ref(upvar_ty));
141 builder.push_clause(consequence, conditions);
142 });
f9f354fc 143 }
f9f354fc 144
1b1a35ee
XL
145 // app_ty implements AutoTrait if all constituents of app_ty implement AutoTrait
146 _ => {
147 let conditions = constituent_types(builder.db, app_ty)
148 .into_iter()
149 .map(mk_ref);
f9f354fc 150
1b1a35ee
XL
151 builder.push_clause(consequence, conditions);
152 }
153 }
f9f354fc
XL
154}
155
f035d41b
XL
156/// Leak auto traits for opaque types, just like `push_auto_trait_impls` does for structs.
157///
158/// For example, given the following program:
159///
160/// ```notrust
161/// #[auto] trait Send { }
162/// trait Trait { }
163/// struct Bar { }
164/// opaque type Foo: Trait = Bar
165/// ```
166/// Checking the goal `Foo: Send` would generate the following:
167///
168/// ```notrust
169/// Foo: Send :- Bar: Send
170/// ```
171#[instrument(level = "debug", skip(builder))]
172pub fn push_auto_trait_impls_opaque<I: Interner>(
173 builder: &mut ClauseBuilder<'_, I>,
174 auto_trait_id: TraitId<I>,
175 opaque_id: OpaqueTyId<I>,
176) {
177 let opaque_ty_datum = &builder.db.opaque_ty_data(opaque_id);
178 let interner = builder.interner();
179
180 // Must be an auto trait.
181 assert!(builder.db.trait_datum(auto_trait_id).is_auto_trait());
182
183 // Auto traits never have generic parameters of their own (apart from `Self`).
184 assert_eq!(
185 builder.db.trait_datum(auto_trait_id).binders.len(interner),
186 1
187 );
188
189 let hidden_ty = builder.db.hidden_opaque_type(opaque_id);
190 let binders = opaque_ty_datum.bound.clone();
191 builder.push_binders(&binders, |builder, _| {
192 let self_ty: Ty<_> = ApplicationTy {
193 name: opaque_id.cast(interner),
194 substitution: builder.substitution_in_scope(),
195 }
196 .intern(interner);
197
198 // trait_ref = `OpaqueType<...>: MyAutoTrait`
199 let auto_trait_ref = TraitRef {
200 trait_id: auto_trait_id,
201 substitution: Substitution::from1(interner, self_ty),
202 };
203
204 // OpaqueType<...>: MyAutoTrait :- HiddenType: MyAutoTrait
205 builder.push_clause(
206 auto_trait_ref,
207 std::iter::once(TraitRef {
208 trait_id: auto_trait_id,
209 substitution: Substitution::from1(interner, hidden_ty.clone()),
210 }),
211 );
212 });
213}
214
f9f354fc
XL
215/// Given some goal `goal` that must be proven, along with
216/// its `environment`, figures out the program clauses that apply
217/// to this goal from the Rust program. So for example if the goal
218/// is `Implemented(T: Clone)`, then this function might return clauses
219/// derived from the trait `Clone` and its impls.
f035d41b 220#[instrument(level = "debug", skip(db))]
3dfed10e 221pub fn program_clauses_for_goal<'db, I: Interner>(
f9f354fc
XL
222 db: &'db dyn RustIrDatabase<I>,
223 environment: &Environment<I>,
224 goal: &DomainGoal<I>,
3dfed10e 225 binders: &CanonicalVarKinds<I>,
f9f354fc 226) -> Result<Vec<ProgramClause<I>>, Floundered> {
f9f354fc
XL
227 let interner = db.interner();
228
f035d41b 229 let custom_clauses = db.custom_clauses().into_iter();
3dfed10e
XL
230 let clauses_that_could_match = program_clauses_that_could_match(db, environment, goal, binders)
231 .map(|cl| cl.into_iter())?;
f035d41b
XL
232
233 let clauses: Vec<ProgramClause<I>> = custom_clauses
234 .chain(clauses_that_could_match)
235 .chain(
236 db.program_clauses_for_env(environment)
237 .iter(interner)
238 .cloned(),
239 )
240 .filter(|c| c.could_match(interner, goal))
241 .collect();
f9f354fc 242
3dfed10e 243 debug!(?clauses);
f9f354fc 244
f035d41b 245 Ok(clauses)
f9f354fc
XL
246}
247
248/// Returns a set of program clauses that could possibly match
249/// `goal`. This can be any superset of the correct set, but the
250/// more precise you can make it, the more efficient solving will
251/// be.
f035d41b 252#[instrument(level = "debug", skip(db, environment))]
f9f354fc
XL
253fn program_clauses_that_could_match<I: Interner>(
254 db: &dyn RustIrDatabase<I>,
255 environment: &Environment<I>,
256 goal: &DomainGoal<I>,
3dfed10e
XL
257 // FIXME: These are the binders for `goal`. We're passing them separately
258 // because `goal` is not necessarily canonicalized: The recursive solver
259 // passes the canonical goal; the SLG solver instantiates the goal first.
260 // (See #568.)
261 binders: &CanonicalVarKinds<I>,
f035d41b 262) -> Result<Vec<ProgramClause<I>>, Floundered> {
f9f354fc 263 let interner = db.interner();
f035d41b
XL
264 let mut clauses: Vec<ProgramClause<I>> = vec![];
265 let builder = &mut ClauseBuilder::new(db, &mut clauses);
f9f354fc
XL
266
267 match goal {
268 DomainGoal::Holds(WhereClause::Implemented(trait_ref)) => {
269 let trait_id = trait_ref.trait_id;
270
271 let trait_datum = db.trait_datum(trait_id);
272
273 if trait_datum.is_non_enumerable_trait() || trait_datum.is_auto_trait() {
274 let self_ty = trait_ref.self_type_parameter(interner);
f035d41b
XL
275
276 if let TyData::Alias(AliasTy::Opaque(opaque_ty)) = self_ty.data(interner) {
277 if trait_datum.is_auto_trait() {
278 push_auto_trait_impls_opaque(builder, trait_id, opaque_ty.opaque_ty_id)
279 }
3dfed10e 280 } else if self_ty.is_general_var(interner, binders) {
f9f354fc
XL
281 return Err(Floundered);
282 }
283 }
284
285 // This is needed for the coherence related impls, as well
286 // as for the `Implemented(Foo) :- FromEnv(Foo)` rule.
3dfed10e 287 trait_datum.to_program_clauses(builder, environment);
f9f354fc
XL
288
289 for impl_id in db.impls_for_trait(
290 trait_ref.trait_id,
3dfed10e
XL
291 trait_ref.substitution.as_slice(interner),
292 binders,
f9f354fc 293 ) {
3dfed10e
XL
294 db.impl_datum(impl_id)
295 .to_program_clauses(builder, environment);
f9f354fc
XL
296 }
297
298 // If this is a `Foo: Send` (or any auto-trait), then add
299 // the automatic impls for `Foo`.
300 let trait_datum = db.trait_datum(trait_id);
301 if trait_datum.is_auto_trait() {
1b1a35ee
XL
302 let ty = trait_ref.self_type_parameter(interner);
303 match ty.data(interner) {
304 TyData::Apply(apply) => {
305 push_auto_trait_impls(builder, trait_id, apply);
306 }
307 // function-types implement auto traits unconditionally
308 TyData::Function(_) => {
309 let auto_trait_ref = TraitRef {
310 trait_id,
311 substitution: Substitution::from1(interner, ty.cast(interner)),
312 };
313
314 builder.push_fact(auto_trait_ref);
315 }
f035d41b 316 TyData::InferenceVar(_, _) | TyData::BoundVar(_) => {
f9f354fc
XL
317 return Err(Floundered);
318 }
319 _ => {}
320 }
321 }
322
f035d41b
XL
323 // If the self type is a `dyn trait` type, generate program-clauses
324 // that indicates that it implements its own traits.
325 // FIXME: This is presently rather wasteful, in that we don't check that the
326 // these program clauses we are generating are actually relevant to the goal
327 // `goal` that we are actually *trying* to prove (though there is some later
328 // code that will screen out irrelevant stuff).
f9f354fc 329 //
f035d41b
XL
330 // In other words, if we were trying to prove `Implemented(dyn
331 // Fn(&u8): Clone)`, we would still generate two clauses that are
332 // totally irrelevant to that goal, because they let us prove other
333 // things but not `Clone`.
f9f354fc 334 let self_ty = trait_ref.self_type_parameter(interner);
f035d41b
XL
335 if let TyData::Dyn(_) = self_ty.data(interner) {
336 dyn_ty::build_dyn_self_ty_clauses(db, builder, self_ty.clone())
f9f354fc
XL
337 }
338
339 match self_ty.data(interner) {
340 TyData::Apply(ApplicationTy {
341 name: TypeName::OpaqueType(opaque_ty_id),
342 ..
343 })
344 | TyData::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id, .. })) => {
3dfed10e
XL
345 db.opaque_ty_data(*opaque_ty_id)
346 .to_program_clauses(builder, environment);
347 }
348 _ => {}
349 }
350
351 // We don't actually do anything here, but we need to record the types it when logging
352 match self_ty.data(interner) {
353 TyData::Apply(ApplicationTy {
354 name: TypeName::Adt(adt_id),
355 ..
356 }) => {
357 let _ = db.adt_datum(*adt_id);
358 }
359 TyData::Apply(ApplicationTy {
360 name: TypeName::FnDef(fn_def_id),
361 ..
362 }) => {
363 let _ = db.fn_def_datum(*fn_def_id);
f9f354fc
XL
364 }
365 _ => {}
366 }
367
368 if let Some(well_known) = trait_datum.well_known {
3dfed10e
XL
369 builtin_traits::add_builtin_program_clauses(
370 db, builder, well_known, trait_ref, binders,
371 )?;
f9f354fc
XL
372 }
373 }
374 DomainGoal::Holds(WhereClause::AliasEq(alias_eq)) => match &alias_eq.alias {
f035d41b
XL
375 AliasTy::Projection(proj) => {
376 let trait_self_ty = db
377 .trait_ref_from_projection(proj)
378 .self_type_parameter(interner);
379
380 match trait_self_ty.data(interner) {
381 TyData::Apply(ApplicationTy {
382 name: TypeName::OpaqueType(opaque_ty_id),
383 ..
384 })
385 | TyData::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id, .. })) => {
3dfed10e
XL
386 db.opaque_ty_data(*opaque_ty_id)
387 .to_program_clauses(builder, environment);
f035d41b
XL
388 }
389 _ => {}
390 }
391
3dfed10e
XL
392 // If the self type is a `dyn trait` type, generate program-clauses
393 // for any associated type bindings it contains.
394 // FIXME: see the fixme for the analogous code for Implemented goals.
395 if let TyData::Dyn(_) = trait_self_ty.data(interner) {
396 dyn_ty::build_dyn_self_ty_clauses(db, builder, trait_self_ty.clone())
397 }
398
f035d41b 399 db.associated_ty_data(proj.associated_ty_id)
3dfed10e 400 .to_program_clauses(builder, environment)
f035d41b 401 }
f9f354fc
XL
402 AliasTy::Opaque(opaque_ty) => db
403 .opaque_ty_data(opaque_ty.opaque_ty_id)
3dfed10e 404 .to_program_clauses(builder, environment),
f9f354fc 405 },
3dfed10e
XL
406 DomainGoal::Holds(WhereClause::LifetimeOutlives(..)) => {
407 builder.push_bound_lifetime(|builder, a| {
408 builder.push_bound_lifetime(|builder, b| {
409 builder.push_fact_with_constraints(
410 DomainGoal::Holds(WhereClause::LifetimeOutlives(LifetimeOutlives {
411 a: a.clone(),
412 b: b.clone(),
413 })),
414 Some(InEnvironment::new(
415 environment,
416 Constraint::LifetimeOutlives(a, b),
417 )),
418 );
419 })
420 });
421 }
422 DomainGoal::Holds(WhereClause::TypeOutlives(..)) => {
423 builder.push_bound_ty(|builder, ty| {
424 builder.push_bound_lifetime(|builder, lifetime| {
425 builder.push_fact_with_constraints(
426 DomainGoal::Holds(WhereClause::TypeOutlives(TypeOutlives {
427 ty: ty.clone(),
428 lifetime: lifetime.clone(),
429 })),
430 Some(InEnvironment::new(
431 environment,
432 Constraint::TypeOutlives(ty, lifetime),
433 )),
434 )
435 })
436 });
f035d41b
XL
437 }
438 DomainGoal::WellFormed(WellFormed::Trait(trait_ref))
439 | DomainGoal::LocalImplAllowed(trait_ref) => {
440 db.trait_datum(trait_ref.trait_id)
3dfed10e 441 .to_program_clauses(builder, environment);
f9f354fc 442 }
f035d41b
XL
443 DomainGoal::ObjectSafe(trait_id) => {
444 if builder.db.is_object_safe(*trait_id) {
445 builder.push_fact(DomainGoal::ObjectSafe(*trait_id));
446 }
447 }
f9f354fc
XL
448 DomainGoal::WellFormed(WellFormed::Ty(ty))
449 | DomainGoal::IsUpstream(ty)
f035d41b
XL
450 | DomainGoal::DownstreamType(ty)
451 | DomainGoal::IsFullyVisible(ty)
452 | DomainGoal::IsLocal(ty) => match_ty(builder, environment, ty)?,
f9f354fc
XL
453 DomainGoal::FromEnv(_) => (), // Computed in the environment
454 DomainGoal::Normalize(Normalize { alias, ty: _ }) => match alias {
455 AliasTy::Projection(proj) => {
456 // Normalize goals derive from `AssociatedTyValue` datums,
457 // which are found in impls. That is, if we are
458 // normalizing (e.g.) `<T as Iterator>::Item>`, then
459 // search for impls of iterator and, within those impls,
460 // for associated type values:
461 //
462 // ```ignore
463 // impl Iterator for Foo {
464 // type Item = Bar; // <-- associated type value
465 // }
466 // ```
467 let associated_ty_datum = db.associated_ty_data(proj.associated_ty_id);
468 let trait_id = associated_ty_datum.trait_id;
469 let trait_parameters = db.trait_parameters_from_projection(proj);
470
471 let trait_datum = db.trait_datum(trait_id);
472
f035d41b
XL
473 let self_ty = alias.self_type_parameter(interner);
474
f9f354fc
XL
475 // Flounder if the self-type is unknown and the trait is non-enumerable.
476 //
477 // e.g., Normalize(<?X as Iterator>::Item = u32)
3dfed10e
XL
478 if (self_ty.is_general_var(interner, binders))
479 && trait_datum.is_non_enumerable_trait()
480 {
f9f354fc
XL
481 return Err(Floundered);
482 }
483
f035d41b
XL
484 if let Some(well_known) = trait_datum.well_known {
485 builtin_traits::add_builtin_assoc_program_clauses(
486 db, builder, well_known, self_ty,
487 )?;
488 }
489
f9f354fc
XL
490 push_program_clauses_for_associated_type_values_in_impls_of(
491 builder,
3dfed10e 492 environment,
f9f354fc
XL
493 trait_id,
494 trait_parameters,
3dfed10e 495 binders,
f9f354fc 496 );
3dfed10e
XL
497
498 if environment.has_compatible_clause(interner) {
499 push_clauses_for_compatible_normalize(
500 db,
501 builder,
502 interner,
503 trait_id,
504 proj.associated_ty_id,
505 );
506 }
f9f354fc
XL
507 }
508 AliasTy::Opaque(_) => (),
509 },
3dfed10e 510 DomainGoal::Compatible | DomainGoal::Reveal => (),
f9f354fc
XL
511 };
512
f035d41b 513 Ok(clauses)
f9f354fc
XL
514}
515
3dfed10e
XL
516/// Adds clauses to allow normalizing possible downstream associated type
517/// implementations when in the "compatible" mode. Example clauses:
518///
519/// ```notrust
520/// for<type, type, type> Normalize(<^0.0 as Trait<^0.1>>::Item -> ^0.2)
521/// :- Compatible, Implemented(^0.0: Trait<^0.1>), DownstreamType(^0.1), CannotProve
522/// for<type, type, type> Normalize(<^0.0 as Trait<^0.1>>::Item -> ^0.2)
523/// :- Compatible, Implemented(^0.0: Trait<^0.1>), IsFullyVisible(^0.0), DownstreamType(^0.1), CannotProve
524/// ```
525fn push_clauses_for_compatible_normalize<I: Interner>(
526 db: &dyn RustIrDatabase<I>,
527 builder: &mut ClauseBuilder<'_, I>,
528 interner: &I,
529 trait_id: TraitId<I>,
530 associated_ty_id: AssocTypeId<I>,
531) {
532 let trait_datum = db.trait_datum(trait_id);
533 let trait_binders = trait_datum.binders.map_ref(|b| &b.where_clauses);
534 builder.push_binders(&trait_binders, |builder, where_clauses| {
535 let projection = ProjectionTy {
536 associated_ty_id,
537 substitution: builder.substitution_in_scope(),
538 };
539 let trait_ref = TraitRef {
540 trait_id,
541 substitution: builder.substitution_in_scope(),
542 };
543 let type_parameters: Vec<_> = trait_ref.type_parameters(interner).collect();
544
545 builder.push_bound_ty(|builder, target_ty| {
546 for i in 0..type_parameters.len() {
547 builder.push_clause(
548 DomainGoal::Normalize(Normalize {
549 ty: target_ty.clone(),
550 alias: AliasTy::Projection(projection.clone()),
551 }),
552 where_clauses
553 .iter()
554 .cloned()
555 .casted(interner)
556 .chain(iter::once(DomainGoal::Compatible.cast(interner)))
557 .chain(iter::once(
558 WhereClause::Implemented(trait_ref.clone()).cast(interner),
559 ))
560 .chain((0..i).map(|j| {
561 DomainGoal::IsFullyVisible(type_parameters[j].clone()).cast(interner)
562 }))
563 .chain(iter::once(
564 DomainGoal::DownstreamType(type_parameters[i].clone()).cast(interner),
565 ))
566 .chain(iter::once(GoalData::CannotProve.intern(interner))),
567 );
568 }
569 });
570 });
571}
572
f9f354fc
XL
573/// Generate program clauses from the associated-type values
574/// found in impls of the given trait. i.e., if `trait_id` = Iterator,
575/// then we would generate program clauses from each `type Item = ...`
576/// found in any impls of `Iterator`:
577/// which are found in impls. That is, if we are
578/// normalizing (e.g.) `<T as Iterator>::Item>`, then
579/// search for impls of iterator and, within those impls,
580/// for associated type values:
581///
582/// ```ignore
583/// impl Iterator for Foo {
584/// type Item = Bar; // <-- associated type value
585/// }
586/// ```
f035d41b 587#[instrument(level = "debug", skip(builder))]
f9f354fc
XL
588fn push_program_clauses_for_associated_type_values_in_impls_of<I: Interner>(
589 builder: &mut ClauseBuilder<'_, I>,
3dfed10e 590 environment: &Environment<I>,
f9f354fc 591 trait_id: TraitId<I>,
f035d41b 592 trait_parameters: &[GenericArg<I>],
3dfed10e 593 binders: &CanonicalVarKinds<I>,
f9f354fc 594) {
3dfed10e
XL
595 for impl_id in builder
596 .db
597 .impls_for_trait(trait_id, trait_parameters, binders)
598 {
f9f354fc
XL
599 let impl_datum = builder.db.impl_datum(impl_id);
600 if !impl_datum.is_positive() {
601 continue;
602 }
603
3dfed10e 604 debug!(?impl_id);
f9f354fc
XL
605
606 for &atv_id in &impl_datum.associated_ty_value_ids {
607 let atv = builder.db.associated_ty_value(atv_id);
3dfed10e
XL
608 debug!(?atv_id, ?atv);
609 atv.to_program_clauses(builder, environment);
f9f354fc
XL
610 }
611 }
612}
613
614/// Examine `T` and push clauses that may be relevant to proving the
615/// following sorts of goals (and maybe others):
616///
617/// * `DomainGoal::WellFormed(T)`
618/// * `DomainGoal::IsUpstream(T)`
619/// * `DomainGoal::DownstreamType(T)`
620/// * `DomainGoal::IsFullyVisible(T)`
621/// * `DomainGoal::IsLocal(T)`
622///
623/// Note that the type `T` must not be an unbound inference variable;
624/// earlier parts of the logic should "flounder" in that case.
625fn match_ty<I: Interner>(
626 builder: &mut ClauseBuilder<'_, I>,
627 environment: &Environment<I>,
628 ty: &Ty<I>,
629) -> Result<(), Floundered> {
630 let interner = builder.interner();
631 Ok(match ty.data(interner) {
3dfed10e 632 TyData::Apply(application_ty) => match_type_name(builder, environment, application_ty),
f9f354fc
XL
633 TyData::Placeholder(_) => {
634 builder.push_clause(WellFormed::Ty(ty.clone()), Some(FromEnv::Ty(ty.clone())));
635 }
636 TyData::Alias(AliasTy::Projection(proj)) => builder
637 .db
638 .associated_ty_data(proj.associated_ty_id)
3dfed10e 639 .to_program_clauses(builder, environment),
f9f354fc
XL
640 TyData::Alias(AliasTy::Opaque(opaque_ty)) => builder
641 .db
642 .opaque_ty_data(opaque_ty.opaque_ty_id)
3dfed10e 643 .to_program_clauses(builder, environment),
f9f354fc
XL
644 TyData::Function(quantified_ty) => {
645 builder.push_fact(WellFormed::Ty(ty.clone()));
646 quantified_ty
647 .substitution
648 .iter(interner)
649 .map(|p| p.assert_ty_ref(interner))
650 .map(|ty| match_ty(builder, environment, &ty))
651 .collect::<Result<_, Floundered>>()?;
652 }
f035d41b 653 TyData::BoundVar(_) | TyData::InferenceVar(_, _) => return Err(Floundered),
f9f354fc
XL
654 TyData::Dyn(_) => {}
655 })
656}
657
f035d41b 658/// Lower a Rust IR application type to logic
f9f354fc
XL
659fn match_type_name<I: Interner>(
660 builder: &mut ClauseBuilder<'_, I>,
3dfed10e 661 environment: &Environment<I>,
f9f354fc
XL
662 application: &ApplicationTy<I>,
663) {
3dfed10e 664 let interner = builder.interner();
f9f354fc 665 match application.name {
3dfed10e
XL
666 TypeName::Adt(adt_id) => builder
667 .db
668 .adt_datum(adt_id)
669 .to_program_clauses(builder, environment),
f9f354fc
XL
670 TypeName::OpaqueType(opaque_ty_id) => builder
671 .db
672 .opaque_ty_data(opaque_ty_id)
3dfed10e 673 .to_program_clauses(builder, environment),
f9f354fc
XL
674 TypeName::Error => {}
675 TypeName::AssociatedType(type_id) => builder
676 .db
677 .associated_ty_data(type_id)
3dfed10e 678 .to_program_clauses(builder, environment),
f035d41b
XL
679 TypeName::FnDef(fn_def_id) => builder
680 .db
681 .fn_def_datum(fn_def_id)
3dfed10e 682 .to_program_clauses(builder, environment),
f035d41b
XL
683 TypeName::Tuple(_)
684 | TypeName::Scalar(_)
685 | TypeName::Str
686 | TypeName::Slice
687 | TypeName::Raw(_)
688 | TypeName::Ref(_)
689 | TypeName::Array
690 | TypeName::Never
1b1a35ee
XL
691 | TypeName::Closure(_)
692 | TypeName::Foreign(_) => {
f9f354fc
XL
693 builder.push_fact(WellFormed::Ty(application.clone().intern(interner)))
694 }
695 }
696}
697
3dfed10e
XL
698fn match_alias_ty<I: Interner>(
699 builder: &mut ClauseBuilder<'_, I>,
700 environment: &Environment<I>,
701 alias: &AliasTy<I>,
702) {
f9f354fc
XL
703 match alias {
704 AliasTy::Projection(projection_ty) => builder
705 .db
706 .associated_ty_data(projection_ty.associated_ty_id)
3dfed10e 707 .to_program_clauses(builder, environment),
f9f354fc
XL
708 _ => (),
709 }
710}
711
f9f354fc
XL
712pub fn program_clauses_for_env<'db, I: Interner>(
713 db: &'db dyn RustIrDatabase<I>,
714 environment: &Environment<I>,
715) -> ProgramClauses<I> {
716 let mut last_round = environment
717 .clauses
718 .as_slice(db.interner())
719 .iter()
720 .cloned()
721 .collect::<FxHashSet<_>>();
722 let mut closure = last_round.clone();
723 let mut next_round = FxHashSet::default();
724 while !last_round.is_empty() {
3dfed10e
XL
725 elaborate_env_clauses(
726 db,
727 &last_round.drain().collect::<Vec<_>>(),
728 &mut next_round,
729 environment,
730 );
f9f354fc
XL
731 last_round.extend(
732 next_round
733 .drain()
734 .filter(|clause| closure.insert(clause.clone())),
735 );
736 }
737
3dfed10e 738 ProgramClauses::from_iter(db.interner(), closure)
f9f354fc 739}