Add built-in const impls for Clone and Copy
This commit is contained in:
parent
2888098522
commit
744c670812
5 changed files with 133 additions and 8 deletions
|
|
@ -211,10 +211,32 @@ where
|
|||
}
|
||||
|
||||
fn consider_builtin_copy_clone_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 constituent_tys =
|
||||
structural_traits::instantiate_constituent_tys_for_copy_clone_trait(ecx, self_ty)?;
|
||||
|
||||
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
|
||||
ecx.enter_forall(constituent_tys, |ecx, tys| {
|
||||
ecx.add_goals(
|
||||
GoalSource::ImplWhereBound,
|
||||
tys.into_iter().map(|ty| {
|
||||
goal.with(
|
||||
cx,
|
||||
ty::ClauseKind::HostEffect(
|
||||
goal.predicate.with_replaced_self_ty(cx, ty),
|
||||
),
|
||||
)
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
})
|
||||
}
|
||||
|
||||
fn consider_builtin_fn_ptr_trait_candidate(
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_middle::span_bug;
|
|||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::ty::elaborate::elaborate;
|
||||
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
|
||||
use rustc_middle::ty::{self, TypingMode};
|
||||
use rustc_middle::ty::{self, Ty, TypingMode};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
use super::SelectionContext;
|
||||
|
|
@ -303,6 +303,9 @@ fn evaluate_host_effect_from_builtin_impls<'tcx>(
|
|||
obligation: &HostEffectObligation<'tcx>,
|
||||
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
|
||||
match selcx.tcx().as_lang_item(obligation.predicate.def_id()) {
|
||||
Some(LangItem::Copy | LangItem::Clone) => {
|
||||
evaluate_host_effect_for_copy_clone_goal(selcx, obligation)
|
||||
}
|
||||
Some(LangItem::Destruct) => evaluate_host_effect_for_destruct_goal(selcx, obligation),
|
||||
Some(LangItem::Fn | LangItem::FnMut | LangItem::FnOnce) => {
|
||||
evaluate_host_effect_for_fn_goal(selcx, obligation)
|
||||
|
|
@ -311,6 +314,95 @@ fn evaluate_host_effect_from_builtin_impls<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
fn evaluate_host_effect_for_copy_clone_goal<'tcx>(
|
||||
selcx: &mut SelectionContext<'_, 'tcx>,
|
||||
obligation: &HostEffectObligation<'tcx>,
|
||||
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
|
||||
let tcx = selcx.tcx();
|
||||
let self_ty = obligation.predicate.self_ty();
|
||||
let constituent_tys = match *self_ty.kind() {
|
||||
// impl Copy/Clone for FnDef, FnPtr
|
||||
ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
|
||||
|
||||
// Implementations are provided in core
|
||||
ty::Uint(_)
|
||||
| ty::Int(_)
|
||||
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
||||
| ty::Bool
|
||||
| ty::Float(_)
|
||||
| ty::Char
|
||||
| ty::RawPtr(..)
|
||||
| ty::Never
|
||||
| ty::Ref(_, _, ty::Mutability::Not)
|
||||
| ty::Array(..) => Err(EvaluationFailure::NoSolution),
|
||||
|
||||
// Cannot implement in core, as we can't be generic over patterns yet,
|
||||
// so we'd have to list all patterns and type combinations.
|
||||
ty::Pat(ty, ..) => Ok(ty::Binder::dummy(vec![ty])),
|
||||
|
||||
ty::Dynamic(..)
|
||||
| ty::Str
|
||||
| ty::Slice(_)
|
||||
| ty::Foreign(..)
|
||||
| ty::Ref(_, _, ty::Mutability::Mut)
|
||||
| ty::Adt(_, _)
|
||||
| ty::Alias(_, _)
|
||||
| ty::Param(_)
|
||||
| ty::Placeholder(..) => Err(EvaluationFailure::NoSolution),
|
||||
|
||||
ty::Bound(..)
|
||||
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
||||
panic!("unexpected type `{self_ty:?}`")
|
||||
}
|
||||
|
||||
// impl Copy/Clone for (T1, T2, .., Tn) where T1: Copy/Clone, T2: Copy/Clone, .. Tn: Copy/Clone
|
||||
ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.to_vec())),
|
||||
|
||||
// impl Copy/Clone for Closure where Self::TupledUpvars: Copy/Clone
|
||||
ty::Closure(_, args) => Ok(ty::Binder::dummy(vec![args.as_closure().tupled_upvars_ty()])),
|
||||
|
||||
// impl Copy/Clone for CoroutineClosure where Self::TupledUpvars: Copy/Clone
|
||||
ty::CoroutineClosure(_, args) => {
|
||||
Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
|
||||
}
|
||||
|
||||
// only when `coroutine_clone` is enabled and the coroutine is movable
|
||||
// impl Copy/Clone for Coroutine where T: Copy/Clone forall T in (upvars, witnesses)
|
||||
ty::Coroutine(def_id, args) => match tcx.coroutine_movability(def_id) {
|
||||
ty::Movability::Static => Err(EvaluationFailure::NoSolution),
|
||||
ty::Movability::Movable => {
|
||||
if tcx.features().coroutine_clone() {
|
||||
Ok(ty::Binder::dummy(vec![
|
||||
args.as_coroutine().tupled_upvars_ty(),
|
||||
Ty::new_coroutine_witness_for_coroutine(tcx, def_id, args),
|
||||
]))
|
||||
} else {
|
||||
Err(EvaluationFailure::NoSolution)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
ty::UnsafeBinder(_) => Err(EvaluationFailure::NoSolution),
|
||||
|
||||
// impl Copy/Clone for CoroutineWitness where T: Copy/Clone forall T in coroutine_hidden_types
|
||||
ty::CoroutineWitness(def_id, args) => Ok(tcx
|
||||
.coroutine_hidden_types(def_id)
|
||||
.instantiate(tcx, args)
|
||||
.map_bound(|bound| bound.types.to_vec())),
|
||||
}?;
|
||||
|
||||
Ok(constituent_tys
|
||||
.iter()
|
||||
.map(|ty| {
|
||||
obligation.with(
|
||||
tcx,
|
||||
ty.map_bound(|ty| ty::TraitRef::new(tcx, obligation.predicate.def_id(), [ty]))
|
||||
.to_host_effect_clause(tcx, obligation.predicate.constness),
|
||||
)
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
// NOTE: Keep this in sync with `const_conditions_for_destruct` in the new solver.
|
||||
fn evaluate_host_effect_for_destruct_goal<'tcx>(
|
||||
selcx: &mut SelectionContext<'_, 'tcx>,
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ impl<I: Interner> ty::Binder<I, TraitRef<I>> {
|
|||
}
|
||||
|
||||
pub fn to_host_effect_clause(self, cx: I, constness: BoundConstness) -> I::Clause {
|
||||
self.map_bound(|trait_ref| {
|
||||
self.map_bound(|trait_ref: TraitRef<I>| {
|
||||
ty::ClauseKind::HostEffect(HostEffectPredicate { trait_ref, constness })
|
||||
})
|
||||
.upcast(cx)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//@ run-pass
|
||||
//@ check-pass
|
||||
#![feature(const_trait_impl, const_default)]
|
||||
#![allow(dead_code)]
|
||||
// alloc::string
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
//@ run-pass
|
||||
//@ check-pass
|
||||
#![feature(
|
||||
const_trait_impl, const_default, ptr_alignment_type, ascii_char, f16, f128, sync_unsafe_cell,
|
||||
const_clone,
|
||||
const_default,
|
||||
const_trait_impl,
|
||||
ptr_alignment_type,
|
||||
ascii_char,
|
||||
f16,
|
||||
f128,
|
||||
sync_unsafe_cell,
|
||||
)]
|
||||
#![allow(dead_code)]
|
||||
// core::default
|
||||
|
|
@ -43,4 +50,8 @@ const REF_CELL: std::cell::RefCell<()> = Default::default();
|
|||
const UNSAFE_CELL: std::cell::UnsafeCell<()> = Default::default();
|
||||
const SYNC_UNSAFE_CELL: std::cell::SyncUnsafeCell<()> = Default::default();
|
||||
|
||||
// `Clone` for tuples
|
||||
const BUILTIN_CLONE: () = ().clone();
|
||||
const BUILTIN_CLONE_2: (u32, i32) = (42, 100).clone();
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue