Skip to main content

hir_ty/
builtin_derive.rs

1//! Implementation of builtin derive impls.
2
3use std::ops::ControlFlow;
4
5use hir_def::{
6    AdtId, BuiltinDeriveImplId, BuiltinDeriveImplLoc, HasModule, LocalFieldId, TraitId,
7    TypeOrConstParamId, TypeParamId,
8    attrs::AttrFlags,
9    builtin_derive::BuiltinDeriveImplTrait,
10    hir::generics::{GenericParams, TypeOrConstParamData},
11};
12use itertools::Itertools;
13use la_arena::ArenaMap;
14use rustc_type_ir::{
15    AliasTyKind, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast,
16    inherent::{GenericArgs as _, IntoKind},
17};
18
19use crate::{
20    FieldType, GenericPredicates,
21    db::HirDatabase,
22    next_solver::{
23        AliasTy, Clause, Clauses, DbInterner, EarlyBinder, GenericArgs, ParamEnv,
24        StoredEarlyBinder, TraitRef, Ty, TyKind, Unnormalized, fold::fold_tys, generics::Generics,
25    },
26};
27
28fn coerce_pointee_new_type_param(trait_id: TraitId) -> TypeParamId {
29    // HACK: Fake the param.
30    // We cannot use a dummy param here, because it can leak into the IDE layer and that'll cause panics
31    // when e.g. trying to display it. So we use an existing param.
32    TypeParamId::from_unchecked(TypeOrConstParamId {
33        parent: trait_id.into(),
34        local_id: la_arena::Idx::from_raw(la_arena::RawIdx::from_u32(1)),
35    })
36}
37
38fn trait_args(trait_: BuiltinDeriveImplTrait, self_ty: Ty<'_>) -> GenericArgs<'_> {
39    match trait_ {
40        BuiltinDeriveImplTrait::Copy
41        | BuiltinDeriveImplTrait::Reborrow
42        | BuiltinDeriveImplTrait::Clone
43        | BuiltinDeriveImplTrait::Default
44        | BuiltinDeriveImplTrait::Debug
45        | BuiltinDeriveImplTrait::Hash
46        | BuiltinDeriveImplTrait::Eq
47        | BuiltinDeriveImplTrait::Ord => GenericArgs::new_from_slice(&[self_ty.into()]),
48        BuiltinDeriveImplTrait::PartialOrd | BuiltinDeriveImplTrait::PartialEq => {
49            GenericArgs::new_from_slice(&[self_ty.into(), self_ty.into()])
50        }
51        BuiltinDeriveImplTrait::CoerceUnsized | BuiltinDeriveImplTrait::DispatchFromDyn => {
52            panic!("`CoerceUnsized` and `DispatchFromDyn` have special generics")
53        }
54    }
55}
56
57pub(crate) fn generics_of<'db>(
58    interner: DbInterner<'db>,
59    id: BuiltinDeriveImplId,
60) -> Generics<'db> {
61    let db = interner.db;
62    let loc = id.loc(db);
63    match loc.trait_ {
64        BuiltinDeriveImplTrait::Copy
65        | BuiltinDeriveImplTrait::Reborrow
66        | BuiltinDeriveImplTrait::Clone
67        | BuiltinDeriveImplTrait::Default
68        | BuiltinDeriveImplTrait::Debug
69        | BuiltinDeriveImplTrait::Hash
70        | BuiltinDeriveImplTrait::Ord
71        | BuiltinDeriveImplTrait::PartialOrd
72        | BuiltinDeriveImplTrait::Eq
73        | BuiltinDeriveImplTrait::PartialEq => {
74            Generics::from_generic_def(db, loc.adt.into(), false)
75        }
76        BuiltinDeriveImplTrait::CoerceUnsized | BuiltinDeriveImplTrait::DispatchFromDyn => {
77            let trait_id = loc
78                .trait_
79                .get_id(interner.lang_items())
80                .expect("we don't pass the impl to the solver if we can't resolve the trait");
81            let additional_param = coerce_pointee_new_type_param(trait_id);
82            Generics::from_generic_def_plus_one(db, loc.adt.into(), additional_param, false)
83        }
84    }
85}
86
87pub fn generic_params_count(db: &dyn HirDatabase, id: BuiltinDeriveImplId) -> usize {
88    let loc = id.loc(db);
89    let adt_params = GenericParams::of(db, loc.adt.into());
90    let extra_params_count = match loc.trait_ {
91        BuiltinDeriveImplTrait::Copy
92        | BuiltinDeriveImplTrait::Reborrow
93        | BuiltinDeriveImplTrait::Clone
94        | BuiltinDeriveImplTrait::Default
95        | BuiltinDeriveImplTrait::Debug
96        | BuiltinDeriveImplTrait::Hash
97        | BuiltinDeriveImplTrait::Ord
98        | BuiltinDeriveImplTrait::PartialOrd
99        | BuiltinDeriveImplTrait::Eq
100        | BuiltinDeriveImplTrait::PartialEq => 0,
101        BuiltinDeriveImplTrait::CoerceUnsized | BuiltinDeriveImplTrait::DispatchFromDyn => 1,
102    };
103    adt_params.len() + extra_params_count
104}
105
106pub fn impl_trait<'db>(
107    interner: DbInterner<'db>,
108    id: BuiltinDeriveImplId,
109) -> EarlyBinder<'db, TraitRef<'db>> {
110    let db = interner.db;
111    let loc = id.loc(db);
112    let trait_id = loc
113        .trait_
114        .get_id(interner.lang_items())
115        .expect("we don't pass the impl to the solver if we can't resolve the trait");
116    match loc.trait_ {
117        BuiltinDeriveImplTrait::Copy
118        | BuiltinDeriveImplTrait::Reborrow
119        | BuiltinDeriveImplTrait::Clone
120        | BuiltinDeriveImplTrait::Default
121        | BuiltinDeriveImplTrait::Debug
122        | BuiltinDeriveImplTrait::Hash
123        | BuiltinDeriveImplTrait::Ord
124        | BuiltinDeriveImplTrait::Eq
125        | BuiltinDeriveImplTrait::PartialOrd
126        | BuiltinDeriveImplTrait::PartialEq => {
127            let self_ty = Ty::new_adt(
128                interner,
129                loc.adt,
130                GenericArgs::identity_for_item(interner, loc.adt.into()),
131            );
132            EarlyBinder::bind(TraitRef::new_from_args(
133                interner,
134                trait_id.into(),
135                trait_args(loc.trait_, self_ty),
136            ))
137        }
138        BuiltinDeriveImplTrait::CoerceUnsized | BuiltinDeriveImplTrait::DispatchFromDyn => {
139            let generic_params = GenericParams::of(db, loc.adt.into());
140            let interner = DbInterner::new_no_crate(db);
141            let args = GenericArgs::identity_for_item(interner, loc.adt.into());
142            let self_ty = Ty::new_adt(interner, loc.adt, args);
143            let Some((pointee_param_idx, _, new_param_ty)) =
144                coerce_pointee_params(interner, loc, generic_params, trait_id)
145            else {
146                // Malformed derive.
147                return EarlyBinder::bind(TraitRef::new(
148                    interner,
149                    trait_id.into(),
150                    [self_ty, self_ty],
151                ));
152            };
153            let changed_args = replace_pointee(interner, pointee_param_idx, new_param_ty, args);
154            let changed_self_ty = Ty::new_adt(interner, loc.adt, changed_args);
155            EarlyBinder::bind(TraitRef::new(interner, trait_id.into(), [self_ty, changed_self_ty]))
156        }
157    }
158}
159
160#[salsa::tracked(returns(ref))]
161pub fn predicates(db: &dyn HirDatabase, impl_: BuiltinDeriveImplId) -> GenericPredicates {
162    let loc = impl_.loc(db);
163    let generic_params = GenericParams::of(db, loc.adt.into());
164    let interner = DbInterner::new_with(db, loc.module(db).krate(db));
165    let adt_predicates = GenericPredicates::query(db, loc.adt.into());
166    let trait_id = loc
167        .trait_
168        .get_id(interner.lang_items())
169        .expect("we don't pass the impl to the solver if we can't resolve the trait");
170    match loc.trait_ {
171        BuiltinDeriveImplTrait::Copy
172        | BuiltinDeriveImplTrait::Clone
173        | BuiltinDeriveImplTrait::Debug
174        | BuiltinDeriveImplTrait::Hash
175        | BuiltinDeriveImplTrait::Ord
176        | BuiltinDeriveImplTrait::PartialOrd
177        | BuiltinDeriveImplTrait::Eq
178        | BuiltinDeriveImplTrait::PartialEq => {
179            simple_trait_predicates(interner, loc, generic_params, adt_predicates, trait_id)
180        }
181        BuiltinDeriveImplTrait::Reborrow => {
182            explicit_own_predicates(interner, adt_predicates.own_explicit_predicates())
183        }
184        BuiltinDeriveImplTrait::Default => {
185            if matches!(loc.adt, AdtId::EnumId(_)) {
186                // Enums don't have extra bounds.
187                explicit_own_predicates(interner, adt_predicates.own_explicit_predicates())
188            } else {
189                simple_trait_predicates(interner, loc, generic_params, adt_predicates, trait_id)
190            }
191        }
192        BuiltinDeriveImplTrait::CoerceUnsized | BuiltinDeriveImplTrait::DispatchFromDyn => {
193            let Some((pointee_param_idx, pointee_param_id, new_param_ty)) =
194                coerce_pointee_params(interner, loc, generic_params, trait_id)
195            else {
196                // Malformed derive.
197                return GenericPredicates::from_explicit_own_predicates(StoredEarlyBinder::bind(
198                    Clauses::empty(interner).store(),
199                ));
200            };
201            let duplicated_bounds =
202                adt_predicates.explicit_predicates().iter_identity().filter_map(|pred| {
203                    let pred = pred.skip_norm_wip();
204                    let mentions_pointee =
205                        pred.visit_with(&mut MentionsPointee { pointee_param_idx }).is_break();
206                    if !mentions_pointee {
207                        return None;
208                    }
209                    let transformed =
210                        replace_pointee(interner, pointee_param_idx, new_param_ty, pred);
211                    Some(transformed)
212                });
213            let unsize_trait = interner.lang_items().Unsize;
214            let unsize_bound = unsize_trait.map(|unsize_trait| {
215                let pointee_param_ty = Ty::new_param(interner, pointee_param_id, pointee_param_idx);
216                TraitRef::new(interner, unsize_trait.into(), [pointee_param_ty, new_param_ty])
217                    .upcast(interner)
218            });
219            GenericPredicates::from_explicit_own_predicates(StoredEarlyBinder::bind(
220                Clauses::new_from_iter(
221                    interner,
222                    adt_predicates
223                        .explicit_predicates()
224                        .iter_identity()
225                        .map(Unnormalized::skip_norm_wip)
226                        .chain(duplicated_bounds)
227                        .chain(unsize_bound),
228                )
229                .store(),
230            ))
231        }
232    }
233}
234
235fn explicit_own_predicates<'db>(
236    interner: DbInterner<'db>,
237    predicates: EarlyBinder<'db, impl Iterator<Item = Clause<'db>>>,
238) -> GenericPredicates {
239    GenericPredicates::from_explicit_own_predicates(StoredEarlyBinder::bind(
240        Clauses::new_from_iter(interner, predicates.skip_binder()).store(),
241    ))
242}
243
244/// Not cached in a query, currently used in `hir` only. If you need this in `hir-ty` consider introducing a query.
245pub fn param_env<'db>(interner: DbInterner<'db>, id: BuiltinDeriveImplId) -> ParamEnv<'db> {
246    let predicates = predicates(interner.db, id);
247    crate::lower::param_env_from_predicates(interner, predicates)
248}
249
250struct MentionsPointee {
251    pointee_param_idx: u32,
252}
253
254impl<'db> TypeVisitor<DbInterner<'db>> for MentionsPointee {
255    type Result = ControlFlow<()>;
256
257    fn visit_ty(&mut self, t: Ty<'db>) -> Self::Result {
258        if let TyKind::Param(param) = t.kind()
259            && param.index == self.pointee_param_idx
260        {
261            ControlFlow::Break(())
262        } else {
263            t.super_visit_with(self)
264        }
265    }
266}
267
268fn replace_pointee<'db, T: TypeFoldable<DbInterner<'db>>>(
269    interner: DbInterner<'db>,
270    pointee_param_idx: u32,
271    new_param_ty: Ty<'db>,
272    t: T,
273) -> T {
274    fold_tys(interner, t, |ty| match ty.kind() {
275        TyKind::Param(param) if param.index == pointee_param_idx => new_param_ty,
276        _ => ty,
277    })
278}
279
280fn simple_trait_predicates<'db>(
281    interner: DbInterner<'db>,
282    loc: &BuiltinDeriveImplLoc,
283    generic_params: &GenericParams,
284    adt_predicates: &GenericPredicates,
285    trait_id: TraitId,
286) -> GenericPredicates {
287    let extra_predicates = generic_params
288        .iter_type_or_consts()
289        .filter(|(_, data)| matches!(data, TypeOrConstParamData::TypeParamData(_)))
290        .map(|(param_idx, _)| {
291            let param_id = TypeParamId::from_unchecked(TypeOrConstParamId {
292                parent: loc.adt.into(),
293                local_id: param_idx,
294            });
295            let param_idx =
296                param_idx.into_raw().into_u32() + (generic_params.len_lifetimes() as u32);
297            let param_ty = Ty::new_param(interner, param_id, param_idx);
298            let trait_args = trait_args(loc.trait_, param_ty);
299            let trait_ref = TraitRef::new_from_args(interner, trait_id.into(), trait_args);
300            trait_ref.upcast(interner)
301        });
302    let mut assoc_type_bounds = Vec::new();
303    match loc.adt {
304        AdtId::StructId(id) => extend_assoc_type_bounds(
305            interner,
306            &mut assoc_type_bounds,
307            interner.db.field_types(id.into()),
308            trait_id,
309            loc.trait_,
310        ),
311        AdtId::UnionId(id) => extend_assoc_type_bounds(
312            interner,
313            &mut assoc_type_bounds,
314            interner.db.field_types(id.into()),
315            trait_id,
316            loc.trait_,
317        ),
318        AdtId::EnumId(id) => {
319            for &(variant_id, _) in id.enum_variants(interner.db).variants.values() {
320                extend_assoc_type_bounds(
321                    interner,
322                    &mut assoc_type_bounds,
323                    interner.db.field_types(variant_id.into()),
324                    trait_id,
325                    loc.trait_,
326                )
327            }
328        }
329    }
330    GenericPredicates::from_explicit_own_predicates(StoredEarlyBinder::bind(
331        Clauses::new_from_iter(
332            interner,
333            adt_predicates
334                .explicit_predicates()
335                .iter_identity()
336                .map(Unnormalized::skip_norm_wip)
337                .chain(extra_predicates)
338                .chain(assoc_type_bounds),
339        )
340        .store(),
341    ))
342}
343
344fn extend_assoc_type_bounds<'db>(
345    interner: DbInterner<'db>,
346    assoc_type_bounds: &mut Vec<Clause<'db>>,
347    fields: &ArenaMap<LocalFieldId, FieldType>,
348    trait_id: TraitId,
349    trait_: BuiltinDeriveImplTrait,
350) {
351    struct ProjectionFinder<'a, 'db> {
352        interner: DbInterner<'db>,
353        assoc_type_bounds: &'a mut Vec<Clause<'db>>,
354        trait_id: TraitId,
355        trait_: BuiltinDeriveImplTrait,
356    }
357
358    impl<'db> TypeVisitor<DbInterner<'db>> for ProjectionFinder<'_, 'db> {
359        type Result = ();
360
361        fn visit_ty(&mut self, t: Ty<'db>) -> Self::Result {
362            if let TyKind::Alias(AliasTy { kind: AliasTyKind::Projection { .. }, .. }) = t.kind() {
363                self.assoc_type_bounds.push(
364                    TraitRef::new_from_args(
365                        self.interner,
366                        self.trait_id.into(),
367                        trait_args(self.trait_, t),
368                    )
369                    .upcast(self.interner),
370                );
371            }
372
373            t.super_visit_with(self)
374        }
375    }
376
377    let mut visitor = ProjectionFinder { interner, assoc_type_bounds, trait_id, trait_ };
378    for (_, field) in fields.iter() {
379        field.ty().instantiate_identity().skip_norm_wip().visit_with(&mut visitor);
380    }
381}
382
383fn coerce_pointee_params<'db>(
384    interner: DbInterner<'db>,
385    loc: &BuiltinDeriveImplLoc,
386    generic_params: &GenericParams,
387    trait_id: TraitId,
388) -> Option<(u32, TypeParamId, Ty<'db>)> {
389    let pointee_param = {
390        if let Ok((pointee_param, _)) = generic_params
391            .iter_type_or_consts()
392            .filter(|param| matches!(param.1, TypeOrConstParamData::TypeParamData(_)))
393            .exactly_one()
394        {
395            pointee_param
396        } else {
397            let (_, generic_param_attrs) =
398                AttrFlags::query_generic_params(interner.db, loc.adt.into());
399            generic_param_attrs
400                .iter()
401                .find(|param| param.1.contains(AttrFlags::IS_POINTEE))
402                .map(|(param, _)| param)
403                .or_else(|| {
404                    generic_params
405                        .iter_type_or_consts()
406                        .find(|param| matches!(param.1, TypeOrConstParamData::TypeParamData(_)))
407                        .map(|(idx, _)| idx)
408                })?
409        }
410    };
411    let pointee_param_id = TypeParamId::from_unchecked(TypeOrConstParamId {
412        parent: loc.adt.into(),
413        local_id: pointee_param,
414    });
415    let pointee_param_idx =
416        pointee_param.into_raw().into_u32() + (generic_params.len_lifetimes() as u32);
417    let new_param_idx = generic_params.len() as u32;
418    let new_param_id = coerce_pointee_new_type_param(trait_id);
419    let new_param_ty = Ty::new_param(interner, new_param_id, new_param_idx);
420    Some((pointee_param_idx, pointee_param_id, new_param_ty))
421}
422
423#[cfg(test)]
424mod tests {
425    use expect_test::{Expect, expect};
426    use hir_def::nameres::crate_def_map;
427    use itertools::Itertools;
428    use stdx::format_to;
429    use test_fixture::WithFixture;
430
431    use crate::{builtin_derive::impl_trait, next_solver::DbInterner, test_db::TestDB};
432
433    fn check_trait_refs(#[rust_analyzer::rust_fixture] ra_fixture: &str, expectation: Expect) {
434        let db = TestDB::with_files(ra_fixture);
435        let def_map = crate_def_map(&db, db.test_crate());
436
437        let interner = DbInterner::new_with(&db, db.test_crate());
438        crate::attach_db(&db, || {
439            let mut trait_refs = Vec::new();
440            for (_, module) in def_map.modules() {
441                for derive in module.scope.builtin_derive_impls() {
442                    let trait_ref = impl_trait(interner, derive).skip_binder();
443                    trait_refs.push(format!("{trait_ref:?}"));
444                }
445            }
446
447            expectation.assert_eq(&trait_refs.join("\n"));
448        });
449    }
450
451    fn check_predicates(#[rust_analyzer::rust_fixture] ra_fixture: &str, expectation: Expect) {
452        let db = TestDB::with_files(ra_fixture);
453        let def_map = crate_def_map(&db, db.test_crate());
454
455        crate::attach_db(&db, || {
456            let mut predicates = String::new();
457            for (_, module) in def_map.modules() {
458                for derive in module.scope.builtin_derive_impls() {
459                    let preds = super::predicates(&db, derive).all_predicates().skip_binder();
460                    format_to!(
461                        predicates,
462                        "{}\n\n",
463                        preds.format_with("\n", |pred, formatter| formatter(&format_args!(
464                            "{pred:?}"
465                        ))),
466                    );
467                }
468            }
469
470            expectation.assert_eq(&predicates);
471        });
472    }
473
474    #[test]
475    fn simple_macros_trait_ref() {
476        check_trait_refs(
477            r#"
478//- minicore: derive, clone, copy, eq, ord, hash, fmt
479
480#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
481struct Simple;
482
483trait Trait {}
484
485#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
486struct WithGenerics<'a, T: Trait, const N: usize>(&'a [T; N]);
487        "#,
488            expect![[r#"
489                Simple: Debug
490                Simple: Clone
491                Simple: Copy
492                Simple: PartialEq<[Simple]>
493                Simple: Eq
494                Simple: PartialOrd<[Simple]>
495                Simple: Ord
496                Simple: Hash
497                WithGenerics<#0, #1, #2>: Debug
498                WithGenerics<#0, #1, #2>: Clone
499                WithGenerics<#0, #1, #2>: Copy
500                WithGenerics<#0, #1, #2>: PartialEq<[WithGenerics<#0, #1, #2>]>
501                WithGenerics<#0, #1, #2>: Eq
502                WithGenerics<#0, #1, #2>: PartialOrd<[WithGenerics<#0, #1, #2>]>
503                WithGenerics<#0, #1, #2>: Ord
504                WithGenerics<#0, #1, #2>: Hash"#]],
505        );
506    }
507
508    #[test]
509    fn coerce_pointee_trait_ref() {
510        check_trait_refs(
511            r#"
512//- minicore: derive, coerce_pointee
513use core::marker::CoercePointee;
514
515#[derive(CoercePointee)]
516struct Simple<T: ?Sized>(*const T);
517
518#[derive(CoercePointee)]
519struct MultiGenericParams<'a, T, #[pointee] U: ?Sized, const N: usize>(*const U);
520        "#,
521            expect![[r#"
522                Simple<#0>: CoerceUnsized<[Simple<#1>]>
523                Simple<#0>: DispatchFromDyn<[Simple<#1>]>
524                MultiGenericParams<#0, #1, #2, #3>: CoerceUnsized<[MultiGenericParams<#0, #1, #4, #3>]>
525                MultiGenericParams<#0, #1, #2, #3>: DispatchFromDyn<[MultiGenericParams<#0, #1, #4, #3>]>"#]],
526        );
527    }
528
529    #[test]
530    fn reborrow_trait_ref() {
531        check_trait_refs(
532            r#"
533//- minicore: reborrow
534use core::marker::Reborrow;
535
536#[derive(Reborrow)]
537struct Marker<'a, T>(&'a mut T);
538        "#,
539            expect![[r#"
540                Marker<#0, #1>: Reborrow"#]],
541        );
542    }
543
544    #[test]
545    fn simple_macros_predicates() {
546        check_predicates(
547            r#"
548//- minicore: derive, clone, copy, eq, ord, hash, fmt
549
550#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
551struct Simple;
552
553trait Trait {
554    type Assoc;
555}
556
557#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
558struct WithGenerics<'a, T: Trait, const N: usize>(&'a [T; N], T::Assoc);
559        "#,
560            expect![[r#"
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577                Clause(Binder { value: TraitPredicate(#1: Trait, polarity:Positive), bound_vars: [] })
578                Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
579                Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
580                Clause(Binder { value: TraitPredicate(#1: Debug, polarity:Positive), bound_vars: [] })
581                Clause(Binder { value: TraitPredicate(Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. }): Debug, polarity:Positive), bound_vars: [] })
582
583                Clause(Binder { value: TraitPredicate(#1: Trait, polarity:Positive), bound_vars: [] })
584                Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
585                Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
586                Clause(Binder { value: TraitPredicate(#1: Clone, polarity:Positive), bound_vars: [] })
587                Clause(Binder { value: TraitPredicate(Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. }): Clone, polarity:Positive), bound_vars: [] })
588
589                Clause(Binder { value: TraitPredicate(#1: Trait, polarity:Positive), bound_vars: [] })
590                Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
591                Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
592                Clause(Binder { value: TraitPredicate(#1: Copy, polarity:Positive), bound_vars: [] })
593                Clause(Binder { value: TraitPredicate(Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. }): Copy, polarity:Positive), bound_vars: [] })
594
595                Clause(Binder { value: TraitPredicate(#1: Trait, polarity:Positive), bound_vars: [] })
596                Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
597                Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
598                Clause(Binder { value: TraitPredicate(#1: PartialEq<[#1]>, polarity:Positive), bound_vars: [] })
599                Clause(Binder { value: TraitPredicate(Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. }): PartialEq<[Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. })]>, polarity:Positive), bound_vars: [] })
600
601                Clause(Binder { value: TraitPredicate(#1: Trait, polarity:Positive), bound_vars: [] })
602                Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
603                Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
604                Clause(Binder { value: TraitPredicate(#1: Eq, polarity:Positive), bound_vars: [] })
605                Clause(Binder { value: TraitPredicate(Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. }): Eq, polarity:Positive), bound_vars: [] })
606
607                Clause(Binder { value: TraitPredicate(#1: Trait, polarity:Positive), bound_vars: [] })
608                Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
609                Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
610                Clause(Binder { value: TraitPredicate(#1: PartialOrd<[#1]>, polarity:Positive), bound_vars: [] })
611                Clause(Binder { value: TraitPredicate(Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. }): PartialOrd<[Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. })]>, polarity:Positive), bound_vars: [] })
612
613                Clause(Binder { value: TraitPredicate(#1: Trait, polarity:Positive), bound_vars: [] })
614                Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
615                Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
616                Clause(Binder { value: TraitPredicate(#1: Ord, polarity:Positive), bound_vars: [] })
617                Clause(Binder { value: TraitPredicate(Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. }): Ord, polarity:Positive), bound_vars: [] })
618
619                Clause(Binder { value: TraitPredicate(#1: Trait, polarity:Positive), bound_vars: [] })
620                Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
621                Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
622                Clause(Binder { value: TraitPredicate(#1: Hash, polarity:Positive), bound_vars: [] })
623                Clause(Binder { value: TraitPredicate(Alias(AliasTy { args: [#1], kind: Projection { def_id: TypeAliasId("Assoc") }, .. }): Hash, polarity:Positive), bound_vars: [] })
624
625            "#]],
626        );
627    }
628
629    #[test]
630    fn reborrow_predicates() {
631        check_predicates(
632            r#"
633//- minicore: reborrow
634use core::marker::Reborrow;
635
636trait Trait {}
637
638#[derive(Reborrow)]
639struct Marker<'a, T: Trait, const N: usize>(&'a mut [T; N]);
640        "#,
641            expect![[r#"
642                Clause(Binder { value: TraitPredicate(#1: Trait, polarity:Positive), bound_vars: [] })
643                Clause(Binder { value: ConstArgHasType(#2, usize), bound_vars: [] })
644                Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
645
646            "#]],
647        );
648    }
649
650    #[test]
651    fn coerce_pointee_predicates() {
652        check_predicates(
653            r#"
654//- minicore: derive, coerce_pointee
655use core::marker::CoercePointee;
656
657#[derive(CoercePointee)]
658struct Simple<T: ?Sized>(*const T);
659
660trait Trait<T> {}
661
662#[derive(CoercePointee)]
663struct MultiGenericParams<'a, T, #[pointee] U: ?Sized, const N: usize>(*const U)
664where
665    T: Trait<U>,
666    U: Trait<U>;
667        "#,
668            expect![[r#"
669                Clause(Binder { value: TraitPredicate(#0: Unsize<[#1]>, polarity:Positive), bound_vars: [] })
670
671                Clause(Binder { value: TraitPredicate(#0: Unsize<[#1]>, polarity:Positive), bound_vars: [] })
672
673                Clause(Binder { value: TraitPredicate(#1: Trait<[#2]>, polarity:Positive), bound_vars: [] })
674                Clause(Binder { value: TraitPredicate(#2: Trait<[#2]>, polarity:Positive), bound_vars: [] })
675                Clause(Binder { value: ConstArgHasType(#3, usize), bound_vars: [] })
676                Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
677                Clause(Binder { value: TraitPredicate(#1: Trait<[#4]>, polarity:Positive), bound_vars: [] })
678                Clause(Binder { value: TraitPredicate(#4: Trait<[#4]>, polarity:Positive), bound_vars: [] })
679                Clause(Binder { value: TraitPredicate(#2: Unsize<[#4]>, polarity:Positive), bound_vars: [] })
680
681                Clause(Binder { value: TraitPredicate(#1: Trait<[#2]>, polarity:Positive), bound_vars: [] })
682                Clause(Binder { value: TraitPredicate(#2: Trait<[#2]>, polarity:Positive), bound_vars: [] })
683                Clause(Binder { value: ConstArgHasType(#3, usize), bound_vars: [] })
684                Clause(Binder { value: TraitPredicate(#1: Sized, polarity:Positive), bound_vars: [] })
685                Clause(Binder { value: TraitPredicate(#1: Trait<[#4]>, polarity:Positive), bound_vars: [] })
686                Clause(Binder { value: TraitPredicate(#4: Trait<[#4]>, polarity:Positive), bound_vars: [] })
687                Clause(Binder { value: TraitPredicate(#2: Unsize<[#4]>, polarity:Positive), bound_vars: [] })
688
689            "#]],
690        );
691    }
692}