From 340f0fc3334f11b30f4c55757a0acb0b76ac5e37 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 8 Apr 2022 14:29:43 +0200 Subject: [PATCH] Ignore `Drop` and `Destruct` bounds for now - `T: ~const Drop` has a special meaning in Rust 1.61 that we don't implement. (So ideally, we'd only ignore `~const Drop`, but this should be fine for now.) - `Destruct` impls are built-in in 1.62 (current nightlies as of 08-04-2022), so until the builtin impls are supported by Chalk, we ignore them as well. Since `Destruct` is implemented for everything in non-const contexts IIUC, this should also work fine. Fixes #11932. --- crates/hir_ty/src/lower.rs | 19 ++++++- crates/hir_ty/src/tests/regression.rs | 79 +++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index ca6241c5d1a..24eff4cc9a9 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -14,6 +14,7 @@ use chalk_ir::interner::HasInterner; use chalk_ir::{cast::Cast, fold::Shift, Mutability, Safety}; use hir_def::generics::TypeOrConstParamData; use hir_def::intern::Interned; +use hir_def::lang_item::lang_attr; use hir_def::path::{ModPath, PathKind}; use hir_def::type_ref::ConstScalarOrPath; use hir_def::{ @@ -863,7 +864,23 @@ impl<'a> TyLoweringContext<'a> { let trait_ref = match bound { TypeBound::Path(path, TraitBoundModifier::None) => { bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); - bindings.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders) + bindings + .clone() + .filter(|tr| { + // ignore `T: Drop` or `T: Destruct` bounds. + // - `T: ~const Drop` has a special meaning in Rust 1.61 that we don't implement. + // (So ideally, we'd only ignore `~const Drop` here) + // - `Destruct` impls are built-in in 1.62 (current nightlies as of 08-04-2022), so until + // the builtin impls are supported by Chalk, we ignore them here. + if let Some(lang) = lang_attr(self.db.upcast(), tr.hir_trait_id()) { + if lang == "drop" || lang == "destruct" { + return false; + } + } + true + }) + .map(WhereClause::Implemented) + .map(crate::wrap_empty_binders) } TypeBound::Path(path, TraitBoundModifier::Maybe) => { let sized_trait = self diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs index 37f321a0f00..a02ec6f85c6 100644 --- a/crates/hir_ty/src/tests/regression.rs +++ b/crates/hir_ty/src/tests/regression.rs @@ -1505,3 +1505,82 @@ fn f(s: S) { "#, ); } + +#[test] +fn rust_161_option_clone() { + check_types( + r#" +//- minicore: option, drop + +fn test(o: &Option) { + o.my_clone(); + //^^^^^^^^^^^^ Option +} + +pub trait MyClone: Sized { + fn my_clone(&self) -> Self; +} + +impl const MyClone for Option +where + T: ~const MyClone + ~const Drop + ~const Destruct, +{ + fn my_clone(&self) -> Self { + match self { + Some(x) => Some(x.my_clone()), + None => None, + } + } +} + +impl const MyClone for i32 { + fn my_clone(&self) -> Self { + *self + } +} + +pub trait Destruct {} + +impl const Destruct for T {} +"#, + ); +} + +#[test] +fn rust_162_option_clone() { + check_types( + r#" +//- minicore: option, drop + +fn test(o: &Option) { + o.my_clone(); + //^^^^^^^^^^^^ Option +} + +pub trait MyClone: Sized { + fn my_clone(&self) -> Self; +} + +impl const MyClone for Option +where + T: ~const MyClone + ~const Destruct, +{ + fn my_clone(&self) -> Self { + match self { + Some(x) => Some(x.my_clone()), + None => None, + } + } +} + +impl const MyClone for i32 { + fn my_clone(&self) -> Self { + *self + } +} + +#[lang = "destruct"] +pub trait Destruct {} +"#, + ); +}