summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_transmute/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_transmute/src')
-rw-r--r--compiler/rustc_transmute/src/layout/dfa.rs1
-rw-r--r--compiler/rustc_transmute/src/layout/nfa.rs6
-rw-r--r--compiler/rustc_transmute/src/layout/tree.rs36
-rw-r--r--compiler/rustc_transmute/src/lib.rs73
-rw-r--r--compiler/rustc_transmute/src/maybe_transmutable/mod.rs6
-rw-r--r--compiler/rustc_transmute/src/maybe_transmutable/query_context.rs2
-rw-r--r--compiler/rustc_transmute/src/maybe_transmutable/tests.rs4
7 files changed, 84 insertions, 44 deletions
diff --git a/compiler/rustc_transmute/src/layout/dfa.rs b/compiler/rustc_transmute/src/layout/dfa.rs
index b60ea6e7a..b8922696e 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 f25e3c1fd..c2bc47bc0 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/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 70b3ba02b..211c813b8 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -1,4 +1,5 @@
use super::{Byte, Def, Ref};
+use std::ops::ControlFlow;
#[cfg(test)]
mod tests;
@@ -86,17 +87,18 @@ where
F: Fn(D) -> bool,
{
match self {
- Self::Seq(elts) => elts
- .into_iter()
- .map(|elt| elt.prune(f))
- .try_fold(Tree::unit(), |elts, elt| {
+ Self::Seq(elts) => match elts.into_iter().map(|elt| elt.prune(f)).try_fold(
+ Tree::unit(),
+ |elts, elt| {
if elt == Tree::uninhabited() {
- Err(Tree::uninhabited())
+ ControlFlow::Break(Tree::uninhabited())
} else {
- Ok(elts.then(elt))
+ ControlFlow::Continue(elts.then(elt))
}
- })
- .into_ok_or_err(),
+ },
+ ) {
+ ControlFlow::Break(node) | ControlFlow::Continue(node) => node,
+ },
Self::Alt(alts) => alts
.into_iter()
.map(|alt| alt.prune(f))
@@ -315,7 +317,7 @@ pub(crate) mod rustc {
tcx,
)?,
AdtKind::Enum => {
- tracing::trace!(?adt_def, "treeifying enum");
+ trace!(?adt_def, "treeifying enum");
let mut tree = Tree::uninhabited();
for (idx, discr) in adt_def.discriminants(tcx) {
@@ -379,7 +381,7 @@ pub(crate) mod rustc {
let clamp =
|align: Align| align.clamp(min_align, max_align).bytes().try_into().unwrap();
- let variant_span = tracing::trace_span!(
+ let variant_span = trace_span!(
"treeifying variant",
min_align = ?min_align,
max_align = ?max_align,
@@ -394,27 +396,27 @@ pub(crate) mod rustc {
// The layout of the variant is prefixed by the discriminant, if any.
if let Some(discr) = discr {
- tracing::trace!(?discr, "treeifying discriminant");
+ trace!(?discr, "treeifying discriminant");
let discr_layout = alloc::Layout::from_size_align(
layout_summary.discriminant_size,
clamp(layout_summary.discriminant_align),
)
.unwrap();
- tracing::trace!(?discr_layout, "computed discriminant layout");
+ trace!(?discr_layout, "computed discriminant layout");
variant_layout = variant_layout.extend(discr_layout).unwrap().0;
tree = tree.then(Self::from_disr(discr, tcx, layout_summary.discriminant_size));
}
// Next come fields.
- let fields_span = tracing::trace_span!("treeifying fields").entered();
+ let fields_span = trace_span!("treeifying fields").entered();
for field_def in variant_def.fields.iter() {
let field_ty = field_def.ty(tcx, substs_ref);
- let _span = tracing::trace_span!("treeifying field", field = ?field_ty).entered();
+ let _span = trace_span!("treeifying field", field = ?field_ty).entered();
// begin with the field's visibility
tree = tree.then(Self::def(Def::Field(field_def)));
- // compute the field's layout charactaristics
+ // compute the field's layout characteristics
let field_layout = layout_of(tcx, field_ty)?.clamp_align(min_align, max_align);
// next comes the field's padding
@@ -432,7 +434,7 @@ pub(crate) mod rustc {
drop(fields_span);
// finally: padding
- let padding_span = tracing::trace_span!("adding trailing padding").entered();
+ let padding_span = trace_span!("adding trailing padding").entered();
let padding_needed = layout_summary.total_size - variant_layout.size();
if padding_needed > 0 {
tree = tree.then(Self::padding(padding_needed));
@@ -465,7 +467,7 @@ pub(crate) mod rustc {
layout.align().abi.bytes().try_into().unwrap(),
)
.unwrap();
- tracing::trace!(?ty, ?layout, "computed layout for type");
+ trace!(?ty, ?layout, "computed layout for type");
Ok(layout)
}
}
diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs
index cfc7c752a..64cd70d36 100644
--- a/compiler/rustc_transmute/src/lib.rs
+++ b/compiler/rustc_transmute/src/lib.rs
@@ -1,21 +1,12 @@
-#![feature(
- alloc_layout_extra,
- control_flow_enum,
- decl_macro,
- iterator_try_reduce,
- never_type,
- result_into_ok_or_err
-)]
+#![feature(alloc_layout_extra, control_flow_enum, decl_macro, iterator_try_reduce, never_type)]
#![allow(dead_code, unused_variables)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
#[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;
@@ -24,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?"
@@ -67,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)]
@@ -111,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 076d922d1..1186eac37 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
@@ -105,12 +105,12 @@ 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);
- tracing::trace!(?src, "pruned src");
+ trace!(?src, "pruned src");
// Remove all `Def` nodes from `dst`, additionally...
let dst = if assume_visibility {
@@ -121,7 +121,7 @@ where
dst.prune(&|def| context.is_accessible_from(def, scope))
};
- tracing::trace!(?dst, "pruned dst");
+ trace!(?dst, "pruned dst");
// Convert `src` from a tree-based representation to an NFA-based representation.
// If the conversion fails because `src` is uninhabited, conclude that the transmutation
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
index 9c2cf4c9a..adab343ac 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
@@ -82,7 +82,7 @@ mod rustc {
false
};
- tracing::trace!(?ret, "ret");
+ trace!(?ret, "ret");
ret
}
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
index d9d125687..4d5772a4f 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();