Skip to content

Commit 1dbfb4c

Browse files
committed
Implement Sized bound condition check
1 parent 4b00c23 commit 1dbfb4c

File tree

2 files changed

+76
-8
lines changed

2 files changed

+76
-8
lines changed

crates/hir-ty/src/object_safety.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1+
//! Compute the object-safety of a trait
2+
13
use chalk_ir::{DebruijnIndex, WhereClause};
24
use hir_def::{
35
lang_item::LangItem, AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId,
46
TypeAliasId,
57
};
68

79
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,
1114
};
1215

1316
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -79,14 +82,27 @@ pub fn object_safety_of_trait_query(
7982

8083
fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool {
8184
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 {
8386
return false;
8487
};
8588

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+
})
90106
}
91107

92108
fn object_safety_violation_for_assoc_item(

crates/ide/src/hover/tests.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8656,3 +8656,55 @@ trait Foo$0<T, U> {
86568656
"#]],
86578657
);
86588658
}
8659+
8660+
#[test]
8661+
fn debug_object_safety_3() {
8662+
check(
8663+
r#"
8664+
//- minicore: sized
8665+
trait Foo$0: Sized {}
8666+
"#,
8667+
expect![[r#"
8668+
*Foo*
8669+
8670+
```rust
8671+
test
8672+
```
8673+
8674+
```rust
8675+
Ok(Some(SizedSelf))
8676+
trait Foo
8677+
where
8678+
Self: Sized,
8679+
```
8680+
"#]],
8681+
);
8682+
}
8683+
8684+
#[test]
8685+
fn debug_object_safety_4() {
8686+
check(
8687+
r#"
8688+
//- minicore: sized
8689+
trait Foo$0
8690+
where
8691+
Self: Sized
8692+
{
8693+
}
8694+
"#,
8695+
expect![[r#"
8696+
*Foo*
8697+
8698+
```rust
8699+
test
8700+
```
8701+
8702+
```rust
8703+
Ok(Some(SizedSelf))
8704+
trait Foo
8705+
where
8706+
Self: Sized,
8707+
```
8708+
"#]],
8709+
);
8710+
}

0 commit comments

Comments
 (0)