about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-05-06 17:44:48 +0000
committerbors <bors@rust-lang.org>2023-05-06 17:44:48 +0000
commitbb66f6fc3c9fc7de653701ce692aec9ec9458f12 (patch)
tree07ad9c13b9fa2b1136c29cef153d428ddbf8086b
parent5ee39a6ee50e6ddfdf5ac5532bbd13e268b3bf36 (diff)
parent9360adccda17f3236a93514a44f8c57b0be4c890 (diff)
downloadrust-bb66f6fc3c9fc7de653701ce692aec9ec9458f12.tar.gz
rust-bb66f6fc3c9fc7de653701ce692aec9ec9458f12.zip
Auto merge of #14750 - lowr:fix/rustc_reservation_impl, r=HKalbasi
fix: ignore impls with `#[rustc_reservation_impl]`

Fixes #12247
Fixes #14279

Currently core has two blanket impls for `From`: `impl<T> From<T> for T` and `impl<T> From<!> for T`. These are conflicting and thus chalk cannot uniquely solve `S: From<?0>` for any type `S`.

The latter impl is actually a reservation impl and should not be considered during trait selection. More generally, impls attributed with perma-unstable `#[rustc_reservation_impl]` attribute should be disregarded except for coherence checks. See rust-lang/rust#64631 and rust-lang/rust#64715 for details.

I chose to entirely ignore them in hir-ty because we don't do coherence checks.
-rw-r--r--crates/hir-ty/src/chalk_db.rs2
-rw-r--r--crates/hir-ty/src/method_resolution.rs9
-rw-r--r--crates/hir-ty/src/tests/never_type.rs19
3 files changed, 29 insertions, 1 deletions
diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs
index d68703ce1d4..983cc222124 100644
--- a/crates/hir-ty/src/chalk_db.rs
+++ b/crates/hir-ty/src/chalk_db.rs
@@ -453,7 +453,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
     }
 }
 
-impl<'a> chalk_ir::UnificationDatabase<Interner> for &'a dyn HirDatabase {
+impl chalk_ir::UnificationDatabase<Interner> for &dyn HirDatabase {
     fn fn_def_variance(
         &self,
         fn_def_id: chalk_ir::FnDefId<Interner>,
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index 912efc3a896..8d57211db07 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -187,6 +187,15 @@ impl TraitImpls {
     fn collect_def_map(&mut self, db: &dyn HirDatabase, def_map: &DefMap) {
         for (_module_id, module_data) in def_map.modules() {
             for impl_id in module_data.scope.impls() {
+                // Reservation impls should be ignored during trait resolution, so we never need
+                // them during type analysis. See rust-lang/rust#64631 for details.
+                //
+                // FIXME: Reservation impls should be considered during coherence checks. If we are
+                // (ever) to implement coherence checks, this filtering should be done by the trait
+                // solver.
+                if db.attrs(impl_id.into()).by_key("rustc_reservation_impl").exists() {
+                    continue;
+                }
                 let target_trait = match db.impl_trait(impl_id) {
                     Some(tr) => tr.skip_binders().hir_trait_id(),
                     None => continue,
diff --git a/crates/hir-ty/src/tests/never_type.rs b/crates/hir-ty/src/tests/never_type.rs
index fbdc8209f8f..09c63f873ee 100644
--- a/crates/hir-ty/src/tests/never_type.rs
+++ b/crates/hir-ty/src/tests/never_type.rs
@@ -483,3 +483,22 @@ fn example() -> bool {
 "#,
     );
 }
+
+#[test]
+fn reservation_impl_should_be_ignored() {
+    // See rust-lang/rust#64631.
+    check_types(
+        r#"
+//- minicore: from
+struct S;
+#[rustc_reservation_impl]
+impl<T> From<!> for T {}
+fn foo<T, U: From<T>>(_: U) -> T { loop {} }
+
+fn test() {
+    let s = foo(S);
+      //^ S
+}
+"#,
+    );
+}