Skip to content

Commit bb66f6f

Browse files
committed
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.
2 parents 5ee39a6 + 9360adc commit bb66f6f

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

crates/hir-ty/src/chalk_db.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
453453
}
454454
}
455455

456-
impl<'a> chalk_ir::UnificationDatabase<Interner> for &'a dyn HirDatabase {
456+
impl chalk_ir::UnificationDatabase<Interner> for &dyn HirDatabase {
457457
fn fn_def_variance(
458458
&self,
459459
fn_def_id: chalk_ir::FnDefId<Interner>,

crates/hir-ty/src/method_resolution.rs

+9
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,15 @@ impl TraitImpls {
187187
fn collect_def_map(&mut self, db: &dyn HirDatabase, def_map: &DefMap) {
188188
for (_module_id, module_data) in def_map.modules() {
189189
for impl_id in module_data.scope.impls() {
190+
// Reservation impls should be ignored during trait resolution, so we never need
191+
// them during type analysis. See rust-lang/rust#64631 for details.
192+
//
193+
// FIXME: Reservation impls should be considered during coherence checks. If we are
194+
// (ever) to implement coherence checks, this filtering should be done by the trait
195+
// solver.
196+
if db.attrs(impl_id.into()).by_key("rustc_reservation_impl").exists() {
197+
continue;
198+
}
190199
let target_trait = match db.impl_trait(impl_id) {
191200
Some(tr) => tr.skip_binders().hir_trait_id(),
192201
None => continue,

crates/hir-ty/src/tests/never_type.rs

+19
Original file line numberDiff line numberDiff line change
@@ -483,3 +483,22 @@ fn example() -> bool {
483483
"#,
484484
);
485485
}
486+
487+
#[test]
488+
fn reservation_impl_should_be_ignored() {
489+
// See rust-lang/rust#64631.
490+
check_types(
491+
r#"
492+
//- minicore: from
493+
struct S;
494+
#[rustc_reservation_impl]
495+
impl<T> From<!> for T {}
496+
fn foo<T, U: From<T>>(_: U) -> T { loop {} }
497+
498+
fn test() {
499+
let s = foo(S);
500+
//^ S
501+
}
502+
"#,
503+
);
504+
}

0 commit comments

Comments
 (0)