diff options
| author | bors <bors@rust-lang.org> | 2022-09-04 07:55:44 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-09-04 07:55:44 +0000 |
| commit | 8521a8c92da6c0c845d4f6394e903651a227946a (patch) | |
| tree | 18fff039f86b368a19865a2c5a563987ef4185d3 /compiler | |
| parent | c2d140bd36e7fcdc894b7c342fd81a63fdd66373 (diff) | |
| parent | fbcc038a224e58f7d3aca25c7f2321f11ce5513d (diff) | |
| download | rust-8521a8c92da6c0c845d4f6394e903651a227946a.tar.gz rust-8521a8c92da6c0c845d4f6394e903651a227946a.zip | |
Auto merge of #100726 - jswrenn:transmute, r=oli-obk
safe transmute: use `Assume` struct to provide analysis options
This task was left as a TODO in #92268; resolving it brings [`BikeshedIntrinsicFrom`](https://doc.rust-lang.org/nightly/core/mem/trait.BikeshedIntrinsicFrom.html) more in line with the API defined in [MCP411](https://github.com/rust-lang/compiler-team/issues/411).
**Before:**
```rust
pub unsafe trait BikeshedIntrinsicFrom<
Src,
Context,
const ASSUME_ALIGNMENT: bool,
const ASSUME_LIFETIMES: bool,
const ASSUME_VALIDITY: bool,
const ASSUME_VISIBILITY: bool,
> where
Src: ?Sized,
{}
```
**After:**
```rust
pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }>
where
Src: ?Sized,
{}
```
`Assume::visibility` has also been renamed to `Assume::safety`, as library safety invariants are what's actually being assumed; visibility is just the mechanism by which it is currently checked (and that may change).
r? `@oli-obk`
---
Related:
- https://github.com/rust-lang/compiler-team/issues/411
- https://github.com/rust-lang/rust/issues/99571
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_hir/src/lang_items.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_span/src/symbol.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/select/confirmation.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_transmute/Cargo.toml | 5 | ||||
| -rw-r--r-- | compiler/rustc_transmute/src/layout/dfa.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_transmute/src/layout/nfa.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_transmute/src/lib.rs | 62 | ||||
| -rw-r--r-- | compiler/rustc_transmute/src/maybe_transmutable/mod.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_transmute/src/maybe_transmutable/tests.rs | 4 |
9 files changed, 73 insertions, 35 deletions
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 0c01326d003..f19d07d98dc 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -193,7 +193,8 @@ language_item_table! { DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait, GenericRequirement::Minimum(1); // language items relating to transmutability - TransmuteTrait, sym::transmute_trait, transmute_trait, Target::Trait, GenericRequirement::Exact(6); + TransmuteOpts, sym::transmute_opts, transmute_opts, Target::Struct, GenericRequirement::Exact(0); + TransmuteTrait, sym::transmute_trait, transmute_trait, Target::Trait, GenericRequirement::Exact(3); Add(Op), sym::add, add_trait, Target::Trait, GenericRequirement::Exact(1); Sub(Op), sym::sub, sub_trait, Target::Trait, GenericRequirement::Exact(1); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 64b919587e8..c501fba21c6 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -339,6 +339,7 @@ symbols! { alias, align, align_offset, + alignment, alignstack, all, alloc, @@ -866,6 +867,7 @@ symbols! { lib, libc, lifetime, + lifetimes, likely, line, line_macro, @@ -1294,6 +1296,7 @@ symbols! { rustfmt, rvalue_static_promotion, s, + safety, sanitize, sanitizer_runtime, saturating_add, @@ -1478,6 +1481,7 @@ symbols! { trait_alias, trait_upcasting, transmute, + transmute_opts, transmute_trait, transparent, transparent_enums, @@ -1573,6 +1577,7 @@ symbols! { va_list, va_start, val, + validity, values, var, variant_count, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 2a1099fc82a..e44f6665795 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -279,29 +279,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let predicate = obligation.predicate; let type_at = |i| predicate.map_bound(|p| p.trait_ref.substs.type_at(i)); - let bool_at = |i| { - predicate - .skip_binder() - .trait_ref - .substs - .const_at(i) - .try_eval_bool(self.tcx(), obligation.param_env) - .unwrap_or(true) - }; + let const_at = |i| predicate.skip_binder().trait_ref.substs.const_at(i); let src_and_dst = predicate.map_bound(|p| rustc_transmute::Types { - src: p.trait_ref.substs.type_at(1), dst: p.trait_ref.substs.type_at(0), + src: p.trait_ref.substs.type_at(1), }); let scope = type_at(2).skip_binder(); - let assume = rustc_transmute::Assume { - alignment: bool_at(3), - lifetimes: bool_at(4), - validity: bool_at(5), - visibility: bool_at(6), - }; + let assume = + rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, const_at(3)); let cause = obligation.cause.clone(); diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml index 9dc96e08a8e..aa6fe7d2419 100644 --- a/compiler/rustc_transmute/Cargo.toml +++ b/compiler/rustc_transmute/Cargo.toml @@ -7,7 +7,8 @@ edition = "2021" [dependencies] tracing = "0.1" -rustc_data_structures = { path = "../rustc_data_structures", optional = true} +rustc_data_structures = { path = "../rustc_data_structures"} +rustc_hir = { path = "../rustc_hir", optional = true} rustc_infer = { path = "../rustc_infer", optional = true} rustc_macros = { path = "../rustc_macros", optional = true} rustc_middle = { path = "../rustc_middle", optional = true} @@ -17,7 +18,7 @@ rustc_target = { path = "../rustc_target", optional = true} [features] rustc = [ "rustc_middle", - "rustc_data_structures", + "rustc_hir", "rustc_infer", "rustc_macros", "rustc_span", diff --git a/compiler/rustc_transmute/src/layout/dfa.rs b/compiler/rustc_transmute/src/layout/dfa.rs index b60ea6e7a24..b8922696e30 100644 --- a/compiler/rustc_transmute/src/layout/dfa.rs +++ b/compiler/rustc_transmute/src/layout/dfa.rs @@ -104,7 +104,6 @@ where } #[instrument(level = "debug")] - #[cfg_attr(feature = "rustc", allow(rustc::potential_query_instability))] pub(crate) fn from_nfa(nfa: Nfa<R>) -> Self { let Nfa { transitions: nfa_transitions, start: nfa_start, accepting: nfa_accepting } = nfa; diff --git a/compiler/rustc_transmute/src/layout/nfa.rs b/compiler/rustc_transmute/src/layout/nfa.rs index f25e3c1fd8a..c2bc47bc043 100644 --- a/compiler/rustc_transmute/src/layout/nfa.rs +++ b/compiler/rustc_transmute/src/layout/nfa.rs @@ -119,8 +119,6 @@ where let mut transitions: Map<State, Map<Transition<R>, Set<State>>> = self.transitions; - // the iteration order doesn't matter - #[cfg_attr(feature = "rustc", allow(rustc::potential_query_instability))] for (source, transition) in other.transitions { let fix_state = |state| if state == other.start { self.accepting } else { state }; let entry = transitions.entry(fix_state(source)).or_default(); @@ -142,8 +140,6 @@ where let mut transitions: Map<State, Map<Transition<R>, Set<State>>> = self.transitions.clone(); - // the iteration order doesn't matter - #[cfg_attr(feature = "rustc", allow(rustc::potential_query_instability))] for (&(mut source), transition) in other.transitions.iter() { // if source is starting state of `other`, replace with starting state of `self` if source == other.start { @@ -152,8 +148,6 @@ where let entry = transitions.entry(source).or_default(); for (edge, destinations) in transition { let entry = entry.entry(edge.clone()).or_default(); - // the iteration order doesn't matter - #[cfg_attr(feature = "rustc", allow(rustc::potential_query_instability))] for &(mut destination) in destinations { // if dest is accepting state of `other`, replace with accepting state of `self` if destination == other.accepting { diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index 89b1ce5abe9..64cd70d3678 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -6,11 +6,7 @@ #[macro_use] extern crate tracing; -#[cfg(feature = "rustc")] -pub(crate) use rustc_data_structures::fx::{FxHashMap as Map, FxHashSet as Set}; - -#[cfg(not(feature = "rustc"))] -pub(crate) use std::collections::{HashMap as Map, HashSet as Set}; +pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set}; pub(crate) mod layout; pub(crate) mod maybe_transmutable; @@ -19,8 +15,8 @@ pub(crate) mod maybe_transmutable; pub struct Assume { pub alignment: bool, pub lifetimes: bool, + pub safety: bool, pub validity: bool, - pub visibility: bool, } /// The type encodes answers to the question: "Are these types transmutable?" @@ -62,11 +58,17 @@ pub enum Reason { #[cfg(feature = "rustc")] mod rustc { + use super::*; + + use rustc_hir::lang_items::LangItem; use rustc_infer::infer::InferCtxt; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::Binder; + use rustc_middle::ty::Const; + use rustc_middle::ty::ParamEnv; use rustc_middle::ty::Ty; + use rustc_middle::ty::TyCtxt; /// The source and destination types of a transmutation. #[derive(TypeFoldable, TypeVisitable, Debug, Clone, Copy)] @@ -106,6 +108,54 @@ mod rustc { .answer() } } + + impl Assume { + /// Constructs an `Assume` from a given const-`Assume`. + pub fn from_const<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + c: Const<'tcx>, + ) -> Self { + use rustc_middle::ty::ScalarInt; + use rustc_middle::ty::TypeVisitable; + use rustc_span::symbol::sym; + + let c = c.eval(tcx, param_env); + + if let Some(err) = c.error_reported() { + return Self { alignment: true, lifetimes: true, safety: true, validity: true }; + } + + let adt_def = c.ty().ty_adt_def().expect("The given `Const` must be an ADT."); + + assert_eq!( + tcx.require_lang_item(LangItem::TransmuteOpts, None), + adt_def.did(), + "The given `Const` was not marked with the `{}` lang item.", + LangItem::TransmuteOpts.name(), + ); + + let variant = adt_def.non_enum_variant(); + let fields = c.to_valtree().unwrap_branch(); + + let get_field = |name| { + let (field_idx, _) = variant + .fields + .iter() + .enumerate() + .find(|(_, field_def)| name == field_def.name) + .expect(&format!("There were no fields named `{name}`.")); + fields[field_idx].unwrap_leaf() == ScalarInt::TRUE + }; + + Self { + alignment: get_field(sym::alignment), + lifetimes: get_field(sym::lifetimes), + safety: get_field(sym::safety), + validity: get_field(sym::validity), + } + } + } } #[cfg(feature = "rustc")] diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs index 248ff1ec241..1186eac37ab 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs @@ -105,7 +105,7 @@ where #[inline(always)] #[instrument(level = "debug", skip(self), fields(src = ?self.src, dst = ?self.dst))] pub(crate) fn answer(self) -> Answer<<C as QueryContext>::Ref> { - let assume_visibility = self.assume.visibility; + let assume_visibility = self.assume.safety; let query_or_answer = self.map_layouts(|src, dst, scope, context| { // Remove all `Def` nodes from `src`, without checking their visibility. let src = src.prune(&|def| true); diff --git a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs index d9d125687f6..4d5772a4f2e 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs @@ -13,7 +13,7 @@ mod bool { layout::Tree::<Def, !>::bool(), layout::Tree::<Def, !>::bool(), (), - crate::Assume { alignment: false, lifetimes: false, validity: true, visibility: false }, + crate::Assume { alignment: false, lifetimes: false, validity: true, safety: false }, UltraMinimal, ) .answer(); @@ -26,7 +26,7 @@ mod bool { layout::Dfa::<!>::bool(), layout::Dfa::<!>::bool(), (), - crate::Assume { alignment: false, lifetimes: false, validity: true, visibility: false }, + crate::Assume { alignment: false, lifetimes: false, validity: true, safety: false }, UltraMinimal, ) .answer(); |
