Skip to content

Commit e31991a

Browse files
committed
Implement Sized bound condition check
1 parent b09699a commit e31991a

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
@@ -8633,3 +8633,55 @@ trait Foo$0<T, U> {
86338633
"#]],
86348634
);
86358635
}
8636+
8637+
#[test]
8638+
fn debug_object_safety_3() {
8639+
check(
8640+
r#"
8641+
//- minicore: sized
8642+
trait Foo$0: Sized {}
8643+
"#,
8644+
expect![[r#"
8645+
*Foo*
8646+
8647+
```rust
8648+
test
8649+
```
8650+
8651+
```rust
8652+
Ok(Some(SizedSelf))
8653+
trait Foo
8654+
where
8655+
Self: Sized,
8656+
```
8657+
"#]],
8658+
);
8659+
}
8660+
8661+
#[test]
8662+
fn debug_object_safety_4() {
8663+
check(
8664+
r#"
8665+
//- minicore: sized
8666+
trait Foo$0
8667+
where
8668+
Self: Sized
8669+
{
8670+
}
8671+
"#,
8672+
expect![[r#"
8673+
*Foo*
8674+
8675+
```rust
8676+
test
8677+
```
8678+
8679+
```rust
8680+
Ok(Some(SizedSelf))
8681+
trait Foo
8682+
where
8683+
Self: Sized,
8684+
```
8685+
"#]],
8686+
);
8687+
}

0 commit comments

Comments
 (0)