diff options
| author | Michael Goulet <michael@errs.io> | 2024-10-29 20:08:55 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2024-11-22 16:54:40 +0000 |
| commit | 59408add4d67e7e04fa1dcf378e4e1cc71c6ff48 (patch) | |
| tree | b9d50a919f1f8667097b6236cc177c4029b9019a /compiler/rustc_next_trait_solver | |
| parent | a7d9ebdf088f166e91759ec5b3b0625e3c1d0c82 (diff) | |
| download | rust-59408add4d67e7e04fa1dcf378e4e1cc71c6ff48.tar.gz rust-59408add4d67e7e04fa1dcf378e4e1cc71c6ff48.zip | |
Implement ~const Destruct in new solver
Diffstat (limited to 'compiler/rustc_next_trait_solver')
| -rw-r--r-- | compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs | 74 | ||||
| -rw-r--r-- | compiler/rustc_next_trait_solver/src/solve/effect_goals.rs | 27 |
2 files changed, 97 insertions, 4 deletions
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index a56febec48c..05ce61bc067 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -12,7 +12,7 @@ use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use tracing::instrument; use crate::delegate::SolverDelegate; -use crate::solve::{EvalCtxt, Goal, NoSolution}; +use crate::solve::{AdtDestructorKind, EvalCtxt, Goal, NoSolution}; // Calculates the constituent types of a type for `auto trait` purposes. #[instrument(level = "trace", skip(ecx), ret)] @@ -703,6 +703,78 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>( } } +pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>( + cx: I, + self_ty: I::Ty, +) -> Result<Vec<ty::TraitRef<I>>, NoSolution> { + let destruct_def_id = cx.require_lang_item(TraitSolverLangItem::Destruct); + + match self_ty.kind() { + // An ADT is `~const Destruct` only if all of the fields are, + // *and* if there is a `Drop` impl, that `Drop` impl is also `~const`. + ty::Adt(adt_def, args) => { + let mut const_conditions: Vec<_> = adt_def + .all_field_tys(cx) + .iter_instantiated(cx, args) + .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty])) + .collect(); + match adt_def.destructor(cx) { + // `Drop` impl exists, but it's not const. Type cannot be `~const Destruct`. + Some(AdtDestructorKind::NotConst) => return Err(NoSolution), + // `Drop` impl exists, and it's const. Require `Ty: ~const Drop` to hold. + Some(AdtDestructorKind::Const) => { + let drop_def_id = cx.require_lang_item(TraitSolverLangItem::Drop); + let drop_trait_ref = ty::TraitRef::new(cx, drop_def_id, [self_ty]); + const_conditions.push(drop_trait_ref); + } + // No `Drop` impl, no need to require anything else. + None => {} + } + Ok(const_conditions) + } + + ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => { + Ok(vec![ty::TraitRef::new(cx, destruct_def_id, [ty])]) + } + + ty::Tuple(tys) => Ok(tys + .iter() + .map(|field_ty| ty::TraitRef::new(cx, destruct_def_id, [field_ty])) + .collect()), + + // Trivially implement `~const Destruct` + ty::Bool + | ty::Char + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Str + | ty::RawPtr(..) + | ty::Ref(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::Never + | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_)) + | ty::Error(_) => Ok(vec![]), + + // Coroutines and closures could implement `~const Drop`, + // but they don't really need to right now. + ty::Closure(_, _) + | ty::CoroutineClosure(_, _) + | ty::Coroutine(_, _) + | ty::CoroutineWitness(_, _) => Err(NoSolution), + + ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => { + Err(NoSolution) + } + + ty::Bound(..) + | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { + panic!("unexpected type `{self_ty:?}`") + } + } +} + /// Assemble a list of predicates that would be present on a theoretical /// user impl for an object type. These predicates must be checked any time /// we assemble a built-in object candidate for an object type, since they diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 603a68eb890..81b5199002b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -84,6 +84,10 @@ where let cx = ecx.cx(); let mut candidates = vec![]; + if !ecx.cx().alias_has_const_conditions(alias_ty.def_id) { + return vec![]; + } + for clause in elaborate::elaborate( cx, cx.explicit_implied_const_bounds(alias_ty.def_id) @@ -338,10 +342,27 @@ where } fn consider_builtin_destruct_candidate( - _ecx: &mut EvalCtxt<'_, D>, - _goal: Goal<I, Self>, + ecx: &mut EvalCtxt<'_, D>, + goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { - Err(NoSolution) + let cx = ecx.cx(); + + let self_ty = goal.predicate.self_ty(); + let const_conditions = structural_traits::const_conditions_for_destruct(cx, self_ty)?; + + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + ecx.add_goals( + GoalSource::Misc, + const_conditions.into_iter().map(|trait_ref| { + goal.with( + cx, + ty::Binder::dummy(trait_ref) + .to_host_effect_clause(cx, goal.predicate.constness), + ) + }), + ); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } fn consider_builtin_transmute_candidate( |
