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.
This commit is contained in:
Florian Diebold 2022-04-08 14:29:43 +02:00
parent bc56920757
commit 340f0fc333
2 changed files with 97 additions and 1 deletions

View File

@ -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

View File

@ -1505,3 +1505,82 @@ fn f(s: S) {
"#,
);
}
#[test]
fn rust_161_option_clone() {
check_types(
r#"
//- minicore: option, drop
fn test(o: &Option<i32>) {
o.my_clone();
//^^^^^^^^^^^^ Option<i32>
}
pub trait MyClone: Sized {
fn my_clone(&self) -> Self;
}
impl<T> const MyClone for Option<T>
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<T: ?Sized> const Destruct for T {}
"#,
);
}
#[test]
fn rust_162_option_clone() {
check_types(
r#"
//- minicore: option, drop
fn test(o: &Option<i32>) {
o.my_clone();
//^^^^^^^^^^^^ Option<i32>
}
pub trait MyClone: Sized {
fn my_clone(&self) -> Self;
}
impl<T> const MyClone for Option<T>
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 {}
"#,
);
}