Unnamed repository; edit this file 'description' to name the repository.
Mark auto traits as coinductive
Coinductive traits are traits that when proving a predicate for them, `Type: Trait`, inside the predicate we can rely on itself to hold. For example, in `struct Foo(Foo)`, coinductive trait will succeed `Foo: Trait` and non-coinductive trait will fail unless there's an `impl Trait for Foo`. In Rust, only auto traits and `#[rustc_coinductive]` traits are coinductive, but previously we haven't considered auto traits coinductive.
Chayim Refael Friedman 2 weeks ago
parent a7d2343 · commit 1663629
-rw-r--r--crates/hir-def/src/signatures.rs2
-rw-r--r--crates/hir-ty/src/tests/traits.rs34
2 files changed, 35 insertions, 1 deletions
diff --git a/crates/hir-def/src/signatures.rs b/crates/hir-def/src/signatures.rs
index 10a38ec71e..45dab8859d 100644
--- a/crates/hir-def/src/signatures.rs
+++ b/crates/hir-def/src/signatures.rs
@@ -545,7 +545,7 @@ impl TraitSignature {
let attrs = AttrFlags::query(db, id.into());
let source = loc.source(db);
if source.value.auto_token().is_some() {
- flags.insert(TraitFlags::AUTO);
+ flags.insert(TraitFlags::AUTO | TraitFlags::COINDUCTIVE);
}
if source.value.unsafe_token().is_some() {
flags.insert(TraitFlags::UNSAFE);
diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs
index 8233a00981..fad944589d 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/crates/hir-ty/src/tests/traits.rs
@@ -5377,3 +5377,37 @@ fn run_dyn<'b>(val: &dyn for<'a> Trait<'a, 'b>) {}
"#]],
);
}
+
+#[test]
+fn recursive_auto_trait() {
+ check_types(
+ r#"
+auto trait Send {}
+impl<T> !Send for *const T {}
+
+struct Vec<T>(*const T);
+impl<T: Send> Send for Vec<T> {}
+
+struct Node {
+ children: Vec<Node>,
+}
+
+struct Holder<T>(T);
+
+trait Lock<T> {
+ fn get(&self) -> &T;
+}
+
+impl<T: Send> Lock<T> for Holder<T> {
+ fn get(&self) -> &T {
+ &self.0
+ }
+}
+
+fn probe(h: &Holder<Node>) {
+ h.get();
+ // ^^^^^^^ &'? Node
+}
+ "#,
+ );
+}