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
|
@ -102,6 +102,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
self.assemble_candidate_for_tuple(obligation, &mut candidates);
|
||||
} else if tcx.is_lang_item(def_id, LangItem::FnPtrTrait) {
|
||||
self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates);
|
||||
} else if tcx.is_lang_item(def_id, LangItem::BikeshedGuaranteedNoDrop) {
|
||||
self.assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
|
||||
obligation,
|
||||
&mut candidates,
|
||||
);
|
||||
} else {
|
||||
if tcx.is_lang_item(def_id, LangItem::Clone) {
|
||||
// Same builtin conditions as `Copy`, i.e., every type which has builtin support
|
||||
|
@ -1184,4 +1189,48 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
|
||||
&mut self,
|
||||
obligation: &PolyTraitObligation<'tcx>,
|
||||
candidates: &mut SelectionCandidateSet<'tcx>,
|
||||
) {
|
||||
match obligation.predicate.self_ty().skip_binder().kind() {
|
||||
ty::Ref(..)
|
||||
| ty::Adt(..)
|
||||
| ty::Tuple(_)
|
||||
| ty::Array(..)
|
||||
| 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::Alias(..)
|
||||
| ty::Param(_)
|
||||
| ty::Placeholder(..)
|
||||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Coroutine(..)
|
||||
| ty::UnsafeBinder(_)
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::Bound(..) => {
|
||||
candidates.vec.push(BikeshedGuaranteedNoDropCandidate);
|
||||
}
|
||||
|
||||
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
||||
candidates.ambiguous = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, Upcast};
|
|||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_type_ir::elaborate;
|
||||
use thin_vec::thin_vec;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use super::SelectionCandidate::{self, *};
|
||||
|
@ -130,6 +131,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
TraitUpcastingUnsizeCandidate(idx) => {
|
||||
self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?
|
||||
}
|
||||
|
||||
BikeshedGuaranteedNoDropCandidate => {
|
||||
self.confirm_bikeshed_guaranteed_no_drop_candidate(obligation)
|
||||
}
|
||||
};
|
||||
|
||||
// The obligations returned by confirmation are recursively evaluated
|
||||
|
@ -1346,6 +1351,93 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
_ => bug!("source: {source}, target: {target}"),
|
||||
})
|
||||
}
|
||||
|
||||
fn confirm_bikeshed_guaranteed_no_drop_candidate(
|
||||
&mut self,
|
||||
obligation: &PolyTraitObligation<'tcx>,
|
||||
) -> ImplSource<'tcx, PredicateObligation<'tcx>> {
|
||||
let mut obligations = thin_vec![];
|
||||
|
||||
let tcx = self.tcx();
|
||||
let self_ty = obligation.predicate.self_ty();
|
||||
match *self_ty.skip_binder().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) => {
|
||||
obligations.extend(tys.iter().map(|elem_ty| {
|
||||
obligation.with(
|
||||
tcx,
|
||||
self_ty.rebind(ty::TraitRef::new(
|
||||
tcx,
|
||||
obligation.predicate.def_id(),
|
||||
[elem_ty],
|
||||
)),
|
||||
)
|
||||
}));
|
||||
}
|
||||
ty::Array(elem_ty, _) => {
|
||||
obligations.push(obligation.with(
|
||||
tcx,
|
||||
self_ty.rebind(ty::TraitRef::new(
|
||||
tcx,
|
||||
obligation.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(..)
|
||||
| ty::Bound(..) => {
|
||||
obligations.push(obligation.with(
|
||||
tcx,
|
||||
self_ty.map_bound(|ty| {
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
tcx.require_lang_item(LangItem::Copy, Some(obligation.cause.span)),
|
||||
[ty],
|
||||
)
|
||||
}),
|
||||
));
|
||||
}
|
||||
|
||||
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
||||
panic!("unexpected type `{self_ty:?}`")
|
||||
}
|
||||
}
|
||||
|
||||
ImplSource::Builtin(BuiltinImplSource::Misc, obligations)
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute a goal that some RPITIT (right now, only RPITITs corresponding to Futures)
|
||||
|
|
|
@ -1949,7 +1949,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||
| TraitAliasCandidate
|
||||
| TraitUpcastingUnsizeCandidate(_)
|
||||
| BuiltinObjectCandidate
|
||||
| BuiltinUnsizeCandidate => false,
|
||||
| BuiltinUnsizeCandidate
|
||||
| BikeshedGuaranteedNoDropCandidate => false,
|
||||
// Non-global param candidates have already been handled, global
|
||||
// where-bounds get ignored.
|
||||
ParamCandidate(_) | ImplCandidate(_) => true,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue