Migrate drop glue handling to new solver
And:
- Remove it from being a query (it is only used for hover, where no caching is needed, and MIR evaluation of `needs_drop()`, which is rare).
- Fix handling of `PhantomData`.
diff --git a/crates/hir-ty/src/consteval/tests/intrinsics.rs b/crates/hir-ty/src/consteval/tests/intrinsics.rs
index 5e85978..10282d2 100644
--- a/crates/hir-ty/src/consteval/tests/intrinsics.rs
+++ b/crates/hir-ty/src/consteval/tests/intrinsics.rs
@@ -354,8 +354,9 @@
fn needs_drop() {
check_number(
r#"
- //- minicore: drop, manually_drop, copy, sized
+ //- minicore: drop, manually_drop, copy, sized, phantom_data
use core::mem::ManuallyDrop;
+ use core::marker::PhantomData;
extern "rust-intrinsic" {
pub fn needs_drop<T: ?Sized>() -> bool;
}
@@ -380,17 +381,19 @@
const fn opaque_copy() -> impl Sized + Copy {
|| {}
}
+ struct RecursiveType(RecursiveType);
trait Everything {}
impl<T> Everything for T {}
const GOAL: bool = !needs_drop::<i32>() && !needs_drop::<X>()
&& needs_drop::<NeedsDrop>() && !needs_drop::<ManuallyDrop<NeedsDrop>>()
&& needs_drop::<[NeedsDrop; 1]>() && !needs_drop::<[NeedsDrop; 0]>()
- && needs_drop::<(X, NeedsDrop)>()
+ && needs_drop::<(X, NeedsDrop)>() && !needs_drop::<PhantomData<NeedsDrop>>()
&& needs_drop::<Enum<NeedsDrop>>() && !needs_drop::<Enum<X>>()
&& closure_needs_drop()
&& !val_needs_drop(opaque()) && !val_needs_drop(opaque_copy())
&& needs_drop::<[NeedsDrop]>() && needs_drop::<dyn Everything>()
- && !needs_drop::<&dyn Everything>() && !needs_drop::<str>();
+ && !needs_drop::<&dyn Everything>() && !needs_drop::<str>()
+ && !needs_drop::<RecursiveType>();
"#,
1,
);
diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs
index 82d17cc..11d3be5 100644
--- a/crates/hir-ty/src/db.rs
+++ b/crates/hir-ty/src/db.rs
@@ -19,7 +19,6 @@
Binders, Const, ImplTraitId, ImplTraits, InferenceResult, Substitution, TraitEnvironment, Ty,
TyDefId, ValueTyDefId, chalk_db,
consteval::ConstEvalError,
- drop::DropGlue,
dyn_compatibility::DynCompatibilityViolation,
layout::{Layout, LayoutError},
lower::{Diagnostics, GenericDefaults, GenericPredicates},
@@ -334,10 +333,6 @@
goal: crate::Canonical<crate::InEnvironment<crate::Goal>>,
) -> NextTraitSolveResult;
- #[salsa::invoke(crate::drop::has_drop_glue)]
- #[salsa::cycle(cycle_result = crate::drop::has_drop_glue_cycle_result)]
- fn has_drop_glue(&self, ty: Ty, env: Arc<TraitEnvironment<'_>>) -> DropGlue;
-
// next trait solver
#[salsa::invoke(crate::lower_nextsolver::const_param_ty_query)]
diff --git a/crates/hir-ty/src/drop.rs b/crates/hir-ty/src/drop.rs
index 0618fd1..4bd9691 100644
--- a/crates/hir-ty/src/drop.rs
+++ b/crates/hir-ty/src/drop.rs
@@ -1,18 +1,20 @@
//! Utilities for computing drop info about types.
-use chalk_ir::cast::Cast;
-use hir_def::AdtId;
-use hir_def::lang_item::LangItem;
-use hir_def::signatures::StructFlags;
+use hir_def::{AdtId, lang_item::LangItem, signatures::StructFlags};
+use rustc_hash::FxHashSet;
+use rustc_type_ir::inherent::{AdtDef, IntoKind, SliceLike};
use stdx::never;
use triomphe::Arc;
-use crate::next_solver::DbInterner;
-use crate::next_solver::mapping::{ChalkToNextSolver, NextSolverToChalk};
use crate::{
- AliasTy, Canonical, CanonicalVarKinds, ConcreteConst, ConstScalar, ConstValue, InEnvironment,
- Interner, ProjectionTy, TraitEnvironment, Ty, TyBuilder, TyKind, db::HirDatabase,
+ TraitEnvironment, consteval_nextsolver,
+ db::HirDatabase,
method_resolution::TyFingerprint,
+ next_solver::{
+ Ty, TyKind,
+ infer::{InferCtxt, traits::ObligationCause},
+ obligation_ctxt::ObligationCtxt,
+ },
};
fn has_destructor(db: &dyn HirDatabase, adt: AdtId) -> bool {
@@ -45,27 +47,52 @@
HasDropGlue,
}
-pub(crate) fn has_drop_glue(
- db: &dyn HirDatabase,
- ty: Ty,
- env: Arc<TraitEnvironment<'_>>,
+pub fn has_drop_glue<'db>(
+ infcx: &InferCtxt<'db>,
+ ty: Ty<'db>,
+ env: Arc<TraitEnvironment<'db>>,
) -> DropGlue {
- match ty.kind(Interner) {
- TyKind::Adt(adt, subst) => {
- if has_destructor(db, adt.0) {
+ has_drop_glue_impl(infcx, ty, env, &mut FxHashSet::default())
+}
+
+fn has_drop_glue_impl<'db>(
+ infcx: &InferCtxt<'db>,
+ ty: Ty<'db>,
+ env: Arc<TraitEnvironment<'db>>,
+ visited: &mut FxHashSet<Ty<'db>>,
+) -> DropGlue {
+ let mut ocx = ObligationCtxt::new(infcx);
+ let ty = ocx.structurally_normalize_ty(&ObligationCause::dummy(), env.env, ty).unwrap_or(ty);
+
+ if !visited.insert(ty) {
+ // Recursive type.
+ return DropGlue::None;
+ }
+
+ let db = infcx.interner.db;
+ match ty.kind() {
+ TyKind::Adt(adt_def, subst) => {
+ let adt_id = adt_def.def_id().0;
+ if has_destructor(db, adt_id) {
return DropGlue::HasDropGlue;
}
- match adt.0 {
+ match adt_id {
AdtId::StructId(id) => {
- if db.struct_signature(id).flags.contains(StructFlags::IS_MANUALLY_DROP) {
+ if db
+ .struct_signature(id)
+ .flags
+ .intersects(StructFlags::IS_MANUALLY_DROP | StructFlags::IS_PHANTOM_DATA)
+ {
return DropGlue::None;
}
- db.field_types(id.into())
+ db.field_types_ns(id.into())
.iter()
.map(|(_, field_ty)| {
- db.has_drop_glue(
- field_ty.clone().substitute(Interner, subst),
+ has_drop_glue_impl(
+ infcx,
+ field_ty.instantiate(infcx.interner, subst),
env.clone(),
+ visited,
)
})
.max()
@@ -78,12 +105,14 @@
.variants
.iter()
.map(|&(variant, _, _)| {
- db.field_types(variant.into())
+ db.field_types_ns(variant.into())
.iter()
.map(|(_, field_ty)| {
- db.has_drop_glue(
- field_ty.clone().substitute(Interner, subst),
+ has_drop_glue_impl(
+ infcx,
+ field_ty.instantiate(infcx.interner, subst),
env.clone(),
+ visited,
)
})
.max()
@@ -93,123 +122,70 @@
.unwrap_or(DropGlue::None),
}
}
- TyKind::Tuple(_, subst) => subst
- .iter(Interner)
- .map(|ty| ty.assert_ty_ref(Interner))
- .map(|ty| db.has_drop_glue(ty.clone(), env.clone()))
+ TyKind::Tuple(tys) => tys
+ .iter()
+ .map(|ty| has_drop_glue_impl(infcx, ty, env.clone(), visited))
.max()
.unwrap_or(DropGlue::None),
TyKind::Array(ty, len) => {
- if let ConstValue::Concrete(ConcreteConst { interned: ConstScalar::Bytes(len, _) }) =
- &len.data(Interner).value
- {
- match (&**len).try_into() {
- Ok(len) => {
- let len = usize::from_le_bytes(len);
- if len == 0 {
- // Arrays of size 0 don't have drop glue.
- return DropGlue::None;
- }
- }
- Err(_) => {
- never!("const array size with non-usize len");
- }
- }
+ if consteval_nextsolver::try_const_usize(db, len) == Some(0) {
+ // Arrays of size 0 don't have drop glue.
+ return DropGlue::None;
}
- db.has_drop_glue(ty.clone(), env)
+ has_drop_glue_impl(infcx, ty, env, visited)
}
- TyKind::Slice(ty) => db.has_drop_glue(ty.clone(), env),
+ TyKind::Slice(ty) => has_drop_glue_impl(infcx, ty, env, visited),
TyKind::Closure(closure_id, subst) => {
- let closure_id = (*closure_id).into();
- let owner = db.lookup_intern_closure(closure_id).0;
+ let owner = db.lookup_intern_closure(closure_id.0).0;
let infer = db.infer(owner);
- let (captures, _) = infer.closure_info(closure_id);
+ let (captures, _) = infer.closure_info(closure_id.0);
let env = db.trait_environment_for_body(owner);
- let interner = DbInterner::conjure();
captures
.iter()
.map(|capture| {
- db.has_drop_glue(
- capture.ty(db, subst.to_nextsolver(interner)).to_chalk(interner),
- env.clone(),
- )
+ has_drop_glue_impl(infcx, capture.ty(db, subst), env.clone(), visited)
})
.max()
.unwrap_or(DropGlue::None)
}
// FIXME: Handle coroutines.
- TyKind::Coroutine(..) | TyKind::CoroutineWitness(..) => DropGlue::None,
+ TyKind::Coroutine(..) | TyKind::CoroutineWitness(..) | TyKind::CoroutineClosure(..) => {
+ DropGlue::None
+ }
TyKind::Ref(..)
- | TyKind::Raw(..)
+ | TyKind::RawPtr(..)
| TyKind::FnDef(..)
| TyKind::Str
| TyKind::Never
- | TyKind::Scalar(_)
- | TyKind::Function(_)
+ | TyKind::Bool
+ | TyKind::Char
+ | TyKind::Int(_)
+ | TyKind::Uint(_)
+ | TyKind::Float(_)
+ | TyKind::FnPtr(..)
| TyKind::Foreign(_)
- | TyKind::Error => DropGlue::None,
- TyKind::Dyn(_) => DropGlue::HasDropGlue,
- TyKind::AssociatedType(assoc_type_id, subst) => projection_has_drop_glue(
- db,
- env,
- ProjectionTy { associated_ty_id: *assoc_type_id, substitution: subst.clone() },
- ty,
- ),
- TyKind::Alias(AliasTy::Projection(projection)) => {
- projection_has_drop_glue(db, env, projection.clone(), ty)
- }
- TyKind::OpaqueType(..) | TyKind::Alias(AliasTy::Opaque(_)) => {
- if is_copy(db, ty, env) {
+ | TyKind::Error(_)
+ | TyKind::Bound(..)
+ | TyKind::Placeholder(..) => DropGlue::None,
+ TyKind::Dynamic(..) => DropGlue::HasDropGlue,
+ TyKind::Alias(..) => {
+ if infcx.type_is_copy_modulo_regions(env.env, ty) {
DropGlue::None
} else {
DropGlue::HasDropGlue
}
}
- TyKind::Placeholder(_) | TyKind::BoundVar(_) => {
- if is_copy(db, ty, env) {
+ TyKind::Param(_) => {
+ if infcx.type_is_copy_modulo_regions(env.env, ty) {
DropGlue::None
} else {
DropGlue::DependOnParams
}
}
- TyKind::InferenceVar(..) => unreachable!("inference vars shouldn't exist out of inference"),
- }
-}
-
-fn projection_has_drop_glue(
- db: &dyn HirDatabase,
- env: Arc<TraitEnvironment<'_>>,
- projection: ProjectionTy,
- ty: Ty,
-) -> DropGlue {
- let normalized = db.normalize_projection(projection, env.clone());
- match normalized.kind(Interner) {
- TyKind::Alias(AliasTy::Projection(_)) | TyKind::AssociatedType(..) => {
- if is_copy(db, ty, env) { DropGlue::None } else { DropGlue::DependOnParams }
+ TyKind::Infer(..) => unreachable!("inference vars shouldn't exist out of inference"),
+ TyKind::Pat(..) | TyKind::UnsafeBinder(..) => {
+ never!("we do not handle pattern and unsafe binder types");
+ DropGlue::None
}
- _ => db.has_drop_glue(normalized, env),
}
}
-
-fn is_copy(db: &dyn HirDatabase, ty: Ty, env: Arc<TraitEnvironment<'_>>) -> bool {
- let Some(copy_trait) = LangItem::Copy.resolve_trait(db, env.krate) else {
- return false;
- };
- let trait_ref = TyBuilder::trait_ref(db, copy_trait).push(ty).build();
- let goal = Canonical {
- value: InEnvironment::new(
- &env.env.to_chalk(DbInterner::new_with(db, Some(env.krate), env.block)),
- trait_ref.cast(Interner),
- ),
- binders: CanonicalVarKinds::empty(Interner),
- };
- db.trait_solve(env.krate, env.block, goal).certain()
-}
-
-pub(crate) fn has_drop_glue_cycle_result(
- _db: &dyn HirDatabase,
- _ty: Ty,
- _env: Arc<TraitEnvironment<'_>>,
-) -> DropGlue {
- DropGlue::None
-}
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 2add66d..4ff5cc5 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -24,7 +24,6 @@
mod builder;
mod chalk_db;
mod chalk_ext;
-mod drop;
mod infer;
mod inhabitedness;
mod interner;
@@ -42,6 +41,7 @@
pub mod db;
pub mod diagnostics;
pub mod display;
+pub mod drop;
pub mod dyn_compatibility;
pub mod generics;
pub mod lang_items;
@@ -94,7 +94,6 @@
pub use autoderef::autoderef;
pub use builder::{ParamKind, TyBuilder};
pub use chalk_ext::*;
-pub use drop::DropGlue;
pub use infer::{
Adjust, Adjustment, AutoBorrow, BindingMode, InferenceDiagnostic, InferenceResult,
InferenceTyDiagnosticSource, OverloadedDeref, PointerCast,
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index e1983b3..6e09cf9 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -32,7 +32,6 @@
use syntax::{SyntaxNodePtr, TextRange};
use triomphe::Arc;
-use crate::next_solver::mapping::NextSolverToChalk;
use crate::{
AliasTy, CallableDefId, ClosureId, ComplexMemoryMap, Const, ConstData, ConstScalar, Interner,
MemoryMap, Substitution, ToChalk, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind,
@@ -44,8 +43,11 @@
layout::{Layout, LayoutError, RustcEnumVariantIdx},
method_resolution::{is_dyn_method, lookup_impl_const},
next_solver::{
- DbInterner,
- mapping::{ChalkToNextSolver, convert_args_for_result, convert_ty_for_result},
+ DbInterner, TypingMode,
+ infer::{DbInternerInferExt, InferCtxt},
+ mapping::{
+ ChalkToNextSolver, NextSolverToChalk, convert_args_for_result, convert_ty_for_result,
+ },
},
static_lifetime,
traits::FnTrait,
@@ -204,6 +206,7 @@
/// Maximum count of bytes that heap and stack can grow
memory_limit: usize,
interner: DbInterner<'a>,
+ infcx: InferCtxt<'a>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -690,6 +693,7 @@
x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call_once))
}),
interner,
+ infcx: interner.infer_ctxt().build(TypingMode::non_body_analysis()),
})
}
diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs
index 54d13a8..9ef0012 100644
--- a/crates/hir-ty/src/mir/eval/shim.rs
+++ b/crates/hir-ty/src/mir/eval/shim.rs
@@ -16,8 +16,8 @@
use crate::next_solver::mapping::NextSolverToChalk;
use crate::{
- DropGlue,
display::DisplayTarget,
+ drop::{DropGlue, has_drop_glue},
error_lifetime,
mir::eval::{
Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId, HasModule, HirDisplay,
@@ -855,7 +855,11 @@
"size_of generic arg is not provided".into(),
));
};
- let result = match self.db.has_drop_glue(ty.clone(), self.trait_env.clone()) {
+ let result = match has_drop_glue(
+ &self.infcx,
+ ty.to_nextsolver(self.interner),
+ self.trait_env.clone(),
+ ) {
DropGlue::HasDropGlue => true,
DropGlue::None => false,
DropGlue::DependOnParams => {
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index ae52986..cce2564 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -82,8 +82,8 @@
method_resolution,
mir::{MutBorrowKind, interpret_mir},
next_solver::{
- ClauseKind, DbInterner, GenericArgs,
- infer::InferCtxt,
+ ClauseKind, DbInterner, GenericArgs, TypingMode,
+ infer::{DbInternerInferExt, InferCtxt},
mapping::{ChalkToNextSolver, NextSolverToChalk, convert_ty_for_result},
},
primitive::UintTy,
@@ -157,10 +157,11 @@
tt,
},
hir_ty::{
- CastError, DropGlue, FnAbi, PointerCast, Variance, attach_db, attach_db_allow_change,
+ CastError, FnAbi, PointerCast, Variance, attach_db, attach_db_allow_change,
consteval::ConstEvalError,
diagnostics::UnsafetyReason,
display::{ClosureStyle, DisplayTarget, HirDisplay, HirDisplayError, HirWrite},
+ drop::DropGlue,
dyn_compatibility::{DynCompatibilityViolation, MethodViolationCode},
layout::LayoutError,
method_resolution::TyFingerprint,
@@ -6043,7 +6044,10 @@
}
pub fn drop_glue(&self, db: &'db dyn HirDatabase) -> DropGlue {
- db.has_drop_glue(self.ty.clone(), self.env.clone())
+ let interner = DbInterner::new_with(db, Some(self.env.krate), self.env.block);
+ // FIXME: This should be `PostAnalysis` I believe.
+ let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis());
+ hir_ty::drop::has_drop_glue(&infcx, self.ty.to_nextsolver(interner), self.env.clone())
}
}