Skip to content

Commit 059578b

Browse files
committed
Implement Sized bound condition check
1 parent 458d224 commit 059578b

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
@@ -8756,3 +8756,55 @@ trait Foo$0<T, U> {
87568756
"#]],
87578757
);
87588758
}
8759+
8760+
#[test]
8761+
fn debug_object_safety_3() {
8762+
check(
8763+
r#"
8764+
//- minicore: sized
8765+
trait Foo$0: Sized {}
8766+
"#,
8767+
expect![[r#"
8768+
*Foo*
8769+
8770+
```rust
8771+
test
8772+
```
8773+
8774+
```rust
8775+
Ok(Some(SizedSelf))
8776+
trait Foo
8777+
where
8778+
Self: Sized,
8779+
```
8780+
"#]],
8781+
);
8782+
}
8783+
8784+
#[test]
8785+
fn debug_object_safety_4() {
8786+
check(
8787+
r#"
8788+
//- minicore: sized
8789+
trait Foo$0
8790+
where
8791+
Self: Sized
8792+
{
8793+
}
8794+
"#,
8795+
expect![[r#"
8796+
*Foo*
8797+
8798+
```rust
8799+
test
8800+
```
8801+
8802+
```rust
8803+
Ok(Some(SizedSelf))
8804+
trait Foo
8805+
where
8806+
Self: Sized,
8807+
```
8808+
"#]],
8809+
);
8810+
}

0 commit comments

Comments
 (0)