chalk_solve/
wf.rs

1use std::ops::ControlFlow;
2use std::{fmt, iter};
3
4use crate::{
5    ext::*, goal_builder::GoalBuilder, rust_ir::*, solve::Solver, split::Split, RustIrDatabase,
6};
7use chalk_ir::{
8    cast::*,
9    fold::shift::Shift,
10    interner::Interner,
11    visit::{TypeVisitable, TypeVisitor},
12    *,
13};
14use tracing::debug;
15
16#[derive(Debug)]
17pub enum WfError<I: Interner> {
18    IllFormedTypeDecl(chalk_ir::AdtId<I>),
19    IllFormedOpaqueTypeDecl(chalk_ir::OpaqueTyId<I>),
20    IllFormedTraitImpl(chalk_ir::TraitId<I>),
21}
22
23impl<I: Interner> fmt::Display for WfError<I> {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        match self {
26            WfError::IllFormedTypeDecl(id) => write!(
27                f,
28                "type declaration `{:?}` does not meet well-formedness requirements",
29                id
30            ),
31            WfError::IllFormedOpaqueTypeDecl(id) => write!(
32                f,
33                "opaque type declaration `{:?}` does not meet well-formedness requirements",
34                id
35            ),
36            WfError::IllFormedTraitImpl(id) => write!(
37                f,
38                "trait impl for `{:?}` does not meet well-formedness requirements",
39                id
40            ),
41        }
42    }
43}
44
45impl<I: Interner> std::error::Error for WfError<I> {}
46
47pub struct WfSolver<'a, I: Interner> {
48    db: &'a dyn RustIrDatabase<I>,
49    solver_builder: &'a dyn Fn() -> Box<dyn Solver<I>>,
50}
51
52struct InputTypeCollector<I: Interner> {
53    types: Vec<Ty<I>>,
54    interner: I,
55}
56
57impl<I: Interner> InputTypeCollector<I> {
58    fn new(interner: I) -> Self {
59        Self {
60            types: Vec::new(),
61            interner,
62        }
63    }
64
65    fn types_in(interner: I, value: impl TypeVisitable<I>) -> Vec<Ty<I>> {
66        let mut collector = Self::new(interner);
67        value.visit_with(&mut collector, DebruijnIndex::INNERMOST);
68        collector.types
69    }
70}
71
72impl<I: Interner> TypeVisitor<I> for InputTypeCollector<I> {
73    type BreakTy = ();
74    fn as_dyn(&mut self) -> &mut dyn TypeVisitor<I, BreakTy = Self::BreakTy> {
75        self
76    }
77
78    fn interner(&self) -> I {
79        self.interner
80    }
81
82    fn visit_where_clause(
83        &mut self,
84        where_clause: &WhereClause<I>,
85        outer_binder: DebruijnIndex,
86    ) -> ControlFlow<()> {
87        match where_clause {
88            WhereClause::AliasEq(alias_eq) => alias_eq
89                .alias
90                .clone()
91                .intern(self.interner)
92                .visit_with(self, outer_binder),
93            WhereClause::Implemented(trait_ref) => trait_ref.visit_with(self, outer_binder),
94            WhereClause::TypeOutlives(TypeOutlives { ty, .. }) => ty.visit_with(self, outer_binder),
95            WhereClause::LifetimeOutlives(..) => ControlFlow::Continue(()),
96        }
97    }
98
99    fn visit_ty(&mut self, ty: &Ty<I>, outer_binder: DebruijnIndex) -> ControlFlow<()> {
100        let interner = self.interner();
101
102        let mut push_ty = || {
103            self.types
104                .push(ty.clone().shifted_out_to(interner, outer_binder).unwrap())
105        };
106        match ty.kind(interner) {
107            TyKind::Adt(id, substitution) => {
108                push_ty();
109                id.visit_with(self, outer_binder);
110                substitution.visit_with(self, outer_binder)
111            }
112            TyKind::AssociatedType(assoc_ty, substitution) => {
113                push_ty();
114                assoc_ty.visit_with(self, outer_binder);
115                substitution.visit_with(self, outer_binder)
116            }
117            TyKind::Scalar(scalar) => {
118                push_ty();
119                scalar.visit_with(self, outer_binder)
120            }
121            TyKind::Str => {
122                push_ty();
123                ControlFlow::Continue(())
124            }
125            TyKind::Tuple(arity, substitution) => {
126                push_ty();
127                arity.visit_with(self, outer_binder);
128                substitution.visit_with(self, outer_binder)
129            }
130            TyKind::OpaqueType(opaque_ty, substitution) => {
131                push_ty();
132                opaque_ty.visit_with(self, outer_binder);
133                substitution.visit_with(self, outer_binder)
134            }
135            TyKind::Slice(substitution) => {
136                push_ty();
137                substitution.visit_with(self, outer_binder)
138            }
139            TyKind::FnDef(fn_def, substitution) => {
140                push_ty();
141                fn_def.visit_with(self, outer_binder);
142                substitution.visit_with(self, outer_binder)
143            }
144            TyKind::Ref(mutability, lifetime, ty) => {
145                push_ty();
146                mutability.visit_with(self, outer_binder);
147                lifetime.visit_with(self, outer_binder);
148                ty.visit_with(self, outer_binder)
149            }
150            TyKind::Raw(mutability, substitution) => {
151                push_ty();
152                mutability.visit_with(self, outer_binder);
153                substitution.visit_with(self, outer_binder)
154            }
155            TyKind::Never => {
156                push_ty();
157                ControlFlow::Continue(())
158            }
159            TyKind::Array(ty, const_) => {
160                push_ty();
161                ty.visit_with(self, outer_binder);
162                const_.visit_with(self, outer_binder)
163            }
164            TyKind::Closure(_id, substitution) => {
165                push_ty();
166                substitution.visit_with(self, outer_binder)
167            }
168            TyKind::Coroutine(_coroutine, substitution) => {
169                push_ty();
170                substitution.visit_with(self, outer_binder)
171            }
172            TyKind::CoroutineWitness(_witness, substitution) => {
173                push_ty();
174                substitution.visit_with(self, outer_binder)
175            }
176            TyKind::Foreign(_foreign_ty) => {
177                push_ty();
178                ControlFlow::Continue(())
179            }
180            TyKind::Error => {
181                push_ty();
182                ControlFlow::Continue(())
183            }
184
185            TyKind::Dyn(clauses) => {
186                push_ty();
187                clauses.visit_with(self, outer_binder)
188            }
189
190            TyKind::Alias(AliasTy::Projection(proj)) => {
191                push_ty();
192                proj.visit_with(self, outer_binder)
193            }
194
195            TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
196                push_ty();
197                opaque_ty.visit_with(self, outer_binder)
198            }
199
200            TyKind::Placeholder(_) => {
201                push_ty();
202                ControlFlow::Continue(())
203            }
204
205            // Type parameters do not carry any input types (so we can sort of assume they are
206            // always WF).
207            TyKind::BoundVar(..) => ControlFlow::Continue(()),
208
209            // Higher-kinded types such as `for<'a> fn(&'a u32)` introduce their own implied
210            // bounds, and these bounds will be enforced upon calling such a function. In some
211            // sense, well-formedness requirements for the input types of an HKT will be enforced
212            // lazily, so no need to include them here.
213            TyKind::Function(..) => ControlFlow::Continue(()),
214
215            TyKind::InferenceVar(..) => {
216                panic!("unexpected inference variable in wf rules: {:?}", ty)
217            }
218        }
219    }
220}
221
222impl<'a, I> WfSolver<'a, I>
223where
224    I: Interner,
225{
226    /// Constructs a new `WfSolver`.
227    pub fn new(
228        db: &'a dyn RustIrDatabase<I>,
229        solver_builder: &'a dyn Fn() -> Box<dyn Solver<I>>,
230    ) -> Self {
231        Self { db, solver_builder }
232    }
233
234    pub fn verify_adt_decl(&self, adt_id: AdtId<I>) -> Result<(), WfError<I>> {
235        let interner = self.db.interner();
236
237        // Given a struct like
238        //
239        // ```rust
240        // struct Foo<T> where T: Eq {
241        //     data: Vec<T>
242        // }
243        // ```
244        let adt_datum = self.db.adt_datum(adt_id);
245        let is_enum = adt_datum.kind == AdtKind::Enum;
246
247        let mut gb = GoalBuilder::new(self.db);
248        let adt_data = adt_datum
249            .binders
250            .map_ref(|b| (&b.variants, &b.where_clauses));
251
252        // We make a goal like...
253        //
254        // forall<T> { ... }
255        let wg_goal = gb.forall(
256            &adt_data,
257            is_enum,
258            |gb, _, (variants, where_clauses), is_enum| {
259                let interner = gb.interner();
260
261                // (FromEnv(T: Eq) => ...)
262                gb.implies(
263                    where_clauses
264                        .iter()
265                        .cloned()
266                        .map(|wc| wc.into_from_env_goal(interner)),
267                    |gb| {
268                        let sub_goals: Vec<_> = variants
269                            .iter()
270                            .flat_map(|variant| {
271                                let fields = &variant.fields;
272
273                                // When checking if Enum is well-formed, we require that all fields of
274                                // each variant are sized. For `structs`, we relax this requirement to
275                                // all but the last field.
276                                let sized_constraint_goal =
277                                    WfWellKnownConstraints::struct_sized_constraint(
278                                        gb.db(),
279                                        fields,
280                                        is_enum,
281                                    );
282
283                                // WellFormed(Vec<T>), for each field type `Vec<T>` or type that appears in the where clauses
284                                let types = InputTypeCollector::types_in(
285                                    gb.interner(),
286                                    (&fields, &where_clauses),
287                                );
288
289                                types
290                                    .into_iter()
291                                    .map(|ty| ty.well_formed().cast(interner))
292                                    .chain(sized_constraint_goal.into_iter())
293                            })
294                            .collect();
295
296                        gb.all(sub_goals)
297                    },
298                )
299            },
300        );
301
302        let wg_goal = wg_goal.into_closed_goal(interner);
303        let mut fresh_solver = (self.solver_builder)();
304        let is_legal = fresh_solver.has_unique_solution(self.db, &wg_goal);
305
306        if !is_legal {
307            Err(WfError::IllFormedTypeDecl(adt_id))
308        } else {
309            Ok(())
310        }
311    }
312
313    pub fn verify_trait_impl(&self, impl_id: ImplId<I>) -> Result<(), WfError<I>> {
314        let interner = self.db.interner();
315
316        let impl_datum = self.db.impl_datum(impl_id);
317        let trait_id = impl_datum.trait_id();
318
319        let impl_goal = Goal::all(
320            interner,
321            impl_header_wf_goal(self.db, impl_id).into_iter().chain(
322                impl_datum
323                    .associated_ty_value_ids
324                    .iter()
325                    .filter_map(|&id| compute_assoc_ty_goal(self.db, id)),
326            ),
327        );
328
329        if let Some(well_known) = self.db.trait_datum(trait_id).well_known {
330            self.verify_well_known_impl(impl_id, well_known)?
331        }
332
333        debug!("WF trait goal: {:?}", impl_goal);
334
335        let mut fresh_solver = (self.solver_builder)();
336        let is_legal =
337            fresh_solver.has_unique_solution(self.db, &impl_goal.into_closed_goal(interner));
338
339        if is_legal {
340            Ok(())
341        } else {
342            Err(WfError::IllFormedTraitImpl(trait_id))
343        }
344    }
345
346    pub fn verify_opaque_ty_decl(&self, opaque_ty_id: OpaqueTyId<I>) -> Result<(), WfError<I>> {
347        // Given an opaque type like
348        // ```notrust
349        // opaque type Foo<T>: Clone where T: Bar = Baz;
350        // ```
351        let interner = self.db.interner();
352
353        let mut gb = GoalBuilder::new(self.db);
354
355        let datum = self.db.opaque_ty_data(opaque_ty_id);
356        let bound = &datum.bound;
357
358        // We make a goal like
359        //
360        // forall<T>
361        let goal = gb.forall(bound, opaque_ty_id, |gb, _, bound, opaque_ty_id| {
362            let interner = gb.interner();
363
364            let subst = Substitution::from1(interner, gb.db().hidden_opaque_type(opaque_ty_id));
365
366            let bounds = bound.bounds.clone().substitute(interner, &subst);
367            let where_clauses = bound.where_clauses.clone().substitute(interner, &subst);
368
369            let clauses = where_clauses
370                .iter()
371                .cloned()
372                .map(|wc| wc.into_from_env_goal(interner));
373
374            // if (WellFormed(T: Bar))
375            gb.implies(clauses, |gb| {
376                let interner = gb.interner();
377
378                // all(WellFormed(Baz: Clone))
379                gb.all(
380                    bounds
381                        .iter()
382                        .cloned()
383                        .map(|b| b.into_well_formed_goal(interner)),
384                )
385            })
386        });
387
388        debug!("WF opaque type goal: {:#?}", goal);
389
390        let mut new_solver = (self.solver_builder)();
391        let is_legal = new_solver.has_unique_solution(self.db, &goal.into_closed_goal(interner));
392
393        if is_legal {
394            Ok(())
395        } else {
396            Err(WfError::IllFormedOpaqueTypeDecl(opaque_ty_id))
397        }
398    }
399
400    /// Verify builtin rules for well-known traits
401    pub fn verify_well_known_impl(
402        &self,
403        impl_id: ImplId<I>,
404        well_known: WellKnownTrait,
405    ) -> Result<(), WfError<I>> {
406        let mut solver = (self.solver_builder)();
407        let impl_datum = self.db.impl_datum(impl_id);
408
409        let is_legal = match well_known {
410            WellKnownTrait::Copy => {
411                WfWellKnownConstraints::copy_impl_constraint(&mut *solver, self.db, &impl_datum)
412            }
413            WellKnownTrait::Drop => {
414                WfWellKnownConstraints::drop_impl_constraint(&mut *solver, self.db, &impl_datum)
415            }
416            WellKnownTrait::CoerceUnsized => {
417                WfWellKnownConstraints::coerce_unsized_impl_constraint(
418                    &mut *solver,
419                    self.db,
420                    &impl_datum,
421                )
422            }
423            WellKnownTrait::DispatchFromDyn => {
424                WfWellKnownConstraints::dispatch_from_dyn_constraint(
425                    &mut *solver,
426                    self.db,
427                    &impl_datum,
428                )
429            }
430            WellKnownTrait::Clone | WellKnownTrait::Unpin | WellKnownTrait::Future => true,
431            // You can't add a manual implementation for the following traits:
432            WellKnownTrait::Fn
433            | WellKnownTrait::FnOnce
434            | WellKnownTrait::FnMut
435            | WellKnownTrait::AsyncFn
436            | WellKnownTrait::AsyncFnOnce
437            | WellKnownTrait::AsyncFnMut
438            | WellKnownTrait::Unsize
439            | WellKnownTrait::Sized
440            | WellKnownTrait::DiscriminantKind
441            | WellKnownTrait::Coroutine
442            | WellKnownTrait::Pointee
443            | WellKnownTrait::Tuple
444            | WellKnownTrait::FnPtr => false,
445        };
446
447        if is_legal {
448            Ok(())
449        } else {
450            Err(WfError::IllFormedTraitImpl(impl_datum.trait_id()))
451        }
452    }
453}
454
455fn impl_header_wf_goal<I: Interner>(
456    db: &dyn RustIrDatabase<I>,
457    impl_id: ImplId<I>,
458) -> Option<Goal<I>> {
459    let impl_datum = db.impl_datum(impl_id);
460
461    if !impl_datum.is_positive() {
462        return None;
463    }
464
465    let impl_fields = impl_datum
466        .binders
467        .map_ref(|v| (&v.trait_ref, &v.where_clauses));
468
469    let mut gb = GoalBuilder::new(db);
470    // forall<P0...Pn> {...}
471    let well_formed_goal = gb.forall(&impl_fields, (), |gb, _, (trait_ref, where_clauses), ()| {
472        let interner = gb.interner();
473
474        // if (WC && input types are well formed) { ... }
475        gb.implies(
476            impl_wf_environment(interner, where_clauses, trait_ref),
477            |gb| {
478                // We retrieve all the input types of the where clauses appearing on the trait impl,
479                // e.g. in:
480                // ```
481                // impl<T, K> Foo for (T, K) where T: Iterator<Item = (HashSet<K>, Vec<Box<T>>)> { ... }
482                // ```
483                // we would retrieve `HashSet<K>`, `Box<T>`, `Vec<Box<T>>`, `(HashSet<K>, Vec<Box<T>>)`.
484                // We will have to prove that these types are well-formed (e.g. an additional `K: Hash`
485                // bound would be needed here).
486                let types = InputTypeCollector::types_in(gb.interner(), &where_clauses);
487
488                // Things to prove well-formed: input types of the where-clauses, projection types
489                // appearing in the header, associated type values, and of course the trait ref.
490                debug!(input_types=?types);
491                let goals = types
492                    .into_iter()
493                    .map(|ty| ty.well_formed().cast(interner))
494                    .chain(Some((*trait_ref).clone().well_formed().cast(interner)));
495
496                gb.all::<_, Goal<I>>(goals)
497            },
498        )
499    });
500
501    Some(well_formed_goal)
502}
503
504/// Creates the conditions that an impl (and its contents of an impl)
505/// can assume to be true when proving that it is well-formed.
506fn impl_wf_environment<'i, I: Interner>(
507    interner: I,
508    where_clauses: &'i [QuantifiedWhereClause<I>],
509    trait_ref: &'i TraitRef<I>,
510) -> impl Iterator<Item = ProgramClause<I>> + 'i {
511    // if (WC) { ... }
512    let wc = where_clauses
513        .iter()
514        .cloned()
515        .map(move |qwc| qwc.into_from_env_goal(interner).cast(interner));
516
517    // We retrieve all the input types of the type on which we implement the trait: we will
518    // *assume* that these types are well-formed, e.g. we will be able to derive that
519    // `K: Hash` holds without writing any where clause.
520    //
521    // Example:
522    // ```
523    // struct HashSet<K> where K: Hash { ... }
524    //
525    // impl<K> Foo for HashSet<K> {
526    //     // Inside here, we can rely on the fact that `K: Hash` holds
527    // }
528    // ```
529    let types = InputTypeCollector::types_in(interner, trait_ref);
530
531    let types_wf = types
532        .into_iter()
533        .map(move |ty| ty.into_from_env_goal(interner).cast(interner));
534
535    wc.chain(types_wf)
536}
537
538/// Associated type values are special because they can be parametric (independently of
539/// the impl), so we issue a special goal which is quantified using the binders of the
540/// associated type value, for example in:
541///
542/// ```ignore
543/// trait Foo {
544///     type Item<'a>: Clone where Self: 'a
545/// }
546///
547/// impl<T> Foo for Box<T> {
548///     type Item<'a> = Box<&'a T>;
549/// }
550/// ```
551///
552/// we would issue the following subgoal: `forall<'a> { WellFormed(Box<&'a T>) }`.
553///
554/// Note that there is no binder for `T` in the above: the goal we
555/// generate is expected to be exected in the context of the
556/// larger WF goal for the impl, which already has such a
557/// binder. So the entire goal for the impl might be:
558///
559/// ```ignore
560/// forall<T> {
561///     WellFormed(Box<T>) /* this comes from the impl, not this routine */,
562///     forall<'a> { WellFormed(Box<&'a T>) },
563/// }
564/// ```
565fn compute_assoc_ty_goal<I: Interner>(
566    db: &dyn RustIrDatabase<I>,
567    assoc_ty_id: AssociatedTyValueId<I>,
568) -> Option<Goal<I>> {
569    let mut gb = GoalBuilder::new(db);
570    let assoc_ty = &db.associated_ty_value(assoc_ty_id);
571
572    // Create `forall<T, 'a> { .. }`
573    Some(gb.forall(
574        &assoc_ty.value.map_ref(|v| &v.ty),
575        assoc_ty_id,
576        |gb, assoc_ty_substitution, value_ty, assoc_ty_id| {
577            let interner = gb.interner();
578            let db = gb.db();
579
580            // Hmm, because `Arc<AssociatedTyValue>` does not implement `TypeFoldable`, we can't pass this value through,
581            // just the id, so we have to fetch `assoc_ty` from the database again.
582            // Implementing `TypeFoldable` for `AssociatedTyValue` doesn't *quite* seem right though, as that
583            // would result in a deep clone, and the value is inert. We could do some more refatoring
584            // (move the `Arc` behind a newtype, for example) to fix this, but for now doesn't
585            // seem worth it.
586            let assoc_ty = &db.associated_ty_value(assoc_ty_id);
587
588            let (impl_parameters, projection) = db
589                .impl_parameters_and_projection_from_associated_ty_value(
590                    assoc_ty_substitution.as_slice(interner),
591                    assoc_ty,
592                );
593
594            // If (/* impl WF environment */) { ... }
595            let impl_id = assoc_ty.impl_id;
596            let impl_datum = &db.impl_datum(impl_id);
597            let ImplDatumBound {
598                trait_ref: impl_trait_ref,
599                where_clauses: impl_where_clauses,
600            } = impl_datum
601                .binders
602                .clone()
603                .substitute(interner, impl_parameters);
604            let impl_wf_clauses =
605                impl_wf_environment(interner, &impl_where_clauses, &impl_trait_ref);
606            gb.implies(impl_wf_clauses, |gb| {
607                // Get the bounds and where clauses from the trait
608                // declaration, substituted appropriately.
609                //
610                // From our example:
611                //
612                // * bounds
613                //     * original in trait, `Clone`
614                //     * after substituting impl parameters, `Clone`
615                //     * note that the self-type is not yet supplied for bounds,
616                //       we will do that later
617                // * where clauses
618                //     * original in trait, `Self: 'a`
619                //     * after substituting impl parameters, `Box<!T>: '!a`
620                let assoc_ty_datum = db.associated_ty_data(projection.associated_ty_id);
621                let AssociatedTyDatumBound {
622                    bounds: defn_bounds,
623                    where_clauses: defn_where_clauses,
624                } = assoc_ty_datum
625                    .binders
626                    .clone()
627                    .substitute(interner, &projection.substitution);
628
629                // Create `if (/* where clauses on associated type value */) { .. }`
630                gb.implies(
631                    defn_where_clauses
632                        .iter()
633                        .cloned()
634                        .map(|qwc| qwc.into_from_env_goal(interner)),
635                    |gb| {
636                        let types = InputTypeCollector::types_in(gb.interner(), value_ty);
637
638                        // We require that `WellFormed(T)` for each type that appears in the value
639                        let wf_goals = types
640                            .into_iter()
641                            .map(|ty| ty.well_formed())
642                            .casted(interner);
643
644                        // Check that the `value_ty` meets the bounds from the trait.
645                        // Here we take the substituted bounds (`defn_bounds`) and we
646                        // supply the self-type `value_ty` to yield the final result.
647                        //
648                        // In our example, the bound was `Clone`, so the combined
649                        // result is `Box<!T>: Clone`. This is then converted to a
650                        // well-formed goal like `WellFormed(Box<!T>: Clone)`.
651                        let bound_goals = defn_bounds
652                            .iter()
653                            .cloned()
654                            .flat_map(|qb| qb.into_where_clauses(interner, (*value_ty).clone()))
655                            .map(|qwc| qwc.into_well_formed_goal(interner))
656                            .casted(interner);
657
658                        // Concatenate the WF goals of inner types + the requirements from trait
659                        gb.all::<_, Goal<I>>(wf_goals.chain(bound_goals))
660                    },
661                )
662            })
663        },
664    ))
665}
666
667/// Defines methods to compute well-formedness goals for well-known
668/// traits (e.g. a goal for all fields of struct in a Copy impl to be Copy)
669struct WfWellKnownConstraints;
670
671impl WfWellKnownConstraints {
672    /// Computes a goal to prove Sized constraints on a struct definition.
673    /// Struct is considered well-formed (in terms of Sized) when it either
674    /// has no fields or all of it's fields except the last are proven to be Sized.
675    pub fn struct_sized_constraint<I: Interner>(
676        db: &dyn RustIrDatabase<I>,
677        fields: &[Ty<I>],
678        size_all: bool,
679    ) -> Option<Goal<I>> {
680        let excluded = if size_all { 0 } else { 1 };
681
682        if fields.len() <= excluded {
683            return None;
684        }
685
686        let interner = db.interner();
687
688        let sized_trait = db.well_known_trait_id(WellKnownTrait::Sized)?;
689
690        Some(Goal::all(
691            interner,
692            fields[..fields.len() - excluded].iter().map(|ty| {
693                TraitRef {
694                    trait_id: sized_trait,
695                    substitution: Substitution::from1(interner, ty.clone()),
696                }
697                .cast(interner)
698            }),
699        ))
700    }
701
702    /// Verify constraints on a Copy implementation.
703    /// Copy impl is considered well-formed for
704    ///    a) certain builtin types (scalar values, shared ref, etc..)
705    ///    b) adts which
706    ///        1) have all Copy fields
707    ///        2) don't have a Drop impl
708    fn copy_impl_constraint<I: Interner>(
709        solver: &mut dyn Solver<I>,
710        db: &dyn RustIrDatabase<I>,
711        impl_datum: &ImplDatum<I>,
712    ) -> bool {
713        let interner = db.interner();
714
715        let mut gb = GoalBuilder::new(db);
716
717        let impl_fields = impl_datum
718            .binders
719            .map_ref(|v| (&v.trait_ref, &v.where_clauses));
720
721        // Implementations for scalars, pointer types and never type are provided by libcore.
722        // User implementations on types other than ADTs are forbidden.
723        match impl_datum
724            .binders
725            .skip_binders()
726            .trait_ref
727            .self_type_parameter(interner)
728            .kind(interner)
729        {
730            TyKind::Scalar(_)
731            | TyKind::Raw(_, _)
732            | TyKind::Ref(Mutability::Not, _, _)
733            | TyKind::Never => return true,
734
735            TyKind::Adt(_, _) => (),
736
737            _ => return false,
738        };
739
740        // Well fomedness goal for ADTs
741        let well_formed_goal =
742            gb.forall(&impl_fields, (), |gb, _, (trait_ref, where_clauses), ()| {
743                let interner = gb.interner();
744
745                let ty = trait_ref.self_type_parameter(interner);
746
747                let (adt_id, substitution) = match ty.kind(interner) {
748                    TyKind::Adt(adt_id, substitution) => (*adt_id, substitution),
749
750                    _ => unreachable!(),
751                };
752
753                // if (WC) { ... }
754                gb.implies(
755                    impl_wf_environment(interner, where_clauses, trait_ref),
756                    |gb| -> Goal<I> {
757                        let db = gb.db();
758
759                        // not { Implemented(ImplSelfTy: Drop) }
760                        let neg_drop_goal =
761                            db.well_known_trait_id(WellKnownTrait::Drop)
762                                .map(|drop_trait_id| {
763                                    TraitRef {
764                                        trait_id: drop_trait_id,
765                                        substitution: Substitution::from1(interner, ty.clone()),
766                                    }
767                                    .cast::<Goal<I>>(interner)
768                                    .negate(interner)
769                                });
770
771                        let adt_datum = db.adt_datum(adt_id);
772
773                        let goals = adt_datum
774                            .binders
775                            .map_ref(|b| &b.variants)
776                            .cloned()
777                            .substitute(interner, substitution)
778                            .into_iter()
779                            .flat_map(|v| {
780                                v.fields.into_iter().map(|f| {
781                                    // Implemented(FieldTy: Copy)
782                                    TraitRef {
783                                        trait_id: trait_ref.trait_id,
784                                        substitution: Substitution::from1(interner, f),
785                                    }
786                                    .cast(interner)
787                                })
788                            })
789                            .chain(neg_drop_goal.into_iter());
790                        gb.all(goals)
791                    },
792                )
793            });
794
795        solver.has_unique_solution(db, &well_formed_goal.into_closed_goal(interner))
796    }
797
798    /// Verifies constraints on a Drop implementation
799    /// Drop implementation is considered well-formed if:
800    ///     a) it's implemented on an ADT
801    ///     b) The generic parameters of the impl's type must all be parameters
802    ///        of the Drop impl itself (i.e., no specialization like
803    ///        `impl Drop for S<Foo> {...}` is allowed).
804    ///     c) Any bounds on the genereic parameters of the impl must be
805    ///        deductible from the bounds imposed by the struct definition
806    ///        (i.e. the implementation must be exactly as generic as the ADT definition).
807    ///
808    /// ```rust,ignore
809    /// struct S<T1, T2> { }
810    /// struct Foo<T> { }
811    ///
812    /// impl<U1: Copy, U2: Sized> Drop for S<U2, Foo<U1>> { }
813    /// ```
814    ///
815    /// generates the following:
816    /// goal derived from c):
817    ///
818    /// ```notrust
819    /// forall<U1, U2> {
820    ///    Implemented(U1: Copy), Implemented(U2: Sized) :- FromEnv(S<U2, Foo<U1>>)
821    /// }
822    /// ```
823    ///
824    /// goal derived from b):
825    /// ```notrust
826    /// forall <T1, T2> {
827    ///     exists<U1, U2> {
828    ///        S<T1, T2> = S<U2, Foo<U1>>
829    ///     }
830    /// }
831    /// ```
832    fn drop_impl_constraint<I: Interner>(
833        solver: &mut dyn Solver<I>,
834        db: &dyn RustIrDatabase<I>,
835        impl_datum: &ImplDatum<I>,
836    ) -> bool {
837        let interner = db.interner();
838
839        let adt_id = match impl_datum.self_type_adt_id(interner) {
840            Some(id) => id,
841            // Drop can only be implemented on a nominal type
842            None => return false,
843        };
844
845        let mut gb = GoalBuilder::new(db);
846
847        let adt_datum = db.adt_datum(adt_id);
848
849        let impl_fields = impl_datum
850            .binders
851            .map_ref(|v| (&v.trait_ref, &v.where_clauses));
852
853        // forall<ImplP1...ImplPn> { .. }
854        let implied_by_adt_def_goal =
855            gb.forall(&impl_fields, (), |gb, _, (trait_ref, where_clauses), ()| {
856                let interner = gb.interner();
857
858                // FromEnv(ImplSelfType) => ...
859                gb.implies(
860                    iter::once(
861                        FromEnv::Ty(trait_ref.self_type_parameter(interner))
862                            .cast::<DomainGoal<I>>(interner),
863                    ),
864                    |gb| {
865                        // All(ImplWhereClauses)
866                        gb.all(
867                            where_clauses
868                                .iter()
869                                .map(|wc| wc.clone().into_well_formed_goal(interner)),
870                        )
871                    },
872                )
873            });
874
875        let impl_self_ty = impl_datum
876            .binders
877            .map_ref(|b| b.trait_ref.self_type_parameter(interner));
878
879        // forall<StructP1..StructPN> {...}
880        let eq_goal = gb.forall(
881            &adt_datum.binders,
882            (adt_id, impl_self_ty),
883            |gb, substitution, _, (adt_id, impl_self_ty)| {
884                let interner = gb.interner();
885
886                let def_adt = TyKind::Adt(adt_id, substitution).intern(interner);
887
888                // exists<ImplP1...ImplPn> { .. }
889                gb.exists(&impl_self_ty, def_adt, |gb, _, impl_adt, def_adt| {
890                    let interner = gb.interner();
891
892                    // StructName<StructP1..StructPn> = ImplSelfType
893                    GoalData::EqGoal(EqGoal {
894                        a: GenericArgData::Ty(def_adt).intern(interner),
895                        b: GenericArgData::Ty(impl_adt.clone()).intern(interner),
896                    })
897                    .intern(interner)
898                })
899            },
900        );
901
902        let well_formed_goal = gb.all([implied_by_adt_def_goal, eq_goal].iter());
903
904        solver.has_unique_solution(db, &well_formed_goal.into_closed_goal(interner))
905    }
906
907    /// Verify constraints a CoerceUnsized impl.
908    /// Rules for CoerceUnsized impl to be considered well-formed:
909    /// 1) pointer conversions: `&[mut] T -> &[mut] U`, `&[mut] T -> *[mut] U`,
910    ///    `*[mut] T -> *[mut] U` are considered valid if
911    ///    1) `T: Unsize<U>`
912    ///    2) mutability is respected, i.e. immutable -> immutable, mutable -> immutable,
913    ///       mutable -> mutable conversions are allowed, immutable -> mutable is not.
914    /// 2) struct conversions of structures with the same definition, `S<P0...Pn>` -> `S<Q0...Qn>`.
915    ///    To check if this impl is legal, we would walk down the fields of `S`
916    ///    and consider their types with both substitutes. We are looking to find
917    ///    exactly one (non-phantom) field that has changed its type (from `T` to `U`), and
918    ///    expect `T` to be unsizeable to `U`, i.e. `T: CoerceUnsized<U>`.
919    ///
920    ///    As an example, consider a struct
921    ///    ```rust
922    ///    struct Foo<T, U> {
923    ///        extra: T,
924    ///        ptr: *mut U,
925    ///    }
926    ///    ```
927    ///
928    ///    We might have an impl that allows (e.g.) `Foo<T, [i32; 3]>` to be unsized
929    ///    to `Foo<T, [i32]>`. That impl would look like:
930    ///    ```rust,ignore
931    ///    impl<T, U: Unsize<V>, V> CoerceUnsized<Foo<T, V>> for Foo<T, U> {}
932    ///    ```
933    ///    In this case:
934    ///
935    ///    - `extra` has type `T` before and type `T` after
936    ///    - `ptr` has type `*mut U` before and type `*mut V` after
937    ///
938    ///    Since just one field changed, we would then check that `*mut U: CoerceUnsized<*mut V>`
939    ///    is implemented. This will work out because `U: Unsize<V>`, and we have a libcore rule
940    ///    that `*mut U` can be coerced to `*mut V` if `U: Unsize<V>`.
941    fn coerce_unsized_impl_constraint<I: Interner>(
942        solver: &mut dyn Solver<I>,
943        db: &dyn RustIrDatabase<I>,
944        impl_datum: &ImplDatum<I>,
945    ) -> bool {
946        let interner = db.interner();
947        let mut gb = GoalBuilder::new(db);
948
949        let (binders, impl_datum) = impl_datum.binders.as_ref().into();
950
951        let trait_ref: &TraitRef<I> = &impl_datum.trait_ref;
952
953        let source = trait_ref.self_type_parameter(interner);
954        let target = trait_ref
955            .substitution
956            .at(interner, 1)
957            .assert_ty_ref(interner)
958            .clone();
959
960        let mut place_in_environment = |goal| -> Goal<I> {
961            gb.forall(
962                &Binders::new(
963                    binders.clone(),
964                    (goal, trait_ref, &impl_datum.where_clauses),
965                ),
966                (),
967                |gb, _, (goal, trait_ref, where_clauses), ()| {
968                    let interner = gb.interner();
969                    gb.implies(
970                        impl_wf_environment(interner, where_clauses, trait_ref),
971                        |_| goal,
972                    )
973                },
974            )
975        };
976
977        match (source.kind(interner), target.kind(interner)) {
978            (TyKind::Ref(s_m, _, source), TyKind::Ref(t_m, _, target))
979            | (TyKind::Ref(s_m, _, source), TyKind::Raw(t_m, target))
980            | (TyKind::Raw(s_m, source), TyKind::Raw(t_m, target)) => {
981                if (*s_m, *t_m) == (Mutability::Not, Mutability::Mut) {
982                    return false;
983                }
984
985                let unsize_trait_id =
986                    if let Some(id) = db.well_known_trait_id(WellKnownTrait::Unsize) {
987                        id
988                    } else {
989                        return false;
990                    };
991
992                // Source: Unsize<Target>
993                let unsize_goal: Goal<I> = TraitRef {
994                    trait_id: unsize_trait_id,
995                    substitution: Substitution::from_iter(
996                        interner,
997                        [source.clone(), target.clone()].iter().cloned(),
998                    ),
999                }
1000                .cast(interner);
1001
1002                // ImplEnv -> Source: Unsize<Target>
1003                let unsize_goal = place_in_environment(unsize_goal);
1004
1005                solver.has_unique_solution(db, &unsize_goal.into_closed_goal(interner))
1006            }
1007            (TyKind::Adt(source_id, subst_a), TyKind::Adt(target_id, subst_b)) => {
1008                let adt_datum = db.adt_datum(*source_id);
1009
1010                if source_id != target_id || adt_datum.kind != AdtKind::Struct {
1011                    return false;
1012                }
1013
1014                let fields = adt_datum
1015                    .binders
1016                    .map_ref(|bound| &bound.variants.last().unwrap().fields)
1017                    .cloned();
1018
1019                let (source_fields, target_fields) = (
1020                    fields.clone().substitute(interner, subst_a),
1021                    fields.substitute(interner, subst_b),
1022                );
1023
1024                // collect fields with unequal ids
1025                let uneq_field_ids: Vec<usize> = (0..source_fields.len())
1026                    .filter(|&i| {
1027                        // ignore phantom data fields
1028                        if let Some(adt_id) = source_fields[i].adt_id(interner) {
1029                            if db.adt_datum(adt_id).flags.phantom_data {
1030                                return false;
1031                            }
1032                        }
1033
1034                        let eq_goal: Goal<I> = EqGoal {
1035                            a: source_fields[i].clone().cast(interner),
1036                            b: target_fields[i].clone().cast(interner),
1037                        }
1038                        .cast(interner);
1039
1040                        // ImplEnv -> Source.fields[i] = Target.fields[i]
1041                        let eq_goal = place_in_environment(eq_goal);
1042
1043                        // We are interested in !UNEQUAL! fields
1044                        !solver.has_unique_solution(db, &eq_goal.into_closed_goal(interner))
1045                    })
1046                    .collect();
1047
1048                if uneq_field_ids.len() != 1 {
1049                    return false;
1050                }
1051
1052                let field_id = uneq_field_ids[0];
1053
1054                // Source.fields[i]: CoerceUnsized<TargetFields[i]>
1055                let coerce_unsized_goal: Goal<I> = TraitRef {
1056                    trait_id: trait_ref.trait_id,
1057                    substitution: Substitution::from_iter(
1058                        interner,
1059                        [
1060                            source_fields[field_id].clone(),
1061                            target_fields[field_id].clone(),
1062                        ]
1063                        .iter()
1064                        .cloned(),
1065                    ),
1066                }
1067                .cast(interner);
1068
1069                // ImplEnv -> Source.fields[i]: CoerceUnsized<TargetFields[i]>
1070                let coerce_unsized_goal = place_in_environment(coerce_unsized_goal);
1071
1072                solver.has_unique_solution(db, &coerce_unsized_goal.into_closed_goal(interner))
1073            }
1074            _ => false,
1075        }
1076    }
1077
1078    /// Verify constraints of a DispatchFromDyn impl.
1079    ///
1080    /// Rules for DispatchFromDyn impl to be considered well-formed:
1081    ///
1082    /// * Self and the type parameter must both be references or raw pointers with the same mutabilty
1083    /// * OR all the following hold:
1084    ///   - Self and the type parameter must be structs
1085    ///   - Self and the type parameter must have the same definitions
1086    ///   - Self must not be `#[repr(packed)]` or `#[repr(C)]`
1087    ///   - Self must have exactly one field which is not a 1-ZST (there may be any number of 1-ZST
1088    ///     fields), and that field must have a different type in the type parameter (i.e., it is
1089    ///     the field being coerced)
1090    ///   - `DispatchFromDyn` is implemented for the type of the field being coerced.
1091    fn dispatch_from_dyn_constraint<I: Interner>(
1092        solver: &mut dyn Solver<I>,
1093        db: &dyn RustIrDatabase<I>,
1094        impl_datum: &ImplDatum<I>,
1095    ) -> bool {
1096        let interner = db.interner();
1097        let mut gb = GoalBuilder::new(db);
1098
1099        let (binders, impl_datum) = impl_datum.binders.as_ref().into();
1100
1101        let trait_ref: &TraitRef<I> = &impl_datum.trait_ref;
1102
1103        // DispatchFromDyn specifies that Self (source) can be coerced to T (target; its single type parameter).
1104        let source = trait_ref.self_type_parameter(interner);
1105        let target = trait_ref
1106            .substitution
1107            .at(interner, 1)
1108            .assert_ty_ref(interner)
1109            .clone();
1110
1111        let mut place_in_environment = |goal| -> Goal<I> {
1112            gb.forall(
1113                &Binders::new(
1114                    binders.clone(),
1115                    (goal, trait_ref, &impl_datum.where_clauses),
1116                ),
1117                (),
1118                |gb, _, (goal, trait_ref, where_clauses), ()| {
1119                    let interner = gb.interner();
1120                    gb.implies(
1121                        impl_wf_environment(interner, &where_clauses, &trait_ref),
1122                        |_| goal,
1123                    )
1124                },
1125            )
1126        };
1127
1128        match (source.kind(interner), target.kind(interner)) {
1129            (TyKind::Ref(s_m, _, _), TyKind::Ref(t_m, _, _))
1130            | (TyKind::Raw(s_m, _), TyKind::Raw(t_m, _))
1131                if s_m == t_m =>
1132            {
1133                true
1134            }
1135            (TyKind::Adt(source_id, subst_a), TyKind::Adt(target_id, subst_b)) => {
1136                let adt_datum = db.adt_datum(*source_id);
1137
1138                // Definitions are equal and are structs.
1139                if source_id != target_id || adt_datum.kind != AdtKind::Struct {
1140                    return false;
1141                }
1142
1143                // Not repr(C) or repr(packed).
1144                let repr = db.adt_repr(*source_id);
1145                if repr.c || repr.packed {
1146                    return false;
1147                }
1148
1149                // Collect non 1-ZST fields; there must be exactly one.
1150                let fields = adt_datum
1151                    .binders
1152                    .map_ref(|bound| &bound.variants.last().unwrap().fields)
1153                    .cloned();
1154
1155                let (source_fields, target_fields) = (
1156                    fields.clone().substitute(interner, subst_a),
1157                    fields.substitute(interner, subst_b),
1158                );
1159
1160                let mut non_zst_fields: Vec<_> = source_fields
1161                    .iter()
1162                    .zip(target_fields.iter())
1163                    .filter(|(sf, _)| match sf.adt_id(interner) {
1164                        Some(adt) => !db.adt_size_align(adt).one_zst(),
1165                        None => true,
1166                    })
1167                    .collect();
1168
1169                if non_zst_fields.len() != 1 {
1170                    return false;
1171                }
1172
1173                // The field being coerced (the interesting field).
1174                let (field_src, field_tgt) = non_zst_fields.pop().unwrap();
1175
1176                // The interesting field is different in the source and target types.
1177                let eq_goal: Goal<I> = EqGoal {
1178                    a: field_src.clone().cast(interner),
1179                    b: field_tgt.clone().cast(interner),
1180                }
1181                .cast(interner);
1182                let eq_goal = place_in_environment(eq_goal);
1183                if solver.has_unique_solution(db, &eq_goal.into_closed_goal(interner)) {
1184                    return false;
1185                }
1186
1187                // Type(field_src): DispatchFromDyn<Type(field_tgt)>
1188                let field_dispatch_goal: Goal<I> = TraitRef {
1189                    trait_id: trait_ref.trait_id,
1190                    substitution: Substitution::from_iter(
1191                        interner,
1192                        [field_src.clone(), field_tgt.clone()].iter().cloned(),
1193                    ),
1194                }
1195                .cast(interner);
1196                let field_dispatch_goal = place_in_environment(field_dispatch_goal);
1197                if !solver.has_unique_solution(db, &field_dispatch_goal.into_closed_goal(interner))
1198                {
1199                    return false;
1200                }
1201
1202                true
1203            }
1204            _ => false,
1205        }
1206    }
1207}