Implement and use BikeshedGuaranteedNoDrop for union/unsafe field validity
This commit is contained in:
parent
c72d443cdd
commit
516afd557c
21 changed files with 365 additions and 66 deletions
|
@ -267,6 +267,11 @@ where
|
|||
goal: Goal<I, Self>,
|
||||
) -> Result<Candidate<I>, NoSolution>;
|
||||
|
||||
fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
|
||||
ecx: &mut EvalCtxt<'_, D>,
|
||||
goal: Goal<I, Self>,
|
||||
) -> Result<Candidate<I>, NoSolution>;
|
||||
|
||||
/// Consider (possibly several) candidates to upcast or unsize a type to another
|
||||
/// type, excluding the coercion of a sized type into a `dyn Trait`.
|
||||
///
|
||||
|
@ -478,6 +483,9 @@ where
|
|||
Some(TraitSolverLangItem::TransmuteTrait) => {
|
||||
G::consider_builtin_transmute_candidate(self, goal)
|
||||
}
|
||||
Some(TraitSolverLangItem::BikeshedGuaranteedNoDrop) => {
|
||||
G::consider_builtin_bikeshed_guaranteed_no_drop_candidate(self, goal)
|
||||
}
|
||||
_ => Err(NoSolution),
|
||||
}
|
||||
};
|
||||
|
|
|
@ -374,6 +374,13 @@ where
|
|||
unreachable!("TransmuteFrom is not const")
|
||||
}
|
||||
|
||||
fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, D>,
|
||||
_goal: Goal<I, Self>,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
unreachable!("BikeshedGuaranteedNoDrop is not const");
|
||||
}
|
||||
|
||||
fn consider_structural_builtin_unsize_candidates(
|
||||
_ecx: &mut EvalCtxt<'_, D>,
|
||||
_goal: Goal<I, Self>,
|
||||
|
|
|
@ -942,6 +942,13 @@ where
|
|||
) -> Result<Candidate<I>, NoSolution> {
|
||||
panic!("`TransmuteFrom` does not have an associated type: {:?}", goal)
|
||||
}
|
||||
|
||||
fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, D>,
|
||||
goal: Goal<I, Self>,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
unreachable!("`BikeshedGuaranteedNoDrop` does not have an associated type: {:?}", goal)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D, I> EvalCtxt<'_, D>
|
||||
|
|
|
@ -625,6 +625,101 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
/// NOTE: This is implemented as a built-in goal and not a set of impls like:
|
||||
///
|
||||
/// ```
|
||||
/// impl<T> BikeshedGuaranteedNoDrop for T where T: Copy {}
|
||||
/// impl<T> BikeshedGuaranteedNoDrop for ManuallyDrop<T> {}
|
||||
/// ```
|
||||
///
|
||||
/// because these impls overlap, and I'd rather not build a coherence hack for
|
||||
/// this harmless overlap.
|
||||
fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
|
||||
ecx: &mut EvalCtxt<'_, D>,
|
||||
goal: Goal<I, Self>,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
let cx = ecx.cx();
|
||||
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
|
||||
let ty = goal.predicate.self_ty();
|
||||
match ty.kind() {
|
||||
// `&mut T` and `&T` always implement `BikeshedGuaranteedNoDrop`.
|
||||
ty::Ref(..) => {}
|
||||
// `ManuallyDrop<T>` always implements `BikeshedGuaranteedNoDrop`.
|
||||
ty::Adt(def, _) if def.is_manually_drop() => {}
|
||||
// Arrays and tuples implement `BikeshedGuaranteedNoDrop` only if
|
||||
// their constituent types implement `BikeshedGuaranteedNoDrop`.
|
||||
ty::Tuple(tys) => {
|
||||
ecx.add_goals(
|
||||
GoalSource::ImplWhereBound,
|
||||
tys.iter().map(|elem_ty| {
|
||||
goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty]))
|
||||
}),
|
||||
);
|
||||
}
|
||||
ty::Array(elem_ty, _) => {
|
||||
ecx.add_goal(
|
||||
GoalSource::ImplWhereBound,
|
||||
goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty])),
|
||||
);
|
||||
}
|
||||
|
||||
// All other types implement `BikeshedGuaranteedNoDrop` only if
|
||||
// they implement `Copy`. We could be smart here and short-circuit
|
||||
// some trivially `Copy`/`!Copy` types, but there's no benefit.
|
||||
ty::FnDef(..)
|
||||
| ty::FnPtr(..)
|
||||
| ty::Error(_)
|
||||
| ty::Uint(_)
|
||||
| ty::Int(_)
|
||||
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
||||
| ty::Bool
|
||||
| ty::Float(_)
|
||||
| ty::Char
|
||||
| ty::RawPtr(..)
|
||||
| ty::Never
|
||||
| ty::Pat(..)
|
||||
| ty::Dynamic(..)
|
||||
| ty::Str
|
||||
| ty::Slice(_)
|
||||
| ty::Foreign(..)
|
||||
| ty::Adt(..)
|
||||
| ty::Alias(..)
|
||||
| ty::Param(_)
|
||||
| ty::Placeholder(..)
|
||||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Coroutine(..)
|
||||
| ty::UnsafeBinder(_)
|
||||
| ty::CoroutineWitness(..) => {
|
||||
ecx.add_goal(
|
||||
GoalSource::ImplWhereBound,
|
||||
goal.with(
|
||||
cx,
|
||||
ty::TraitRef::new(
|
||||
cx,
|
||||
cx.require_lang_item(TraitSolverLangItem::Copy),
|
||||
[ty],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
ty::Bound(..)
|
||||
| ty::Infer(
|
||||
ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
|
||||
) => {
|
||||
panic!("unexpected type `{ty:?}`")
|
||||
}
|
||||
}
|
||||
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
})
|
||||
}
|
||||
|
||||
/// ```ignore (builtin impl example)
|
||||
/// trait Trait {
|
||||
/// fn foo(&self);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue