mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Separate transmute checking from typeck.
This commit is contained in:
@@ -83,14 +83,6 @@ pub(in super::super) fn check_casts(&mut self) {
|
||||
*self.deferred_cast_checks.borrow_mut() = deferred_cast_checks;
|
||||
}
|
||||
|
||||
pub(in super::super) fn check_transmutes(&self) {
|
||||
let mut deferred_transmute_checks = self.deferred_transmute_checks.borrow_mut();
|
||||
debug!("FnCtxt::check_transmutes: {} deferred checks", deferred_transmute_checks.len());
|
||||
for (from, to, hir_id) in deferred_transmute_checks.drain(..) {
|
||||
self.check_transmute(from, to, hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
pub(in super::super) fn check_asms(&self) {
|
||||
let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut();
|
||||
debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use tracing::trace;
|
||||
|
||||
use super::FnCtxt;
|
||||
|
||||
/// If the type is `Option<T>`, it will return `T`, otherwise
|
||||
/// the type itself. Works on most `Option`-like types.
|
||||
fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
@@ -39,119 +38,115 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
ty
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
/// FIXME: Move this check out of typeck, since it'll easily cycle when revealing opaques,
|
||||
/// and we shouldn't need to check anything here if the typeck results are tainted.
|
||||
pub(crate) fn check_transmute(&self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId) {
|
||||
let tcx = self.tcx;
|
||||
let dl = &tcx.data_layout;
|
||||
let span = tcx.hir_span(hir_id);
|
||||
let normalize = |ty| {
|
||||
let ty = self.resolve_vars_if_possible(ty);
|
||||
if let Ok(ty) =
|
||||
self.tcx.try_normalize_erasing_regions(self.typing_env(self.param_env), ty)
|
||||
{
|
||||
ty
|
||||
} else {
|
||||
Ty::new_error_with_message(
|
||||
tcx,
|
||||
span,
|
||||
"tried to normalize non-wf type in check_transmute",
|
||||
)
|
||||
}
|
||||
};
|
||||
let from = normalize(from);
|
||||
let to = normalize(to);
|
||||
trace!(?from, ?to);
|
||||
if from.has_non_region_infer() || to.has_non_region_infer() {
|
||||
// Note: this path is currently not reached in any test, so any
|
||||
// example that triggers this would be worth minimizing and
|
||||
// converting into a test.
|
||||
self.dcx().span_bug(span, "argument to transmute has inference variables");
|
||||
fn check_transmute<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
typing_env: ty::TypingEnv<'tcx>,
|
||||
from: Ty<'tcx>,
|
||||
to: Ty<'tcx>,
|
||||
hir_id: HirId,
|
||||
) {
|
||||
let dl = &tcx.data_layout;
|
||||
let span = tcx.hir_span(hir_id);
|
||||
let normalize = |ty| {
|
||||
if let Ok(ty) = tcx.try_normalize_erasing_regions(typing_env, ty) {
|
||||
ty
|
||||
} else {
|
||||
Ty::new_error_with_message(
|
||||
tcx,
|
||||
span,
|
||||
format!("tried to normalize non-wf type {ty:#?} in check_transmute"),
|
||||
)
|
||||
}
|
||||
// Transmutes that are only changing lifetimes are always ok.
|
||||
if from == to {
|
||||
};
|
||||
let from = normalize(from);
|
||||
let to = normalize(to);
|
||||
trace!(?from, ?to);
|
||||
if from.has_non_region_infer() || to.has_non_region_infer() {
|
||||
// Note: this path is currently not reached in any test, so any
|
||||
// example that triggers this would be worth minimizing and
|
||||
// converting into a test.
|
||||
tcx.sess.dcx().span_bug(span, "argument to transmute has inference variables");
|
||||
}
|
||||
// Transmutes that are only changing lifetimes are always ok.
|
||||
if from == to {
|
||||
return;
|
||||
}
|
||||
|
||||
let skel = |ty| SizeSkeleton::compute(ty, tcx, typing_env);
|
||||
let sk_from = skel(from);
|
||||
let sk_to = skel(to);
|
||||
trace!(?sk_from, ?sk_to);
|
||||
|
||||
// Check for same size using the skeletons.
|
||||
if let (Ok(sk_from), Ok(sk_to)) = (sk_from, sk_to) {
|
||||
if sk_from.same_size(sk_to) {
|
||||
return;
|
||||
}
|
||||
|
||||
let skel = |ty| SizeSkeleton::compute(ty, tcx, self.typing_env(self.param_env));
|
||||
let sk_from = skel(from);
|
||||
let sk_to = skel(to);
|
||||
trace!(?sk_from, ?sk_to);
|
||||
|
||||
// Check for same size using the skeletons.
|
||||
if let (Ok(sk_from), Ok(sk_to)) = (sk_from, sk_to) {
|
||||
if sk_from.same_size(sk_to) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Special-case transmuting from `typeof(function)` and
|
||||
// `Option<typeof(function)>` to present a clearer error.
|
||||
let from = unpack_option_like(tcx, from);
|
||||
if let (&ty::FnDef(..), SizeSkeleton::Known(size_to, _)) = (from.kind(), sk_to)
|
||||
&& size_to == Pointer(dl.instruction_address_space).size(&tcx)
|
||||
{
|
||||
struct_span_code_err!(self.dcx(), span, E0591, "can't transmute zero-sized type")
|
||||
.with_note(format!("source type: {from}"))
|
||||
.with_note(format!("target type: {to}"))
|
||||
.with_help("cast with `as` to a pointer instead")
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to display a sensible error with as much information as possible.
|
||||
let skeleton_string = |ty: Ty<'tcx>, sk: Result<_, &_>| match sk {
|
||||
Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"),
|
||||
Ok(SizeSkeleton::Known(size, _)) => {
|
||||
if let Some(v) = u128::from(size.bytes()).checked_mul(8) {
|
||||
format!("{v} bits")
|
||||
} else {
|
||||
// `u128` should definitely be able to hold the size of different architectures
|
||||
// larger sizes should be reported as error `are too big for the target architecture`
|
||||
// otherwise we have a bug somewhere
|
||||
bug!("{:?} overflow for u128", size)
|
||||
}
|
||||
}
|
||||
Ok(SizeSkeleton::Generic(size)) => {
|
||||
if let Some(size) =
|
||||
self.try_structurally_resolve_const(span, size).try_to_target_usize(tcx)
|
||||
{
|
||||
format!("{size} bytes")
|
||||
} else {
|
||||
format!("generic size {size}")
|
||||
}
|
||||
}
|
||||
Err(LayoutError::TooGeneric(bad)) => {
|
||||
if *bad == ty {
|
||||
"this type does not have a fixed size".to_owned()
|
||||
} else {
|
||||
format!("size can vary because of {bad}")
|
||||
}
|
||||
}
|
||||
Err(err) => err.to_string(),
|
||||
};
|
||||
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0512,
|
||||
"cannot transmute between types of different sizes, \
|
||||
or dependently-sized types"
|
||||
);
|
||||
if from == to {
|
||||
err.note(format!("`{from}` does not have a fixed size"));
|
||||
err.emit();
|
||||
} else {
|
||||
err.note(format!("source type: `{}` ({})", from, skeleton_string(from, sk_from)))
|
||||
.note(format!("target type: `{}` ({})", to, skeleton_string(to, sk_to)));
|
||||
if let Err(LayoutError::ReferencesError(_)) = sk_from {
|
||||
err.delay_as_bug();
|
||||
} else if let Err(LayoutError::ReferencesError(_)) = sk_to {
|
||||
err.delay_as_bug();
|
||||
} else {
|
||||
err.emit();
|
||||
}
|
||||
// Special-case transmuting from `typeof(function)` and
|
||||
// `Option<typeof(function)>` to present a clearer error.
|
||||
let from = unpack_option_like(tcx, from);
|
||||
if let (&ty::FnDef(..), SizeSkeleton::Known(size_to, _)) = (from.kind(), sk_to)
|
||||
&& size_to == Pointer(dl.instruction_address_space).size(&tcx)
|
||||
{
|
||||
struct_span_code_err!(tcx.sess.dcx(), span, E0591, "can't transmute zero-sized type")
|
||||
.with_note(format!("source type: {from}"))
|
||||
.with_note(format!("target type: {to}"))
|
||||
.with_help("cast with `as` to a pointer instead")
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to display a sensible error with as much information as possible.
|
||||
let skeleton_string = |ty: Ty<'tcx>, sk: Result<_, &_>| match sk {
|
||||
Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"),
|
||||
Ok(SizeSkeleton::Known(size, _)) => {
|
||||
if let Some(v) = u128::from(size.bytes()).checked_mul(8) {
|
||||
format!("{v} bits")
|
||||
} else {
|
||||
// `u128` should definitely be able to hold the size of different architectures
|
||||
// larger sizes should be reported as error `are too big for the target architecture`
|
||||
// otherwise we have a bug somewhere
|
||||
bug!("{:?} overflow for u128", size)
|
||||
}
|
||||
}
|
||||
Ok(SizeSkeleton::Generic(size)) => {
|
||||
format!("generic size {size}")
|
||||
}
|
||||
Err(LayoutError::TooGeneric(bad)) => {
|
||||
if *bad == ty {
|
||||
"this type does not have a fixed size".to_owned()
|
||||
} else {
|
||||
format!("size can vary because of {bad}")
|
||||
}
|
||||
}
|
||||
Err(err) => err.to_string(),
|
||||
};
|
||||
|
||||
let mut err = struct_span_code_err!(
|
||||
tcx.sess.dcx(),
|
||||
span,
|
||||
E0512,
|
||||
"cannot transmute between types of different sizes, or dependently-sized types"
|
||||
);
|
||||
if from == to {
|
||||
err.note(format!("`{from}` does not have a fixed size"));
|
||||
err.emit();
|
||||
} else {
|
||||
err.note(format!("source type: `{}` ({})", from, skeleton_string(from, sk_from)));
|
||||
err.note(format!("target type: `{}` ({})", to, skeleton_string(to, sk_to)));
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn check_transmutes(tcx: TyCtxt<'_>, owner: LocalDefId) {
|
||||
assert!(!tcx.is_typeck_child(owner.to_def_id()));
|
||||
let typeck_results = tcx.typeck(owner);
|
||||
let None = typeck_results.tainted_by_errors else { return };
|
||||
|
||||
let typing_env = ty::TypingEnv::post_analysis(tcx, owner);
|
||||
for &(from, to, hir_id) in &typeck_results.transmutes_to_check {
|
||||
check_transmute(tcx, typing_env, from, to, hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,10 +251,6 @@ fn typeck_with_inspect<'tcx>(
|
||||
fcx.report_ambiguity_errors();
|
||||
}
|
||||
|
||||
if let None = fcx.infcx.tainted_by_errors() {
|
||||
fcx.check_transmutes();
|
||||
}
|
||||
|
||||
fcx.check_asms();
|
||||
|
||||
let typeck_results = fcx.resolve_type_vars_in_body(body);
|
||||
@@ -555,6 +551,7 @@ pub fn provide(providers: &mut Providers) {
|
||||
method_autoderef_steps: method::probe::method_autoderef_steps,
|
||||
typeck,
|
||||
used_trait_imports,
|
||||
check_transmutes: intrinsicck::check_transmutes,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ pub(crate) fn resolve_type_vars_in_body(
|
||||
wbcx.visit_user_provided_tys();
|
||||
wbcx.visit_user_provided_sigs();
|
||||
wbcx.visit_coroutine_interior();
|
||||
wbcx.visit_transmutes();
|
||||
wbcx.visit_offset_of_container_types();
|
||||
|
||||
wbcx.typeck_results.rvalue_scopes =
|
||||
@@ -532,6 +533,18 @@ fn visit_coroutine_interior(&mut self) {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_transmutes(&mut self) {
|
||||
let tcx = self.tcx();
|
||||
let fcx_typeck_results = self.fcx.typeck_results.borrow();
|
||||
assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
|
||||
for &(from, to, hir_id) in self.fcx.deferred_transmute_checks.borrow().iter() {
|
||||
let span = tcx.hir_span(hir_id);
|
||||
let from = self.resolve(from, &span);
|
||||
let to = self.resolve(to, &span);
|
||||
self.typeck_results.transmutes_to_check.push((from, to, hir_id));
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn visit_opaque_types(&mut self) {
|
||||
let tcx = self.tcx();
|
||||
|
||||
@@ -1080,7 +1080,8 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
||||
if !tcx.is_typeck_child(def_id.to_def_id()) {
|
||||
// Child unsafety and borrowck happens together with the parent
|
||||
tcx.ensure_ok().check_unsafety(def_id);
|
||||
tcx.ensure_ok().mir_borrowck(def_id)
|
||||
tcx.ensure_ok().mir_borrowck(def_id);
|
||||
tcx.ensure_ok().check_transmutes(def_id);
|
||||
}
|
||||
tcx.ensure_ok().has_ffi_unwind_calls(def_id);
|
||||
|
||||
|
||||
@@ -1115,6 +1115,11 @@
|
||||
desc { |tcx| "collecting all inherent impls for `{:?}`", key }
|
||||
}
|
||||
|
||||
/// Unsafety-check this `LocalDefId`.
|
||||
query check_transmutes(key: LocalDefId) {
|
||||
desc { |tcx| "check transmute calls inside `{}`", tcx.def_path_str(key) }
|
||||
}
|
||||
|
||||
/// Unsafety-check this `LocalDefId`.
|
||||
query check_unsafety(key: LocalDefId) {
|
||||
desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key) }
|
||||
|
||||
@@ -210,6 +210,11 @@ pub struct TypeckResults<'tcx> {
|
||||
/// on closure size.
|
||||
pub closure_size_eval: LocalDefIdMap<ClosureSizeProfileData<'tcx>>,
|
||||
|
||||
/// Stores the types involved in calls to `transmute` intrinsic. These are meant to be checked
|
||||
/// outside of typeck and borrowck to avoid cycles with opaque types and coroutine layout
|
||||
/// computation.
|
||||
pub transmutes_to_check: Vec<(Ty<'tcx>, Ty<'tcx>, HirId)>,
|
||||
|
||||
/// Container types and field indices of `offset_of!` expressions
|
||||
offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)>,
|
||||
}
|
||||
@@ -241,6 +246,7 @@ pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
|
||||
rvalue_scopes: Default::default(),
|
||||
coroutine_stalled_predicates: Default::default(),
|
||||
closure_size_eval: Default::default(),
|
||||
transmutes_to_check: Default::default(),
|
||||
offset_of_data: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,14 @@ LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
|
||||
|
|
||||
= note: the length of array `[[u32; H]; W]` must be type `usize`
|
||||
|
||||
error: the constant `W` is not of type `usize`
|
||||
--> $DIR/transmute-fail.rs:19:9
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
|
||||
|
|
||||
= note: the length of array `[[u32; H]; W]` must be type `usize`
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:11:9
|
||||
|
|
||||
@@ -15,14 +23,6 @@ LL | std::mem::transmute(v)
|
||||
= note: source type: `[[u32; H + 1]; W]` (size can vary because of [u32; H + 1])
|
||||
= note: target type: `[[u32; W + 1]; H]` (size can vary because of [u32; W + 1])
|
||||
|
||||
error: the constant `W` is not of type `usize`
|
||||
--> $DIR/transmute-fail.rs:19:9
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
|
||||
|
|
||||
= note: the length of array `[[u32; H]; W]` must be type `usize`
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:26:9
|
||||
|
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
//@ normalize-stderr-64bit: "8 byte" -> "word size"
|
||||
//@ normalize-stderr-32bit: "4 byte" -> "word size"
|
||||
//@ normalize-stderr-64bit: "64 bits" -> "word size"
|
||||
//@ normalize-stderr-32bit: "32 bits" -> "word size"
|
||||
//@ normalize-stderr-64bit: "16 byte" -> "2 * word size"
|
||||
//@ normalize-stderr-32bit: "8 byte" -> "2 * word size"
|
||||
//@ normalize-stderr-64bit: "128 bits" -> "2 * word size"
|
||||
//@ normalize-stderr-32bit: "64 bits" -> "2 * word size"
|
||||
|
||||
@@ -10,4 +14,5 @@ fn main() {
|
||||
}
|
||||
|
||||
const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
|
||||
//~^ ERROR cannot transmute between types of different sizes
|
||||
//~^ ERROR transmuting from
|
||||
//~| ERROR cannot transmute between types of different sizes
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
error[E0080]: transmuting from 8-byte type to 16-byte type: `usize` -> `&[u8]`
|
||||
--> $DIR/transmute-size-mismatch-before-typeck.rs:16:29
|
||||
|
|
||||
LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `ZST` failed here
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-size-mismatch-before-typeck.rs:12:29
|
||||
--> $DIR/transmute-size-mismatch-before-typeck.rs:16:29
|
||||
|
|
||||
LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
@@ -7,6 +13,7 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
|
||||
= note: source type: `usize` (word size)
|
||||
= note: target type: `&[u8]` (2 * word size)
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0512`.
|
||||
Some errors have detailed explanations: E0080, E0512.
|
||||
For more information about an error, try `rustc --explain E0080`.
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
// This causes a query cycle due to using `TypingEnv::PostAnalysis`,
|
||||
// Used to cause a query cycle due to using `TypingEnv::PostAnalysis`,
|
||||
// in #119821 const eval was changed to always use this mode.
|
||||
//
|
||||
// See that PR for more details.
|
||||
//@ check-pass
|
||||
|
||||
use std::mem::transmute;
|
||||
|
||||
fn foo() -> impl Sized {
|
||||
//~^ ERROR cycle detected when computing type of
|
||||
//~| WARN function cannot return without recursing
|
||||
//~^ WARN function cannot return without recursing
|
||||
unsafe {
|
||||
transmute::<_, u8>(foo());
|
||||
}
|
||||
|
||||
@@ -1,56 +1,5 @@
|
||||
error[E0391]: cycle detected when computing type of `foo::{opaque#0}`
|
||||
--> $DIR/in-defining-scope.rs:6:13
|
||||
|
|
||||
LL | fn foo() -> impl Sized {
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires computing type of opaque `foo::{opaque#0}`...
|
||||
--> $DIR/in-defining-scope.rs:6:13
|
||||
|
|
||||
LL | fn foo() -> impl Sized {
|
||||
| ^^^^^^^^^^
|
||||
note: ...which requires borrow-checking `foo`...
|
||||
--> $DIR/in-defining-scope.rs:6:1
|
||||
|
|
||||
LL | fn foo() -> impl Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires promoting constants in MIR for `foo`...
|
||||
--> $DIR/in-defining-scope.rs:6:1
|
||||
|
|
||||
LL | fn foo() -> impl Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires checking if `foo` contains FFI-unwind calls...
|
||||
--> $DIR/in-defining-scope.rs:6:1
|
||||
|
|
||||
LL | fn foo() -> impl Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires building MIR for `foo`...
|
||||
--> $DIR/in-defining-scope.rs:6:1
|
||||
|
|
||||
LL | fn foo() -> impl Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires match-checking `foo`...
|
||||
--> $DIR/in-defining-scope.rs:6:1
|
||||
|
|
||||
LL | fn foo() -> impl Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires type-checking `foo`...
|
||||
--> $DIR/in-defining-scope.rs:6:1
|
||||
|
|
||||
LL | fn foo() -> impl Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...which requires computing layout of `foo::{opaque#0}`...
|
||||
= note: ...which requires normalizing `foo::{opaque#0}`...
|
||||
= note: ...which again requires computing type of `foo::{opaque#0}`, completing the cycle
|
||||
note: cycle used when checking that `foo::{opaque#0}` is well-formed
|
||||
--> $DIR/in-defining-scope.rs:6:13
|
||||
|
|
||||
LL | fn foo() -> impl Sized {
|
||||
| ^^^^^^^^^^
|
||||
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||
|
||||
warning: function cannot return without recursing
|
||||
--> $DIR/in-defining-scope.rs:6:1
|
||||
--> $DIR/in-defining-scope.rs:8:1
|
||||
|
|
||||
LL | fn foo() -> impl Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||
@@ -61,6 +10,5 @@ LL | transmute::<_, u8>(foo());
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
= note: `#[warn(unconditional_recursion)]` on by default
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
warning: 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
||||
|
||||
@@ -8,7 +8,9 @@ struct S {
|
||||
}
|
||||
|
||||
const C: S = unsafe { std::mem::transmute(()) };
|
||||
//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
|
||||
//~^ ERROR the type `S` has an unknown layout
|
||||
//~| ERROR cannot transmute between types of different sizes, or dependently-sized types
|
||||
|
||||
const _: [(); {
|
||||
C;
|
||||
0
|
||||
|
||||
@@ -16,6 +16,12 @@ help: the `Box` type always has a statically known size and allocates its conten
|
||||
LL | a: Box<[u8]>,
|
||||
| ++++ +
|
||||
|
||||
error[E0080]: the type `S` has an unknown layout
|
||||
--> $DIR/base-layout-is-sized-ice-123078.rs:10:1
|
||||
|
|
||||
LL | const C: S = unsafe { std::mem::transmute(()) };
|
||||
| ^^^^^^^^^^ evaluation of `C` failed here
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/base-layout-is-sized-ice-123078.rs:10:23
|
||||
|
|
||||
@@ -25,7 +31,7 @@ LL | const C: S = unsafe { std::mem::transmute(()) };
|
||||
= note: source type: `()` (0 bits)
|
||||
= note: target type: `S` (the type `S` has an unknown layout)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0512.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
Some errors have detailed explanations: E0080, E0277, E0512.
|
||||
For more information about an error, try `rustc --explain E0080`.
|
||||
|
||||
@@ -49,8 +49,8 @@ fn check<T: Project1>() {
|
||||
unsafe {
|
||||
std::mem::transmute::<_, ()>(opaque::<T>().get());
|
||||
//~^ ERROR: cannot transmute
|
||||
//~| NOTE: (unable to determine layout for `<impl Project2 as Project2>::Assoc2` because `<impl Project2 as Project2>::Assoc2` cannot be normalized)
|
||||
//~| NOTE: (0 bits)
|
||||
//~| NOTE: source type: `{type error}` (the type has an unknown layout)
|
||||
//~| NOTE: target type: `()` (0 bits)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
|
||||
LL | std::mem::transmute::<_, ()>(opaque::<T>().get());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `<impl Project2 as Project2>::Assoc2` (unable to determine layout for `<impl Project2 as Project2>::Assoc2` because `<impl Project2 as Project2>::Assoc2` cannot be normalized)
|
||||
= note: source type: `{type error}` (the type has an unknown layout)
|
||||
= note: target type: `()` (0 bits)
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -5,4 +5,5 @@ trait Trait<T> {}
|
||||
|
||||
fn main() {
|
||||
let x: Bar = unsafe { std::mem::transmute(()) };
|
||||
//~^ ERROR cannot transmute between types of different size
|
||||
}
|
||||
|
||||
@@ -9,6 +9,16 @@ help: you might be missing a type parameter
|
||||
LL | struct Bar<T>(Box<dyn Trait<T>>);
|
||||
| +++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-to-tail-with-err.rs:7:27
|
||||
|
|
||||
LL | let x: Bar = unsafe { std::mem::transmute(()) };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `()` (0 bits)
|
||||
= note: target type: `Bar` (the type has an unknown layout)
|
||||
|
||||
For more information about this error, try `rustc --explain E0412`.
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0412, E0512.
|
||||
For more information about an error, try `rustc --explain E0412`.
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
type Bug<T, U> = impl Fn(T) -> U + Copy;
|
||||
//~^ ERROR cycle detected when computing type of `Bug::{opaque#0}`
|
||||
|
||||
#[define_opaque(Bug)]
|
||||
const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
|
||||
//~^ ERROR item does not constrain `Bug::{opaque#0}`
|
||||
//~| ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
|
||||
#[define_opaque(Bug)]
|
||||
fn make_bug<T, U: From<T>>() -> Bug<T, U> {
|
||||
|
||||
@@ -1,56 +1,5 @@
|
||||
error[E0391]: cycle detected when computing type of `Bug::{opaque#0}`
|
||||
--> $DIR/issue-53092-2.rs:4:18
|
||||
|
|
||||
LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires computing type of opaque `Bug::{opaque#0}`...
|
||||
--> $DIR/issue-53092-2.rs:4:18
|
||||
|
|
||||
LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires borrow-checking `CONST_BUG`...
|
||||
--> $DIR/issue-53092-2.rs:8:1
|
||||
|
|
||||
LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires promoting constants in MIR for `CONST_BUG`...
|
||||
--> $DIR/issue-53092-2.rs:8:1
|
||||
|
|
||||
LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires const checking `CONST_BUG`...
|
||||
--> $DIR/issue-53092-2.rs:8:1
|
||||
|
|
||||
LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires building MIR for `CONST_BUG`...
|
||||
--> $DIR/issue-53092-2.rs:8:1
|
||||
|
|
||||
LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires match-checking `CONST_BUG`...
|
||||
--> $DIR/issue-53092-2.rs:8:1
|
||||
|
|
||||
LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires type-checking `CONST_BUG`...
|
||||
--> $DIR/issue-53092-2.rs:8:1
|
||||
|
|
||||
LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...which requires computing layout of `Bug<u8, ()>`...
|
||||
= note: ...which requires normalizing `Bug<u8, ()>`...
|
||||
= note: ...which again requires computing type of `Bug::{opaque#0}`, completing the cycle
|
||||
note: cycle used when checking that `Bug::{opaque#0}` is well-formed
|
||||
--> $DIR/issue-53092-2.rs:4:18
|
||||
|
|
||||
LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||
|
||||
error: item does not constrain `Bug::{opaque#0}`
|
||||
--> $DIR/issue-53092-2.rs:8:7
|
||||
--> $DIR/issue-53092-2.rs:7:7
|
||||
|
|
||||
LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
|
||||
| ^^^^^^^^^
|
||||
@@ -62,6 +11,15 @@ note: this opaque type is supposed to be constrained
|
||||
LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/issue-53092-2.rs:7:41
|
||||
|
|
||||
LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `{closure@$DIR/issue-53092-2.rs:7:61: 7:68}` (0 bits)
|
||||
= note: target type: `{type error}` (the type has an unknown layout)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
||||
For more information about this error, try `rustc --explain E0512`.
|
||||
|
||||
@@ -15,5 +15,6 @@ pub fn bar(x: Foo) -> Foo {
|
||||
fn main() {
|
||||
unsafe {
|
||||
let _: Foo = std::mem::transmute(0u8);
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,5 +11,15 @@ note: this opaque type is supposed to be constrained
|
||||
LL | pub type Foo = impl Copy;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/no_inferrable_concrete_type.rs:17:22
|
||||
|
|
||||
LL | let _: Foo = std::mem::transmute(0u8);
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `u8` (8 bits)
|
||||
= note: target type: `{type error}` (the type has an unknown layout)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0512`.
|
||||
|
||||
@@ -13,14 +13,18 @@
|
||||
fn main() {
|
||||
//~? ERROR: only non-overlapping pattern type ranges are allowed at present
|
||||
let not_adjacent: pattern_type!(i8 is -127..0 | 1..) = unsafe { std::mem::transmute(0) };
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
|
||||
//~? ERROR: one pattern needs to end at `i8::MAX`, but was 29 instead
|
||||
let not_wrapping: pattern_type!(i8 is 10..20 | 20..30) = unsafe { std::mem::transmute(0) };
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
|
||||
//~? ERROR: only signed integer base types are allowed for or-pattern pattern types
|
||||
let not_signed: pattern_type!(u8 is 10.. | 0..5) = unsafe { std::mem::transmute(0) };
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
|
||||
//~? ERROR: allowed are two range patterns that are directly connected
|
||||
let not_simple_enough_for_mvp: pattern_type!(i8 is ..0 | 1..10 | 10..) =
|
||||
unsafe { std::mem::transmute(0) };
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
|
||||
@@ -1,10 +1,47 @@
|
||||
error: only non-overlapping pattern type ranges are allowed at present
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/or_patterns_invalid.rs:15:69
|
||||
|
|
||||
LL | let not_adjacent: pattern_type!(i8 is -127..0 | 1..) = unsafe { std::mem::transmute(0) };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `i32` (32 bits)
|
||||
= note: target type: `(i8) is (-127..=-1 | 1..)` (the type has an unknown layout)
|
||||
|
||||
error: one pattern needs to end at `i8::MAX`, but was 29 instead
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/or_patterns_invalid.rs:19:71
|
||||
|
|
||||
LL | let not_wrapping: pattern_type!(i8 is 10..20 | 20..30) = unsafe { std::mem::transmute(0) };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `i32` (32 bits)
|
||||
= note: target type: `(i8) is (10..=19 | 20..=29)` (the type has an unknown layout)
|
||||
|
||||
error: only signed integer base types are allowed for or-pattern pattern types at present
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/or_patterns_invalid.rs:23:65
|
||||
|
|
||||
LL | let not_signed: pattern_type!(u8 is 10.. | 0..5) = unsafe { std::mem::transmute(0) };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `i32` (32 bits)
|
||||
= note: target type: `(u8) is (10.. | 0..=4)` (the type has an unknown layout)
|
||||
|
||||
error: the only or-pattern types allowed are two range patterns that are directly connected at their overflow site
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/or_patterns_invalid.rs:28:18
|
||||
|
|
||||
LL | unsafe { std::mem::transmute(0) };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `i32` (32 bits)
|
||||
= note: target type: `(i8) is (i8::MIN..=-1 | 1..=9 | 10..)` (the type has an unknown layout)
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0512`.
|
||||
|
||||
Reference in New Issue
Block a user