Repository: rust-lang/rust-analyzer
Pull request #15125 (2023-06-24 14:55:38)

internal: support `#[rustc_coinductive]`
rust-lang/rust#100386 changed the trait solver so that `Sized` is treated as coinductive trait, just like auto traits. This is now controlled by the perma-unstable `#[rustc_coinductive]` attribute (rust-lang/rust#108033), which this PR adds support for.

In practice, I don't think this matters much if at all. Currently we don't give chalk enough information so chalk cannot precisely (dis)prove `Sized` bounds.



Patch:
diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs
index 5dd8e2719a..fb8c9a9a1c 100644
--- a/crates/hir-ty/src/chalk_db.rs
+++ b/crates/hir-ty/src/chalk_db.rs
@@ -550,6 +550,10 @@ pub(crate) fn trait_datum_query(
     debug!("trait_datum {:?}", trait_id);
     let trait_ = from_chalk_trait_id(trait_id);
     let trait_data = db.trait_data(trait_);
+
+    let coinductive =
+        trait_data.is_auto || db.attrs(trait_.into()).by_key("rustc_coinductive").exists();
+
     debug!("trait {:?} = {:?}", trait_id, trait_data.name);
     let generic_params = generics(db.upcast(), trait_.into());
     let bound_vars = generic_params.bound_vars_subst(db, DebruijnIndex::INNERMOST);
@@ -557,7 +561,7 @@ pub(crate) fn trait_datum_query(
         auto: trait_data.is_auto,
         upstream: trait_.lookup(db.upcast()).container.krate() != krate,
         non_enumerable: true,
-        coinductive: false, // only relevant for Chalk testing
+        coinductive,
         // FIXME: set these flags correctly
         marker: false,
         fundamental: false,
@@ -637,7 +641,7 @@ pub(crate) fn struct_datum_query(
         fundamental: false,
         phantom_data: false,
     };
-    // FIXME provide enum variants properly (for auto traits)
+    // FIXME provide enum variants properly (for auto traits and `Sized`)
     let variant = rust_ir::AdtVariantDatum {
         fields: Vec::new(), // FIXME add fields (only relevant for auto traits),
     };
diff --git a/crates/ide/src/inlay_hints/chaining.rs b/crates/ide/src/inlay_hints/chaining.rs
index 774383d50d..8ac62bee7b 100644
--- a/crates/ide/src/inlay_hints/chaining.rs
+++ b/crates/ide/src/inlay_hints/chaining.rs
@@ -474,7 +474,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9288..9296,
+                                        range: 9313..9321,
                                     },
                                 ),
                                 tooltip: "",
@@ -487,7 +487,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9320..9324,
+                                        range: 9345..9349,
                                     },
                                 ),
                                 tooltip: "",
@@ -511,7 +511,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9288..9296,
+                                        range: 9313..9321,
                                     },
                                 ),
                                 tooltip: "",
@@ -524,7 +524,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9320..9324,
+                                        range: 9345..9349,
                                     },
                                 ),
                                 tooltip: "",
@@ -548,7 +548,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9288..9296,
+                                        range: 9313..9321,
                                     },
                                 ),
                                 tooltip: "",
@@ -561,7 +561,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9320..9324,
+                                        range: 9345..9349,
                                     },
                                 ),
                                 tooltip: "",


Test patch:
diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs
index 97ae732a90..764e77950f 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/crates/hir-ty/src/tests/traits.rs
@@ -4410,3 +4410,35 @@ fn test(v: S<i32>) {
 "#,
     );
 }
+
+#[test]
+fn rustc_coinductive() {
+    // Taken from rust-lang/rust#108033 with modification.
+    check_types(
+        r#"
+#[rustc_coinductive]
+trait Trait { type Assoc; }
+
+impl<T, U> Trait for (T, U)
+where
+    (U, T): Trait,
+    (): ConstrainToU32<T>,
+{
+    type Assoc = i32;
+}
+
+trait ConstrainToU32<T> {}
+impl ConstrainToU32<u32> for () {}
+
+fn impls_trait<T, U, R>() -> R
+where
+    (T, U): Trait<Assoc = R>,
+{ loop {} }
+
+fn main() {
+    let _ = impls_trait::<_, _, _>();
+      //^ i32
+}
+"#,
+    );
+}
diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs
index 0d6e4b98d8..041675d7d8 100644
--- a/crates/test-utils/src/minicore.rs
+++ b/crates/test-utils/src/minicore.rs
@@ -62,6 +62,7 @@ pub mod marker {
     #[lang = "sized"]
     #[fundamental]
     #[rustc_specialization_trait]
+    #[rustc_coinductive]
     pub trait Sized {}
     // endregion:sized