|
| 1 | +//! Compute the object-safety of a trait |
| 2 | +
|
1 | 3 | use chalk_ir::{DebruijnIndex, WhereClause}; |
2 | 4 | use hir_def::{ |
3 | 5 | lang_item::LangItem, AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId, |
4 | 6 | TypeAliasId, |
5 | 7 | }; |
6 | 8 |
|
7 | 9 | use crate::{ |
8 | | - all_super_traits, db::HirDatabase, generics::generics, layout::LayoutError, |
9 | | - lower::callable_item_sig, make_single_type_binders, static_lifetime, wrap_empty_binders, DynTy, |
10 | | - Interner, QuantifiedWhereClauses, Substitution, TyBuilder, TyKind, |
| 10 | + all_super_traits, db::HirDatabase, from_chalk_trait_id, generics::generics, |
| 11 | + layout::LayoutError, lower::callable_item_sig, make_single_type_binders, static_lifetime, |
| 12 | + utils::elaborate_clause_supertraits, wrap_empty_binders, DynTy, Interner, |
| 13 | + QuantifiedWhereClauses, Substitution, TyBuilder, TyKind, |
11 | 14 | }; |
12 | 15 |
|
13 | 16 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -79,14 +82,27 @@ pub fn object_safety_of_trait_query( |
79 | 82 |
|
80 | 83 | fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool { |
81 | 84 | let krate = def.module(db.upcast()).krate(); |
82 | | - let Some(_sized) = db.lang_item(krate, LangItem::Sized).and_then(|l| l.as_trait()) else { |
| 85 | + let Some(sized) = db.lang_item(krate, LangItem::Sized).and_then(|l| l.as_trait()) else { |
83 | 86 | return false; |
84 | 87 | }; |
85 | 88 |
|
86 | | - let _predicates = db.generic_predicates(def); |
87 | | - // TODO: elaborate with `utils::elaborate_clause_supertraits` and check `Self: Sized` |
88 | | - |
89 | | - false |
| 89 | + let predicates = &*db.generic_predicates(def); |
| 90 | + let predicates = predicates.iter().map(|p| p.skip_binders().skip_binders().clone()); |
| 91 | + elaborate_clause_supertraits(db, predicates).any(|pred| match pred { |
| 92 | + WhereClause::Implemented(trait_ref) => { |
| 93 | + if from_chalk_trait_id(trait_ref.trait_id) == sized { |
| 94 | + if let TyKind::BoundVar(it) = |
| 95 | + *trait_ref.self_type_parameter(Interner).kind(Interner) |
| 96 | + { |
| 97 | + // Since `generic_predicates` is `Binder<Binder<..>>`, the `DebrujinIndex` of |
| 98 | + // self-parameter is `1` |
| 99 | + return it.index_if_bound_at(DebruijnIndex::new(1)).is_some_and(|i| i == 0); |
| 100 | + } |
| 101 | + } |
| 102 | + false |
| 103 | + } |
| 104 | + _ => false, |
| 105 | + }) |
90 | 106 | } |
91 | 107 |
|
92 | 108 | fn object_safety_violation_for_assoc_item( |
|
0 commit comments