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