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())
     }
 }